2012-10-31 31 views
4

我想構建一個查詢來比較兩個對象,並且如果它們具有相同的id記錄不會被提取。我有這樣的:在每個循環中使用「或」語句的Rails 3.0

@channels.each do |channel| 
    unless @guide_channels.where(:id => channel.id).exists? 
    @dropdown_channels = @dropdown_channels.where(:id => channel.id) 
    end 
end 

這將創建查詢,但把一個和每一個它是不是我心目中值之間。我想要「或」運算符。是否有可以使用的'orwhere'函數?還是有更好的方法可以用一些比較函數來做到這一點?

+0

糾正我,如果我錯了'@dropdown_channels = @ dropdown_channels.where(:id => channel.id)'是否正確指派你分配/重新分配每個塊內的'dropdown_channels'是否正確糾正我如果我錯了 – Viren

+0

1)爲什麼使用Ruby的呢?看起來有些事要做AR查詢2)'x = x.method'通常是一個壞主意 – tokland

+0

我同意tokland,似乎它會更整潔/更高效的一個很好的連接查詢。你能否提供更多關於你的模型的信息以及你的目標是什麼? – Ant

回答

1

的要點是,一個AR::Relation對象的.where()方法添加的條件的一組條件在執行查詢時所然後AND -ed在一起。

你要做的是什麼樣NOT IN查詢:

# select all the ids for related @guide_channels 
# if @channels comes from a query (so it's a ActiveRecord::Relation): 
guide_ids = @guide_channels.where(:id => @channels.pluck(:id)).pluck(:id) 
# use .where(:id => @channels.map {|c| c.id}) instead if @channels is just an array 

# then use the list to exclude results from the following. 
@dropdown_channels = @dropdown_channels.where("id NOT IN (?)", guide_ids.to_a) 

第一個查詢將積累的所有ID爲在@guide_channels入口通道。第二個將使用第一個的結果從下拉結果中排除找到的渠道。

+0

智能我不知道你可以使用現有記錄中的。 – jonasulveseth

+0

在retroperspective我現在看到,這是做到這一點的方式。它將使用一個查詢獲取所有內容,從而創建最少的服務器負載 – jonasulveseth

0

這種奇怪的行爲是由於ActiveRecord對範圍的懶惰評估。 會發生什麼是該行

@dropdown_channels = @dropdown_channels.where(:id => channel.id) 

不將查詢發送到數據庫,直到你實際使用的@dropdown_channels值,當你做它加到所有條件成一個大的查詢,這就是爲什麼你AND之間的條件。

爲了強制ActiveRecord的躍躍欲試負載,可以使用的範圍無論是all範圍或first範圍,例如:

@dropdown_channels = @dropdown_channels.where(:id => channel.id).first 

這將迫使ActiveRecord的計算查詢現貨立即返回結果而不是積累懶惰評估的範圍。

另一種方法可以是累積所有這些channels_ids,並稍後在一個查詢中獲取它們,而不是對每個查詢進行查詢。這種方法與數據庫資源相關的成本效益更高。 爲了實現這一點:

dropdown_channels_ids = [] 
@channels.each do |channel| 
    unless @guide_channels.where(:id => channel.id).exists? 
    dropdown_channels_ids << channel.id 
    end 
end 
@dropdown_channels = @dropdown_channels.where(:id => dropdown_channels_ids) 
+0

最終我採用這種方法。使用「<<」似乎是最簡單的寫法。不過,我想念一個「或哪裏」選擇器,我已經在其他數據庫適配器 – jonasulveseth

+0

中使用我不同意,你正在使用這個!!!獲得N個查詢! '@ channels'中的每個元素都會產生一個額外的查詢(可能會佔用您的數據庫)。使用我的解決方案,您可以在任何情況下使用2次查詢來獲得結果。 – rewritten

+0

不,那裏的.where()不會執行查詢,直到我在表單中調用@ dropdown_channels.all,如果我們在這裏討論第二個例子? – jonasulveseth