In Rails5, how do I return the union of two scopes or combine them into one?
Answer a question I'm struggling to either return the union of two scopes or combine them into one in my Rails app. The outcome I'm looking for is to retrieve all orders that satisfy either of the sco
Answer a question
I'm struggling to either return the union of two scopes or combine them into one in my Rails app. The outcome I'm looking for is to retrieve all orders that satisfy either of the scopes: Order.with_buyer_like or the Order.with_customer_like. That is I'm looking for the union of the sets. Importantly, I need these to be returned as an ActiveRecord::Relation, rather than an array. Otherwise, I'd just do
results = Order.with_buyer_like + Order.with_customer_like
I've also tried to use the "or" operator but get an error:
Order.with_seller_like('pete').or(Order.with_customer_like('pete'))
ArgumentError: Relation passed to #or must be structurally compatible. Incompatible values: [:joins]
I've also tried combining the scopes into one, but I can't quite get it to work.
Here's my setup:
class Company
has_many :stores
end
class Store
belongs_to :company
end
class Order
belongs_to :buying_store, class_name: 'Store', foreign_key: 'buying_store_id', required: true
belongs_to :selling_store, class_name: 'Store', foreign_key: 'selling_store_id', required: true
scope :with_buyer_like, ->(search_term) { joins(buying_store: [:company], :customer).where(['stores.name LIKE ? OR companies.name LIKE ?', "%#{search_term.gsub(/ /, '_').downcase}%", "%#{search_term.gsub(/ /, '_').downcase}%"]) }
scope :with_customer_like, ->(search_term) { joins(:customer).where(['first_name LIKE ? OR last_name LIKE ? OR mobile_number LIKE ? OR email LIKE ?', "%#{search_term.gsub(/ /, '_').downcase}%", "%#{search_term.gsub(/ /, '_').downcase}%", "%#{search_term.gsub(/ /, '_').downcase}%", "%#{search_term.gsub(/ /, '_').downcase}%"] ) }
end
Answers
This blog has good explanation of issue you are facing.
To summarize here, you have to make sure the joins
, includes
, select
(in short structure of AR data to be fetched) is consistent between both the scopes.
This syntax is the way to go as long as you make sure both the scopes have same joins.
Order.with_seller_like('pete').or(Order.with_customer_like('pete'))
To take first step, check if this works(not recommended though):
Order.where(id: Order.with_seller_like('pete')).or(Order.where(id: Order.with_customer_like('pete')))
I would recommend to move away from joins
and use sub-query style of querying if you are looking for only Order
data in output.
更多推荐
所有评论(0)