I have my models setup like so:
class User < ActiveRecord::Base
has_many :posts, :foreign_key => 'author_id'
end
class Post < ActiveRecord::Base
belongs_to :author, :class_name => 'User'
end
Assuming:
p = Post.first # just any post instance
a = User.first # any user instance
Now this piece of code is acting very weird
p.author = a
After setting the author, the attribute author_id of the post should be set to the id of the user. But this isn’t happening.
I tried using models with belongs_to that does not have the class_name parameter and everything works as expected.
Now, one more thing that makes it weirder is that when I change the association to belongs_to :author, :class_name => 'User', :foreign_key => 'author_id', it surprisingly works.
Is this a bug in Rails 3.0.9? Shouldn’t the foreign key parameter be unnecessary because as the docs say, its default value is the name of the association appended with _id.
Also note that even without :foreign_key => 'author_id', everything else regarding the association works as expected. (Like fetching the associated model) The only thing not working is the setter method not setting the foreign key.
I know I could just do p.author_id = a.id or just add :foreign_key params to all my associations with class_name, but I prefer the more elegant syntax of p.author = a
After reading through lots of Rails code and tracing here’s what I found:
This bug exists because of the gem
composite_primary_keyswhich overrode the default railsreflection.rb.I will have to check how they implemented the
primary_key_nameandderive_primary_key_namemethods.It was quite a bit of time wasted on this silly bug, but at least I got to learn a lot about ActiveRecord’s internals.