Class: NoBrainer::Criteria::Where::BinaryOperator
- Inherits:
-
Struct
- Object
- Struct
- NoBrainer::Criteria::Where::BinaryOperator
- Defined in:
- lib/no_brainer/criteria/where.rb
Class Method Summary collapse
Instance Method Summary collapse
- #compatible_with_index?(index) ⇒ Boolean
- #simplify ⇒ Object
- #to_rql(doc) ⇒ Object
- #to_rql_scalar(lvalue) ⇒ Object
Class Method Details
.get_candidate_clauses(clauses, *types) ⇒ Object
70 71 72 |
# File 'lib/no_brainer/criteria/where.rb', line 70 def self.get_candidate_clauses(clauses, *types) clauses.select { |c| c.is_a?(self) && types.include?(c.op) } end |
.simplify_clauses(op, ast_clauses) ⇒ Object
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/no_brainer/criteria/where.rb', line 74 def self.simplify_clauses(op, ast_clauses) # This code assumes that simplfy() has already been called on all clauses. if op == :or eq_clauses = get_candidate_clauses(ast_clauses, :in, :eq) new_clauses = eq_clauses.group_by { |c| [c.key_path, c.key_modifier] }.map do |(key_path, key_modifier), clauses| if key_modifier.in?([:scalar, :any]) && clauses.size > 1 values = clauses.flat_map { |c| c.op == :in ? c.value : [c.value] }.uniq [BinaryOperator.new(key_path, key_modifier, :in, values, clauses.first.model, true)] else clauses end end.flatten(1) if new_clauses.size != eq_clauses.size ast_clauses = ast_clauses - eq_clauses + new_clauses end end ast_clauses end |
Instance Method Details
#compatible_with_index?(index) ⇒ Boolean
160 161 162 |
# File 'lib/no_brainer/criteria/where.rb', line 160 def compatible_with_index?(index) [key_modifier, index.multi].in?([[:any, true], [:scalar, false]]) end |
#simplify ⇒ Object
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/no_brainer/criteria/where.rb', line 95 def simplify new_key_path = cast_key_path(key_path) new_key_modifier, new_op, new_value = case op when :in then case value when Range then [key_modifier, :between, (cast_value(value.min)..cast_value(value.max))] when Array then [key_modifier, :in, value.map(&method(:cast_value)).uniq] else raise ArgumentError.new "`in' takes an array/range, not #{value}" end when :between then [key_modifier, op, (cast_value(value.min)..cast_value(value.max))] when :include then ensure_scalar_for(op); [:any, :eq, cast_value(value)] when :defined, :undefined then ensure_scalar_for(op); [key_modifier, op, cast_value(value)] when :during then [key_modifier, op, [cast_value(value.first), cast_value(value.last)]] else [key_modifier, op, cast_value(value)] end # When key_path relates to a polymorphic associatoin, the new_key_path is # an Array containing the foreign_type and then the foreign_key. if new_key_path.first.is_a?(Array) foreign_type, foreign_key = new_key_path.first MultiOperator.new( :and, [ BinaryOperator.new([foreign_type], new_key_modifier, new_op, value.class.to_s, model, true), BinaryOperator.new([foreign_key], new_key_modifier, new_op, value.__send__(value.class.pk_name), model, true) ] ) else BinaryOperator.new(new_key_path, new_key_modifier, new_op, new_value, model, true) end end |
#to_rql(doc) ⇒ Object
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/no_brainer/criteria/where.rb', line 128 def to_rql(doc) key_path = [model.lookup_field_alias(self.key_path.first), *self.key_path[1..-1]] doc = key_path[0..-2].reduce(doc) { |d,k| d[k] } key = key_path.last case key_modifier when :scalar then case op when :defined then value ? doc.has_fields(key) : doc.has_fields(key).not when :undefined then !value ? doc.has_fields(key) : doc.has_fields(key).not else to_rql_scalar(doc[key]) end when :any then doc[key].map { |lvalue| to_rql_scalar(lvalue) }.contains(true) when :all then doc[key].map { |lvalue| to_rql_scalar(lvalue) }.contains(false).not end end |
#to_rql_scalar(lvalue) ⇒ Object
146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/no_brainer/criteria/where.rb', line 146 def to_rql_scalar(lvalue) case op when :between then (lvalue >= value.min) & (lvalue <= value.max) when :in then RethinkDB::RQL.new.expr(value).contains(lvalue) when :intersects then lvalue.intersects(value.to_rql) when :during then lvalue.during(value.first, value.last) when :near # XXX options[:max_results] is not used, seems to be a workaround of rethinkdb index implementation. circle = value[:circle] RethinkDB::RQL.new.distance(lvalue, circle.center.to_rql, circle.) <= circle.radius else lvalue.__send__(op, value) end end |