From 5f106a2b6349825cffb4b0ff9f2dd6f13c3bd0bb Mon Sep 17 00:00:00 2001 From: Chris Salzberg Date: Sun, 29 Apr 2018 23:35:24 +0900 Subject: [PATCH] Refactor PredicateBuilder --- lib/mobility/plugins/query.rb | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/lib/mobility/plugins/query.rb b/lib/mobility/plugins/query.rb index 7eff3b2cc..9e13501b9 100644 --- a/lib/mobility/plugins/query.rb +++ b/lib/mobility/plugins/query.rb @@ -75,34 +75,41 @@ def map(opts, locale, invert: false) attrs_opts = opts.slice(*i18n_keys) - predicate_builder = PredicateBuilder.new(attrs.backend_class) + predicate_builder = PredicateBuilder.new(attrs) predicates += i18n_keys.map do |key| - predicate_builder.build(key, locale, opts.delete(key), attrs.options) + predicate_builder.build(key, locale, opts.delete(key), invert) end [attrs, attrs_opts] }.compact - # TODO: inline this - inverter = ::ActiveRecord::Relation::WhereClause.new([]).method(:invert_predicate) if invert - predicates = predicates.map(&inverter.method(:call)) if invert - [opts, predicates.inject(&:and), map] end end class PredicateBuilder - def initialize(backend_class) - @backend_class = backend_class + attr_reader :backend_class, :backend_options + + def initialize(attributes) + @backend_class = attributes.backend_class + @backend_options = attributes.options + end + + def build(attr, locale, values, invert) + predicate = _build(attr, locale, values) + predicate = invert(predicate) if invert + predicate end - def build(attr, locale, values, backend_options) - node = @backend_class.build_node(attr, locale, backend_options) + private + + def _build(attr, locale, values) + node = backend_class.build_node(attr, locale, backend_options) nils, vals = Array.wrap(collapse(values)).uniq.partition(&:nil?) return node.eq(nil) if vals.empty? - vals = vals.map { |val| @backend_class.quote_value(val, backend_options) } + vals = vals.map { |val| backend_class.quote_value(val, backend_options) } predicate = vals.length == 1 ? node.eq(vals.first) : node.in(vals) predicate = predicate.or(node.eq(nil)) unless nils.empty? @@ -112,6 +119,11 @@ def build(attr, locale, values, backend_options) def collapse(value) value.is_a?(Array) ? value.uniq : value end + + # TODO: inline this + def invert(predicate) + ::ActiveRecord::Relation::WhereClause.new([]).method(:invert_predicate)[predicate] + end end private_constant :WhereChain, :ClauseMapper, :PredicateBuilder