2013-04-26 52 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