module Mobility::Plugins::ActiveRecord::Query::QueryExtension::QueryBuilder

Constants

IDENTITY

Public Class Methods

build(scope, where_opts, invert: false) { || ... } click to toggle source
# File lib/mobility/plugins/active_record/query.rb, line 208
def build(scope, where_opts, invert: false, &block)
  return yield unless ::Hash === where_opts

  opts = where_opts.with_indifferent_access
  locale = opts.delete(:locale) || Mobility.locale

  _build(scope, opts, locale, invert, &block)
end

Private Class Methods

_build(scope, opts, locale, invert) { || ... } click to toggle source

Builds a translated relation for a given opts hash and optional invert boolean.

# File lib/mobility/plugins/active_record/query.rb, line 221
def _build(scope, opts, locale, invert)
  return yield if (mods = translation_modules(scope)).empty?

  keys, predicates = opts.keys.map(&:to_s), []

  query_map = mods.inject(IDENTITY) do |qm, mod|
    i18n_keys = mod.names & keys
    next qm if i18n_keys.empty?

    mod_predicates = i18n_keys.map do |key|
      build_predicate(scope.backend_node(key.to_sym, locale), opts.delete(key))
    end
    invert_predicates!(mod_predicates) if invert
    predicates += mod_predicates

    ->(r) { mod.backend_class.apply_scope(qm[r], mod_predicates, locale, invert: invert) }
  end

  return yield if query_map == IDENTITY

  relation = opts.empty? ? scope : yield(opts)
  query_map[relation.where(predicates.inject(:and))]
end
build_predicate(node, values) click to toggle source
# File lib/mobility/plugins/active_record/query.rb, line 249
def build_predicate(node, values)
  nils, vals = partition_values(values)

  return node.eq(nil) if vals.empty?

  predicate = vals.length == 1 ? node.eq(vals.first) : node.in(vals)
  predicate = predicate.or(node.eq(nil)) unless nils.empty?
  predicate
end
invert_predicate(predicate) click to toggle source

Adapted from AR::Relation::WhereClause#invert_predicate

# File lib/mobility/plugins/active_record/query.rb, line 268
def invert_predicate(predicate)
  case predicate
  when ::Arel::Nodes::In
    ::Arel::Nodes::NotIn.new(predicate.left, predicate.right)
  when ::Arel::Nodes::Equality
    ::Arel::Nodes::NotEqual.new(predicate.left, predicate.right)
  else
    ::Arel::Nodes::Not.new(predicate)
  end
end
invert_predicates!(predicates) click to toggle source
# File lib/mobility/plugins/active_record/query.rb, line 263
def invert_predicates!(predicates)
  predicates.map!(&method(:invert_predicate))
end
partition_values(values) click to toggle source
# File lib/mobility/plugins/active_record/query.rb, line 259
def partition_values(values)
  Array.wrap(values).uniq.partition(&:nil?)
end
translation_modules(scope) click to toggle source
# File lib/mobility/plugins/active_record/query.rb, line 245
def translation_modules(scope)
  scope.model.ancestors.grep(::Mobility::Translations)
end