Uma das deficiências dos escopos no ActiveRecord é a incapacidade de encadea-los em uma cláusula “OU”. Aqui está uma maneira de fazer isso. O uso não é particularmente elegante, mas dá conta do recado.
Preocupação com o comportamento OR
module ModelHasScopeHelpers
extend ActiveSupport::Concern
module ClassMethods
# Creates a new scope with with all where clauses joined by "OR"
# Preserves selects & orders but ignores all other query elements.
def or_scopes(*scopes)
selects = []
orders = []
wheres = scopes.map do |scope|
selects << scope.projections
orders << scope.orders
if scope.arel.where_sql.present?
scope.arel.where_sql.gsub(/AWHERE /i, "")
else
nil
end
end
scope = where(wheres.compact.join(" OR "))
selects.flatten.each { |s| scope = scope.select(s) }
orders.flatten.each { |o| scope = scope.order(o) }
scope
end
end
end
Modelo
model User < ActiveRecord::Base
include ModelHasScopeHelpers
end
Uso
users = User.or_scopes(
User.where(name: "Bob"),
User.where(name: "Bobby"),
User.where(name: "Bobbie")
)