Model traversal in rails: from child to sibling's child
-
27-09-2019 - |
Question
I have the following model:
class Advisor < ActiveRecord::Base
belongs_to :course
end
class Course < ActiveRecord::Base
has_many :advisors
has_many :sessions
has_many :materials, :through=>:sessions
end
class Session < ActiveRecord::Base
belongs_to :course
has_many :materials
end
class Material < ActiveRecord::Base
belongs_to :session
end
I.e., every advisor teaches one course, every course has sessions, and every session has materials.
I want to traverse from an advisor to all the associated materials, i.e. something like: Advisor.first.materials
I tried to do:
class Advisor < ActiveRecord::Base
belongs_to :course
has_many :sessions, :through=>:course
has_many :materials, :through=>:sessions
end
But it didn't work as it treated sessions as a many-to-many table: Unknown column 'sessions.advisor_id' in 'where clause': SELECT 'material'.* FROM 'materials' INNER JOIN 'sessions' ON 'materials'.session_id = 'sessions'.id WHERE (('sessions'.advisor_id = 1))
I then tried to do:
class Advisor < ActiveRecord::Base
belongs_to :course
has_many :materials, :through=>:course
end
In an attempt to have the association use the "materials" association in the "Course" model, but received:
ActiveRecord::HasManyThroughSourceAssociationMacroError: Invalid source reflection on macro :has_many :through for has_many :materials, :through=>:sessions. Use :source to specify the source reflection.
Tried to use "sessions" as the source which was a nice try but made me receive only the sessions rather than the materials.
Any ideas if this is at all possible? I'm using Rails 2.3.8 (perhaps time to upgrade?)
Thanks! Amit
Solution
I want to traverse from an advisor to all the associated materials
Unless I'm missing something, using the associations specified in your first example, you can simply call materials
on the associated course
:
a = Advisor.first
materials = a.course.materials
OTHER TIPS
Using a has_many,through association for another has_many,:through relation will not work in rails
instead of creating a association you can just create a method to access all the materials by a Advisor
def materials sessions.collect(&:materials).flatten end
This will work, but you wont be able to chain find queries to this method. If you want to be able to chain find methods something like @advisor.materials.find..
Then inside this method use Material.find()
with appropriate conditions