Created
March 8, 2012 06:48
-
-
Save avdi/1999258 to your computer and use it in GitHub Desktop.
Failure in two-level has_one...:through chain
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This is in a Rails 3.0 app | |
# Class names changed to protect the innocent | |
class NeckBone | |
has_one :back_bone | |
has_one :thigh_bone, :through => :back_bone | |
has_one :knee_bone, :through => :thigh_bone | |
delegate :walk_around, :to => :knee_bone | |
end | |
# assume back_bone exists and has a thigh_bone etc. | |
neck_bone = NeckBone.new(:back_bone => back_bone) | |
neck_bone.walk_around | |
# => NeckBone#walk_around delegated to knee_bone.walk_around, | |
# but knee_bone is nil: #<NeckBone id: nil, back_bone_id: 3, | |
# created_at: nil, updated_at: nil> | |
neck_bone.back_bone.thigh_bone.knee_bone.walk_around # => Works! |
Lately I've been avoiding
has_one :thing, :through => :other_thing
in favor of
delegate :thing, :to => :other_thing, :allow_nil => true
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Interesting.
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/associations/association.rb#L138
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/associations/association.rb#L165-167
Looks like... if it's not saved, it's the ActiveRecord association proxy. Essentially, I'm assuming you've assigned
back_bone
to an existing record. However, that doesn't automatically propagate through to loading theknee_bone
association target (which is delegated to). ActiveRecord will only 'load' an association target if the record is persisted or there is a foreign key present for the association on the record. So yeah, looks like it doesn't walk up through the chain of through associations looking for a loaded target to then walk back down through, although that would be cool!