Rails ActiveRecord查询不等于

67

Rails 3.2.1

有没有一种方法(不使用squeel)可以使用ActiveRecord的哈希语法构造一个!=操作符?

比如像这样:Product.where(id: !params[:id])

将生成SELECT products.* FROM products WHERE id != 5

寻找与Product.where(id: params[:id])相反的方法

更新

在Rails 4中有一个not运算符。

Product.where.not(id: params[:id])

4个回答

93

你可以使用以下方式

Product.where('id != ?', params[:id])

这将生成您要查找的内容,并对查询进行参数化。

在Rails 4中,以下语法已添加以支持非语句

Product.where.not(id: params[:id])

使用链接添加多个子句...

Product.where.not(id: params[:id]).where.not(category_id: params[:cat_id])

2
当params[:id]为空时,这可能会出现意外情况。在Rails 3.2.X中,我使用Product.where('id != ?', params[:id].to_i) - comme
在Rails 3中,请指导如何处理多个ID的情况?例如:Product.where('id != ?', 10000, 10001, 10004, 10035, 10088)。 - rhunal

34

截至Rails 3.2.13,没有内置的方法可以做到这一点。但是,您可以轻松构建一个方法来帮助您:

ActiveRecord::Base.class_eval do
  def self.where_not(opts)
    params = []        
    sql = opts.map{|k, v| params << v; "#{quoted_table_name}.#{quote_column_name k} != ?"}.join(' AND ')
    where(sql, *params)
  end
end

然后你可以这样做:

Product.where_not(id: params[:id])

更新

根据@DanMclain的回答 - 在Rails 4中已经为您完成了这个操作(使用where.not(...))。


1
加一以确保……但一定要测试空值。在我看来,它们不相等,但是结果查询将不会返回字段为空的记录。例如,where_not(:status => 'active')。 - baash05
还需要考虑的是... where_not_or Employee.where(:id=>1).where_not_or(:job_title=>'Awesome', :wages=>10000000).update_all(:job_title=>'Awesome', :wages=>10000000, :updated_at => Time.now) 只有在更改时才会进行更新。 - baash05
1
@daveatflow,SQL标准对于NULL的处理是除非使用IS NULL或IS NOT NULL进行明确检查,否则绝不返回。因此,我不同意调用!=应该修改这种行为。添加一个or方法将会非常有益,但现在使用Arel或Squeel比重新发明轮子更容易。 - PinnyM

24

Rails 4 已经解决了这个问题。因此,您可以更新您的 Rails 应用程序。

Model.where.not(:id => params[:id])

1
升级Rails以改进其AR调用的语法?我喜欢它,但愿我也能去见我们的管理层并将一些旧平台升级! - Mark Kadlec
1
@MarkKadlec 开始创业 ¯_(ツ)_/¯ - boulder_ruby

14

Arel可能是你想要探索的一个工具。它已包含在Rails 3+中,我猜测。

以下是使用Arel的方法:

Product.where(Product.arel_table[:id].not_eq(params[:id]))

并且

Product.where(Product.arel_table[:id].not_eq(params[:id])).to_sql 

会生成以下类似的 SQL 语句:

SELECT `products`.* FROM `products`  WHERE (`products`.`id` != 1)

希望这可以帮到你


如何使用此语法在多个属性上进行查询? - sky_coder123
.where(…) can be chained, too, so this extends to searching across multiple columns. Product.where(…).where(…) - Dave Land

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接