10

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.

James Chevalier
  • 10,604
  • 5
  • 48
  • 74
Rohit
  • 5,631
  • 4
  • 31
  • 59

2 Answers2

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
shingara
  • 46,608
  • 11
  • 99
  • 105
  • 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 part – Rohit Oct 05 '10 at 13:45
  • The first way is doing good and solves my problem. But please find some tweaks in the delegation mechanism and edit the answer. :D – Rohit Oct 05 '10 at 13:59
  • use delegate :model3s, :to => :model1 instead of delegate :model3s, :as => :model1. :D works for me – Rohit Oct 05 '10 at 14:04
  • You right. I need check the documentation befopre answer sometimes. – shingara Oct 05 '10 at 14:12
  • add :allow_nil => true to delegate method, because if calls delegate on a nil object ruby raises an error – Orlando Jun 08 '12 at 17:29
  • 5
    As an update, since Rails 4.2 you can now perform `has_many` and `has_one` through a `belongs_to` relationship – Francesco Belladonna Dec 14 '15 at 02:43
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.

Jason Kenney
  • 101
  • 1
  • 4
  • 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. – Jordan Brough Apr 21 '14 at 21:15