What's a good design for an intermediate triple-relation model?
-
08-07-2019 - |
Question
I'm new to Rails and don't grasp yet all the possibilities with associations. Here's my problem:
I have a couple of models like apple and lemon. Then there's the model 'relation' that holds triples of relations:
subject | relation | object
apple | is sweeter than | lemon
The migration for 'relations' is this:
create_table :relations do |t| t.references :subject, :polymorphic => true t.string :relation t.references :object, :polymorphic => true t.timestamps end
this should store relations like
subject_id = 1
subject_type = apple
relation = is sweeter than
object_id = 2
object_type = lemon
In reality I have more than just 2 models, so I thought I need to make the subject and object column model-agnostic by using the polymorphic option.
How would you set the associations in the model classes of apple, lemon and relation? Is the table design of relations good like this?
Thanks so much for your help!!
-Alex
Solution
Give the db schema you described, seems like it should be fairly straightforward:
class Relation < ActiveRecord::Base
belongs_to :object, :polymorphic => true
belongs_to :subject, :polymorphic => true
end
And your other classes would look like this
class Apple < ActiveRecord::Base
has_many :object_relations, :class_name => 'Relation', :as => :object
has_many :subject_relations, :class_name => 'Relation', :as => :subject
end
class Orange < ActiveRecord::Base
has_many :object_relations, :class_name => 'Relation', :as => :object
has_many :subject_relations, :class_name => 'Relation', :as => :subject
end
OTHER TIPS
Polymorphic IS PAIN:
Unless you need it badly, use somethimng like SingleTableInheritance:
class Fruit < ActiveRecord::Base
has_many :relations
has_many :related_objects, :through => :relation, :class_name => 'Fruit'
has_many :relating_subjects, :through => :relation, :class_name => 'Relation'
end
class Relation < ActiveRecord::Base
belongs_to :object, :class => 'Fruit'
belongs_to :subject, , :class => 'Fruit'
validate_presence_of :object_id
validate_presence_of :subject_id
validate_presence_of :relation
end
And then like:
class Apple < Fruit
...
end
I hope that helps, (I did not tested this code)