问题
I have a scope defined as follows:
scope :ignore_unavailable, lambda {
where([ "Item.id NOT IN (SELECT id FROM Cars WHERE Cars.status = 'NA'" ])
}
Currently its using hardcoded tables names. How can I improve it using frameworks like Arel ? Will appreciate any help here.
I am on Rails 3.2
回答1:
If you are using rails 4, one way would be
scope :ignore_unavailable, lambda {
where.not(id: Car.where(:status => "NA").pluck(:id))
}
For rails 3
scope :ignore_unavailable, lambda {
where("id not in (?)", Car.where(:status => "NA").pluck(:id))
}
回答2:
Since the task description asks for an answer using AREL, I present following:
class Car
scope :available, -> { where(arel_table[:status].not_in(['NA'])) }
end
class Item
scope :available, -> { where(:id => Car.available) }
end
The sql should be something like the following:
SELECT [items].*
FROM [items]
WHERE [item].[id] IN (
SELECT [cars].[id]
FROM [cars]
WHERE [car].[status] NOT IN ('NA')
)
Obviously, rails 4 has the not
scope, so this is a solution for rails 3.
The above code has two benefits:
- It performs a single query
- The table columns are correctly namespaced (unlike when using raw sql)
来源:https://stackoverflow.com/questions/25692461/writing-not-in-sql-query-using-arel