4

这似乎是一个简单的问题,但对我来说有点困惑:

class Parent
  has_many children
  ...
end

class Child
  belongs_to parent
end

p = Parent.find(111)
c = Child.all.where(parent: p)

为什么这不起作用,我为什么要这样做:

c = Child.all.where(parent_id: p.id)

附录

一个更复杂的案例让我根据更复杂的逻辑创建一个关系,例如

c = Child.where(age: 32, city: "boston")
c.where(parent: p) # wouldn't work

附录#2

等等,我需要多对多来说明这一点:

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

附录 3

谢谢你提供这些很棒的信息!有没有更好(或“正确”)的方法来完成上述示例的最后一行?

c.where(teacher_id: t.id) # would work but is a little ugly
4

3 回答 3

3

你可以做:

p = Parent.find(111)
all_children = p.children

关键父级不起作用,因为它使用它作为列名。

附录:

因此,对于这个用例,您应该使用:

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")

首先你不能使用 Class 因为它已经是一个对象。下一个问题是您将孩子重命名为学生,您可以这样做,但需要在 has_many 调用上执行一些其他选项。

在此处查看加入表:http: //guides.rubyonrails.org/active_record_querying.html#joining-tables

这里的关联(您的用例与此示例完美匹配): http: //guides.rubyonrails.org/association_basics.html#the-has_many-through-association

还要记住 rails 3 所有 where 子句都是标准。Critera 用于查找您的匹配项,并且可以添加在一起以缩小结果范围。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
于 2013-04-26T20:11:25.793 回答
3

.all将 ActiveRecord::Relation 对象转换为数组。数组不响应该where方法。你应该使用

c = Child.where(parent_id: p.id).all

在这种情况下,您必须使用 _id,因为where它将直接将给定的哈希转换为 SQL。SQL 不知道是什么parent,它只知道是什么parent_id。话虽如此,最好的方法是

c = p.children
于 2013-04-26T20:11:27.873 回答
2

“Active Record 对象不直接指定它们的属性,而是从它们链接的表定义中推断它们” - http://api.rubyonrails.org/files/activerecord/README_rdoc.html

此关联由特定的数据库列链接,因此您必须使用这些属性来引用关系。

您还可以通过使用p.childrenwhich 将返回父子数组来简化此语句。

于 2013-04-26T20:16:25.377 回答