I've got models A and B; A has_many B, and B belongs_to A. So far, so good—except, I specify that B doesn't have a primary key. I don't plan to ever modify or delete individual B rows, and I expect to have several million to billion of them, so omitting the primary key will be really handy, space-wise.
The migration to create B's table looked like this:
class CreateBs < ActiveRecord::Migration
def change
create_table :bs, {:id => false} do |t|
# … rest of fields …
end
end
end
Unfortunately, ActiveRecord disagrees; trying to create an A (that's right!) results in:
1.9.3p194 :001 > A.create!
(0.3ms) BEGIN
(0.1ms) ROLLBACK
ActiveRecord::UnknownPrimaryKey: ActiveRecord::UnknownPrimaryKey
from /Users/annelicuss/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/reflection.rb:366:in `primary_key'
from /Users/annelicuss/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/reflection.rb:216:in `association_primary_key'
from /Users/annelicuss/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/associations/has_many_association.rb:104:in `foreign_key_present?'
from /Users/annelicuss/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/associations/association.rb:165:in `find_target?'
from /Users/annelicuss/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/associations/collection_association.rb:332:in `load_target'
from /Users/annelicuss/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/associations/collection_proxy.rb:44:in `load_target'
…
If you catch the exception, its message
states:
"Unknown primary key for table bs in model B."
(which would be because B has no primary key.)
I'd like to not have this issue! Is there any way?
The culprit turned out to be a detail missing from the question—of course—and missing from my working memory:
class A < ActiveRecord::Base
has_many :bs
validates :bs, :presence => true
end
Though I thought nothing about it at the time, there was—among many other validations—a validation of the presence of bs
. If you squint really hard at the full backtrace—which I was "helpful" enough to truncate in my original question, you see:
ActiveRecord::UnknownPrimaryKey: ActiveRecord::UnknownPrimaryKey
from /Users/annelicuss/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/reflection.rb:366:in `primary_key'
from /Users/annelicuss/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/reflection.rb:216:in `association_primary_key'
from /Users/annelicuss/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/associations/has_many_association.rb:104:in `foreign_key_present?'
from /Users/annelicuss/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/associations/association.rb:165:in `find_target?'
from /Users/annelicuss/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/associations/collection_association.rb:332:in `load_target'
from /Users/annelicuss/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/associations/collection_proxy.rb:44:in `load_target'
from /Users/annelicuss/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/associations/collection_proxy.rb:87:in `method_missing'
from /Users/annelicuss/.rvm/gems/ruby-1.9.3-p194/gems/activemodel-3.2.8/lib/active_model/errors.rb:255:in `block in add_on_blank'
from /Users/annelicuss/.rvm/gems/ruby-1.9.3-p194/gems/activemodel-3.2.8/lib/active_model/errors.rb:253:in `each'
from /Users/annelicuss/.rvm/gems/ruby-1.9.3-p194/gems/activemodel-3.2.8/lib/active_model/errors.rb:253:in `add_on_blank'
from /Users/annelicuss/.rvm/gems/ruby-1.9.3-p194/gems/activemodel-3.2.8/lib/active_model/validations/presence.rb:8:in `validate'
-------------------------------------------------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^
The error occurs in active_model/validations/presence.rb
! Removing this constraint is enough to get us going. It can't find the target of the validation, as it tries to use the primary key to do so, and hence fails bad.
Hmm, that is very odd. For some reason, I cannot replicate the problem on my end given the information you posted. I created a new project, created an A model followed by a B model that references A, and ran the migrations. My B table does not have a primary key, and only a foreign key to A, as expected.
The only thing I can suggest is the following
Write your A model like this:
class A < ActiveRecord::Base
has_many :b, :primary_key=>:myPrimaryKeyFunction # name this function whatever you want, other than :id of course
end
Then, in the B model, simply create the corresponding "myPrimaryKeyFunction" function.
Other than that, I'm not sure what else to suggest. What version of rails and which DB are you running?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With