2010-07-20 87 views
50

我需要檢查,如果一個條件滿足的SQL語句:Ruby on Rails的3 HOWTO使「或」條件

SELECT * FROM my_table WHERE my_table.x=1 OR my_table.y=1 

我想這樣做的「Rails的3」的方式。我正在尋找類似的東西:

Account.where(:id => 1).or.where(:id => 2) 

我知道我總是可以回退到sql或條件字符串。但是,根據我的經驗,這在合併範圍時往往會導致混亂。做這個的最好方式是什麼?

另一個相關的問題是如何描述依賴於OR條件的關係。我發現的唯一方法是:

has_many :my_thing, :class_name => "MyTable", :finder_sql => 'SELECT my_tables.* ' + 'FROM my_tables ' + 
'WHERE my_tables.payer_id = #{id} OR my_tables.payee_id = #{id}' 

但是,當它們組合使用時,它們再次斷裂。有沒有更好的方法來指定這個?

回答

9

可悲的是,。或者尚未實現(但是當它是,這將是真棒)。

所以你必須做一些事情,如:

class Project < ActiveRecord::Base 
    scope :sufficient_data, :conditions=>['ratio_story_completion != 0 OR ratio_differential != 0'] 
    scope :profitable, :conditions=>['profit > 0'] 

這樣,你仍然可以真棒,做:

Project.sufficient_data.profitable 
+0

: OR運算符尚未支持。它的工作方式如下: users.where(users [:name] .eq('bob')。or(users [:age] .lt(25))) – hjuskewycz 2010-07-21 11:18:27

6

我會去與IN條款,e.g:

Account.where(["id in (?)", [1, 2]]) 
+0

這將是適當的,但要注意的作者是看@ 2個不同的領域...... – Brian 2010-07-20 14:58:31

+0

哦,是的,這是真的,我在這個聲明中寫了答案:Account.where(:id => 1).or.where(:id => 2)'。顯然它不適用於不同的領域。 – jpemberthy 2010-07-20 16:04:52

+2

如果array中的某個值爲'nil',則不起作用。假設你想查找所有記錄的「視圖」是「false」或「nil」,並且你做了Notification.where(:viewing => [false,nil])',它將不起作用,因爲MySQL需要語法'被瀏覽= 0或者被查看IS NULL'和*不能與*'被瀏覽= 0或者被瀏覽= NULL'或者'被瀏覽過IN(0,NULL)'。 – 2011-07-11 08:08:55

71

這將在導軌的5部作品,看rails master

Post.where('id = 1').or(Post.where('id = 2')) 
# => SELECT * FROM posts WHERE (id = 1) OR (id = 2) 

For Rails 3.0.4+:

accounts = Account.arel_table 
Account.where(accounts[:id].eq(1).or(accounts[:id].eq(2))) 
+12

此語法有效。有沒有人不喜歡它? :) – 2012-04-13 14:58:18

+4

絕對不喜歡這種語法。儘管如此,有趣的是。 – DRobinson 2012-08-12 06:42:31

+0

我喜歡它,因爲它可以組合使用 – mdesantis 2014-05-20 12:02:53

16

這些arel查詢對我來說是不可讀的。

SQL字符串有什麼問題?事實上,Rails的引導,暴露出的方式,使條件查詢第一種方式:http://guides.rubyonrails.org/active_record_querying.html#array-conditions

所以,我敢打賭,對於這樣做的「Rails的路」:

Account.where("id = 1 OR id = 2") 

在我卑微的意見,它更短,更清晰。

+7

喜歡這個,但我會使用參數化的值。 'Account.where(「id =?OR id =?」,1,2)' – spyle 2014-09-11 14:06:46

+0

使用簡單數字時,我看不到任何參數化值的原因。 – 2014-09-15 14:35:21

+0

如果您對id進行了硬編碼,那麼不會有簡單的數字,但我會懷疑這些數據是從別處返回的,所以參數化是避免sql注入的方法。 – 2015-06-22 11:23:53

5

我已經使用Squeel gem(https://github.com/ernie/squeel/)來完成OR查詢,它的工作很好。

它可以讓你寫你的查詢作爲Account.where{(id == 1) | (id == 2)}

4

您可以定義一個數組作爲:conditions哈希值。

所以,你可以舉例來說事:

Account.all(:conditions => { :id => [1, 2] }) 

測試使用Rails 3.1.0

+1

這是效率低下,因爲您正在檢索數據庫中的所有項目並檢查內存 – 2014-04-21 23:31:25

111

Account.where(id: [1,2])沒有必要解釋。

+0

乾淨,DRYest我見過。做得好! – 2013-09-04 00:51:51

+0

我見過的最佳解決方案!並且看起來很多(: – 2013-09-20 10:48:45

+10

)這很棒,而且很簡單,我也學會了可以安全地使用'nil':例如'Thing.where(foo:[1,nil])'會被轉換爲'SELECT' (「」事物「。」foo「= 1或」things「。」foo「IS NULL))''!輝煌! – 2013-11-13 03:48:36

2

替代使用語法哈希

Account.where("id = :val1 OR id = :val2", val1: 1, val2: 2). 

這是特別有用的,當此值被設置成多列進行比較。例如:

User.where("first_name = :name OR last_name = :name", name: 'tom') 
0

隨着rails_or,你可以做到這一點,如:

Account.where(id: 1).or(id: 2) 

(它工作在軌道4和5,太)