dlu
dlu

Reputation: 791

Rails: How to associate a model with multiple parents

I have a Note model in my app that I'd like to share with several other models. Something like:

rails g model Note ...
rails g model ModelA ... note:references
rails g model ModelB ... note:references
rails g model ModelC ... note:references

So far so good, but I think I'd like to have a way -- from a Note -- to find the "parent" model. Note that the models are different "things" so I don't think I can do this in the Note model:

belongs_to :model_symbol_here

Since the Note could belong to one of several different models.

Conceptually it seems like I could do something like:

rails g model Note parent_id:integer parent_type:string ...

I think that would work, but I think it would be at the expense of losing the ability to leverage Rails' understanding of the relationships between models.

It seems like this is the sort of problem that would come up often enough that there would be a name for it as well as a "standard" solution. Is there a proper "Rails way" to do this?

Upvotes: 0

Views: 307

Answers (1)

thiaguerd
thiaguerd

Reputation: 847

Generate a model father

rails g model brand name:string

Seed model father

Brand.create name: 'Apple'
Brand.create name: 'Samsung'

Generate 2 model child

rails g model phone name:string brand:references
rails g model home_appliance name:string brand:references

Seed childrens

apple = Brand.first
Phone.create name: 'Iphone X', brand: apple
Phone.create name: 'Iphone 11', brand: apple
HomeAppliance.create name: 'Apple TV', brand: apple
HomeAppliance.create name: 'Homepod', brand: apple

samsung = Brand.last
Phone.create name: 'Galaxy A30', brand: samsung
Phone.create name: 'Galaxy Tab s6', brand: samsung
HomeAppliance.create name: 'Washing machine', brand: samsung
HomeAppliance.create name: 'Refrigerator', brand: samsung

In app/models/brand.rb

  has_many :phones
  has_many :home_appliances

Father finding son

apple.home_appliances
apple.phones

Son finding father

phone = Phone.last
phone.brand

Add a polymorphic example

Add a salesman that can sale a Phone and a HomeAppliance

rails g model salesman name:string

Relationship between salesman and product (HomeAppliance Phone) is M-M so we need create a third table for that

rails g model product_sold salesman:references product_id:integer product_type:string

In app/models/product_sold.rb add

belongs_to :product, polymorphic: true

So

will = Salesman.create name: 'Will'
will_first_sale = ProductSold.create salesman: will, product: Phone.first
will_second_sale = ProductSold.create salesman: will, product: HomeAppliance.last

To see all that Will sold add in app/models/salesman.rb

  has_many :product_sold

Now you cant run this

products = will.product_sold.map(&:product) 

In products you have a model Phone and HomeAppliance

Here you found another polymorphic examples

Upvotes: 3

Related Questions