WilliamNHarvey
WilliamNHarvey

Reputation: 2485

Delegate an association

I have a model A that has many of another model B, which has_many of a third model C, and want to delegate A from B to C. For example:

class House < ApplicationRecord
  has_many :pets
end

class Pet < ApplicationRecord
  belongs_to :house
  has_many :toys
  delegate :house, to: :toys
end

class Toy < ApplicationRecord
  belongs_to :pet
end

> toy.house

As it stands, I have to use toy.pet.house

Upvotes: 2

Views: 1721

Answers (2)

Wizard of Ogz
Wizard of Ogz

Reputation: 12643

You can use the :through option on your ActiveRecord associations to accomplish what you want. Configure your models as follows:

class House < ApplicationRecord
  has_many :pets
  has_many :toys, through: :pets
end

class Pet < ApplicationRecord
  belongs_to :house
  has_many :toys
end

class Toy < ApplicationRecord
  belongs_to :pet
  has_one :house, through: :pet
end

Here is a link to the official guide for the :through option on has_many and has_one associations.

Upvotes: 0

jvillian
jvillian

Reputation: 20253

Try

class Toy < ApplicationRecord
  belongs_to :pet 
  delegate :house, to: :pet 
end

And remove

delegate :house, to: :toys 

from Pet.

There are at least two problems with:

class Pet < ApplicationRecord
  belongs_to :house
  has_many :toys
  delegate :house, to: :toys
end

First, an instance of Toy doesn't respond to house, so you can't delegate :house, to: :toys. Second, even if an instance of Toy did respond to house, you wouldn't be able to call that instance method on a collection, which is what toys is. So, that's busted all over the place.

Pet, however, does respond to house. And, Toy belongs_to :pet. So, you do Toy delegate :house, to: :pet. And Bob's your uncle!

Upvotes: 4

Related Questions