2013-04-26 51 views
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 
+0

您可以添加一个范围http://guides.rubyonrails.org/active_record_querying.html#scopes或修补ActiveRecord,但最好的方式来做到这一点已经涵盖在这个页面上,我相信。 – earlonrails 2013-04-27 19:13:04

回答

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

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

退房这里连接表:http://guides.rubyonrails.org/active_record_querying.html#joining-tables

而且Assoications这里(你的使用情况这个例子完全匹配): http://guides.rubyonrails.org/association_basics.html#the-has_many-through-association

与导轨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 
+0

好点。其实我的真实情况稍微复杂一点。请检查我的附录顶部的问题... – pitosalas 2013-04-26 20:14:38

+0

伟大的信息!我不知道你可以做where_clause_one.merge(where_clause_two)。这与我所设想的一样。 Re:附录3:仍然是我原来的问题的底线是,当你想要做一个谈论特定关联记录的where子句时,你必须使用“.._ id”,因为where子句不知道关于协会? – pitosalas 2013-04-27 00:34:38

3

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

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

你必须在这种情况下使用_id因为where将直接给定的哈希转化为SQL。 SQL不知道什么是parent,它只知道parent_id是什么。话虽这么说,要做到这一点的最好的办法是

c = p.children 
2

“活动记录对象不直接指定它们的属性,而是从与他们联系表定义推断他们” - http://api.rubyonrails.org/files/activerecord/README_rdoc.html

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

您还可以通过使用p.children来简化此声明,它将返回父项子项的数组。

+0

但孩子'知道'它属于父母。看起来ActiveRecord很容易推断它是parent_id。我只是在问,因为这是每隔一段时间就会滑倒我的头脑,我明白为什么我会更容易记住它。 – pitosalas 2013-04-26 20:19:27