Skip to content

Instantly share code, notes, and snippets.

@sginkov
Last active January 5, 2017 10:46
Show Gist options
  • Save sginkov/b947740006b7f270ed90e6e6cc22279d to your computer and use it in GitHub Desktop.
Save sginkov/b947740006b7f270ed90e6e6cc22279d to your computer and use it in GitHub Desktop.
# OR support for rails 4
module OrScopes
extend ActiveSupport::Concern
module ClassMethods
# Creates a new scope with with all where clauses joined by "OR"
# Preserves joins but ignores all other query elements.
def or_scopes(scopes, use_joins: true)
joins = []
wheres = []
scopes.each do |scope|
joins_values = scope.joins_values
joins += scope.joins_values if joins_values.present?
scope_wheres = scope.where_values.map do |where_value|
if where_value.is_a?(Arel::Nodes::Equality) || where_value.is_a?(Arel::Nodes::NotEqual)
right = where_value.right
if right.is_a?(Arel::Nodes::BindParam)
left = where_value.left
relation_table_name = left.relation.name
where_values_hash = scope.where_values_hash(relation_table_name)
where_value.right = Arel::Nodes.build_quoted(where_values_hash[left.name], scope.table[left.name])
end
where_value.to_sql
else
where_value
end
end
wheres << "(#{ scope_wheres.join(' AND ') })"
end
scope = where(wheres.join(' OR '))
scope = joins.inject(scope, &:joins) if use_joins
scope
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment