Reputation: 30170
Given two model classes, Foo
and Bar
, I want Foo to have 3 references to separate instances of Bar using 3 different property names, with the foreign key on the Foo table. Bar will be managed separately and can belong to many instances of Foo. This somewhat explains it, obviously has_one is the wrong association to use (I think?):
Foo
has_one :prop_a, :class_name => "Bar"
has_one :prop_b, :class_name => "Bar"
has_one :prop_c, :class_name => "Bar"
Bar
There are 3 potential types of Bar, denoted by a bar_type
string field, each reference on Foo corresponds to one of these. e.g. Foo.prop_a
references an instance of Bar with bar_type
= 'type_a'. How do I create this type of association in Rails?
Upvotes: 0
Views: 501
Reputation: 1127
Would a polymorphic join handle the relationships? http://guides.rubyonrails.org/association_basics.html#polymorphic-associations
Upvotes: 0
Reputation: 3395
You are right that the wrong association is being used here.
In ActiveRecord, they model that has the foreign key always belongs_to
another model.
In this scenario class Foo actually belongs_to
those props
One way to specify this would be:
class Foo < ActiveRecord::Base
belongs_to :prop_a, :class_name => "Bar", :foreign_key => "prop_a_id"
belongs_to :prop_b, :class_name => "Bar", :foreign_key => "prob_b_id"
belongs_to :prop_c, :class_name => "Bar", :foreign_key => "prob_c_id"
end
What this means though, is that you must have a column on Foo titled "prop_a_id, prop_b_id
, and prop_c_id
" which can store the integer that is the primary key of the Bar table.
This solution, however, does not take care of the problem listed below the ActiveRecord associations. For the solution Will proposed above, you would need to take a look at Rails and Single Table Inheritance. If you google this you can find many resources on it. Personally, I recommend Agile Web Development with Rails. In the 3rd edition you can find it on page 377. Also there is a good beginner write-up on STI here
Good luck!
Upvotes: 1
Reputation: 8282
Why not use inheritance. You can create 3 classes which inherit from Bar. All you need to do is have a type column in your database.
class Foo
has_one :bara
has_one :barb
has_one :barc
end
class BarA < Foo
belongs_to :foo
end
class BarB < Foo
belongs_to :foo
end
class BarC < Foo
belongs_to :foo
end
Then you migration would need to have bara_id, barb_id and a barc_id column.
I have not tried this but it should work.
one = Foo.new
two = BarA.new
three = BarB.new
four = BarC.new
one.bara = two
one.barb = three
one.barc = four
one.save
one.bara.foo #=> one
one.bara.bara = BarA.new
one.bara.bara.foo #=> two
Upvotes: 1