Setting a :has_many :through association on a belongs_to association Ruby on Rails
Asked Answered
M

2

11

I have three models, each having the following associations:

class Model1 < ActiveRecord::Base
  has_many :model2s
  has_many :model3s
end

class Model2 < ActiveRecord::Base
  belongs_to :model1
  has_many :model3s, :through => :model1  # will this work? is there any way around this?
end

class Model3 < ActiveRecord::Base
  belongs_to :model1
  has_many :model2s, :through => :model1  # will this work? is there any way around this?
end

As you can see in the commented text, I have mentioned what I need.

Mocha answered 5/10, 2010 at 13:37 Comment(0)
A
13

You just create the method to access it

class Model2 < ActiveRecord::Base
  belongs_to :model1

  def model3s
    model1.model3s
  end
end

Or, you can delegate to model1 the model3s method

class Model2 < ActiveRecord::Base
  belongs_to :model1

  delegate :model3s, :to => :model1

end
Acrylic answered 5/10, 2010 at 13:42 Comment(6)
the delegation part gives me this error "Delegation needs a target. Supply an options hash with a :to key as the last argument (e.g. delegate :hello, :to => :greeter).". Let me try the method partMocha
The first way is doing good and solves my problem. But please find some tweaks in the delegation mechanism and edit the answer. :DMocha
use delegate :model3s, :to => :model1 instead of delegate :model3s, :as => :model1. :D works for meMocha
You right. I need check the documentation befopre answer sometimes.Acrylic
add :allow_nil => true to delegate method, because if calls delegate on a nil object ruby raises an errorHodometer
As an update, since Rails 4.2 you can now perform has_many and has_one through a belongs_to relationshipKovar
A
0

Why not try:

class Model1 < ActiveRecord::Base
  has_many :model2s
  has_many :model3s
end

class Model2 < ActiveRecord::Base
 belongs_to :model1
 has_many   :model3s, :primary_key => :model1_id,
                      :foreign_key => :model1_id

end

class Model3 < ActiveRecord::Base
  belongs_to :model1
  has_many   :model2s, :primary_key => :model1_id,  
                       :foreign_key => :model1_id
end

This will have active record join model2 and model3 by model1_id leaving model1 completely out of it and should be more efficient.

Agonic answered 3/5, 2012 at 21:34 Comment(1)
In the general case this would lose any conditions attached to the "has_many" definitions in Model1. e.g. if Model1 was defined with has_many :model2s, -> {where deleted: false} you wouldn't pick those conditions up without writing some extra code that was potentially fragile and/or verbose. Just something to be aware of.Timeout

© 2022 - 2024 — McMap. All rights reserved.