2010-07-20 82 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,太)