This seems like a simple question but it's a little puzzle to me:
class Parent
has_many children
...
end
class Child
belongs_to parent
end
p = Parent.find(111)
c = Child.all.where(parent: p)
Why doesn't that work, and how come I have to do:
c = Child.all.where(parent_id: p.id)
A more complicated case has me creating a Relation based on more complicated logic, e.g.
c = Child.where(age: 32, city: "boston")
c.where(parent: p) # wouldn't work
Wait I need to have a many to many to illustrate this:
class Teacher
has_many :students, through: ClassRoom
has_many :classes
end
class ClassRoom
belongs_to :teacher
belongs_to :child
end
class Child
has_many :classes
has_many :teachers, through: ClassRoom
end
t = Teacher.first
c = Child.where(age: 5, city: "boston")
c.where(teacher: t) # wouldn't work
c.where(teacher_id: t.id) # would work but is a little ugly
Thanks for all the great info! Is there a better (or 'correct') way to do the last line form the above example?
c.where(teacher_id: t.id) # would work but is a little ugly
You can do:
p = Parent.find(111)
all_children = p.children
The key parent doesn't work because it using that as the column name.
Addendum:
So for this use case you should use:
class ClassRoom < ActiveRecord::Base
belongs_to :teacher
belongs_to :child
end
class Teacher < ActiveRecord::Base
has_many :children, through: ClassRoom
has_many :class_rooms
end
class Child < ActiveRecord::Base
has_many :class_rooms
has_many :teachers, through: ClassRoom
end
t = Teacher.first
teachers_children_from_boston_and_32 = t.children.where(age: 32, city: "boston")
Firstly you can't use Class because it is an object already. The next problem was that you renamed children to students, which you can do but then need to do some other options on the has_many call.
Check out joining tables here: http://guides.rubyonrails.org/active_record_querying.html#joining-tables
And Assoications here (your use case matches this example perfectly): http://guides.rubyonrails.org/association_basics.html#the-has_many-through-association
Also remember with rails 3 all where clauses are just critera. Critera is used to find your matches and can be added together to narrow your results. IE
where_clause_one = Teacher.where(age: 50)
where_clause_two = Teacher.where(city: "San Francisco")
merged_where_clauses = where_clause_one.merge(where_clause_two)
merged_where_clauses.each do |teacher|
# teachers that are both 50 and from san francisco
...
end
.all
converts an ActiveRecord::Relation object to an array. Arrays do not respond to the where
method. You should use
c = Child.where(parent_id: p.id).all
You have to use _id in this case because where
will directly translate the given hash into SQL. SQL does not know what parent
is, it only knows what parent_id
is. That being said, the best way to do this would be
c = p.children
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With