简体   繁体   中英

Rails has_one/belongs_to associations not working as expected

I'm in the process of teaching myself Rails and I'm stumped as to why an association isn't working correctly. I think I'm missing something pretty basic but I can't snuff out exactly what.

I have two classes -- Builds and Equipment. Builds are made of 2 pieces of equipment, deviously titled position_1 and position_2. Here's what my definitions look like:

class Build < ActiveRecord::Base
  has_one :position_1, :class_name => "Equipment"
  has_one :position_2, :class_name => "Equipment"
  attr_accessor :position_1, :position_2
end

and

class Equipment < ActiveRecord::Base
  belongs_to :build, :foreign_key => :position_1
  belongs_to :build, :foreign_key => :position_2
end

(Ignore for the moment that this could be handled by a relationship table to support any number of positions -- I'm basically trying to figure out how to have a class with two has_one relationships to another class.)

Now if I try and do something simple like this....

position_1 = Equipment.find(params[:build][:position_1])
position_2 = Equipment.find(params[:build][:position_2])

@build = Build.new

@build.position_1 = position_1
@build.position_2 = position_2

logger.debug("THE BUILD IS #{@build.inspect}")

I will have successfully created a build object with the equipment objects correctly assigned to the position_1 parameter, but the position_1 and position_2 fields of the build parameter are left nil.

logger.debug("THE EQUIPMENT IS #{@build.position_1}")
> EQUIPMENT IS #<Equipment:0x007fa0581705c0>

logger.debug("THE BUILD IS #{@build.inspect}")
> THE BUILD IS #<Build id: nil, position_1_id: nil, position_2_id: nil, created_at: "2013-05-27 18:00:32", updated_at: "2013-05-27 18:00:32">

What am I getting wrong here?

First, I would not include the associations as "attr_accessors" in the "parent" ActiveRecord. Rails creates the correct association field for Build for you.

When you create instances of the positions, like an instance of Equipment, the correct way to assign them to a new Build would be:

position_1 = Equipment.find(params[:build][:position_1])
position_2 = Equipment.find(params[:build][:position_2])

@build = Build.new

@build.position_1 << position_1
@build.position_2 << position_2

Here's good guide on Rails associations .

Figured it out -- I had misunderstood part of how Rails does associations -- what I really needed was...

class Equipment < ActiveRecord::Base
  has_many :builds, :foreign_key => :position_1
  has_many :builds, :foreign_key => :position_2
end

class Build < ActiveRecord::Base
  belongs_to :position_1, :class_name => "Equipment", :foreign_key => "position_1_id"
  belongs_to :position_2, :class_name => "Equipment", :foreign_key => "position_2_id"
end

With this in place everything works as I expected.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM