使用AREL编写“不在”sql查询中

我的范围定义如下:

scope :ignore_unavailable, lambda { where([ "Item.id NOT IN (SELECT id FROM Cars WHERE Cars.status = 'NA'" ]) } 

目前它使用硬编码表名。 如何使用像Arel这样的框架来改进它? 将在这里感谢任何帮助。

我在Rails 3.2上

如果你使用的是rails 4,那么就有一种方法

 scope :ignore_unavailable, lambda { where.not(id: Car.where(:status => "NA").pluck(:id)) } 

对于铁轨3

 scope :ignore_unavailable, lambda { where("id not in (?)", Car.where(:status => "NA").pluck(:id)) } 

由于任务描述使用AREL请求答案,我提出以下内容:

 class Car scope :available, -> { where(arel_table[:status].not_in(['NA'])) } end class Item scope :available, -> { where(:id => Car.available) } end 

sql应该类似于以下内容:

 SELECT [items].* FROM [items] WHERE [item].[id] IN ( SELECT [cars].[id] FROM [cars] WHERE [car].[status] NOT IN ('NA') ) 

显然,导轨4不具有范围,因此这是导轨3的解决方案。

上面的代码有两个好处:

  • 它执行单个查询
  • 表列是正确的命名空间(与使用原始sql时不同)