Module: HashConditions::Core
Constant Summary collapse
- DEBUG =
Modular Matchers
false
- PRECISION =
5
- ARITMETIC_OPERATORS =
{ '$add' => :+, '$substract' => :-, '$multiply' => :*, '$divide' => :/, }
Instance Method Summary collapse
- #_ext_get_module(key, condition, options) ⇒ Object
- #_ext_match(condition, options) ⇒ Object
- #_ext_parse(expression, options) ⇒ Object
- #_ext_read_module(parser_output, options) ⇒ Object
- #add_bundle(name) ⇒ Object
- #bundles ⇒ Object
- #contains_bundle(name) ⇒ Object
- #eval_expression(value) ⇒ Object
- #eval_operand(hash, key, options = {}) ⇒ Object
- #extract_expression(key, value) ⇒ Object
- #get_condition_from_expression(expression) ⇒ Object
- #get_key(hash, key) ⇒ Object
- #get_op(key) ⇒ Object
-
#iterator(conditions, options = {}) ⇒ Object
Iterator.
- #log(*args) ⇒ Object
- #module_match(matcher, writer = nil, operations = [], &block) ⇒ Object
- #modules ⇒ Object
- #ops ⇒ Object
- #re_type(data) ⇒ Object
- #reset ⇒ Object
- #results_from_expression(expression, options) ⇒ Object
- #rev_op(key) ⇒ Object
Instance Method Details
#_ext_get_module(key, condition, options) ⇒ Object
215 216 217 218 219 |
# File 'lib/hash_conditions/core.rb', line 215 def _ext_get_module key, condition, modules.select{ |m| m.for_operation? [:operation] }.find do | matcher | matcher.apply_for key, condition end end |
#_ext_match(condition, options) ⇒ Object
197 198 199 |
# File 'lib/hash_conditions/core.rb', line 197 def _ext_match condition, ->(key) { _ext_get_module( key, condition, ) != nil } end |
#_ext_parse(expression, options) ⇒ Object
201 202 203 204 205 206 207 208 209 210 211 212 213 |
# File 'lib/hash_conditions/core.rb', line 201 def _ext_parse expression, key, op, value = expression.values_at :key, :operator, :value condition = get_condition_from_expression expression mod = _ext_get_module key,condition, parser = mod.replacement case parser when String then [:result].call(extract_expression( parser, condition ), ) when Hash then _ext_read_module( { '$eval' => [ parser, op, value ] }, ) when Proc then _ext_read_module( parser.call( key, condition, ), ) end end |
#_ext_read_module(parser_output, options) ⇒ Object
221 222 223 224 225 226 227 228 |
# File 'lib/hash_conditions/core.rb', line 221 def _ext_read_module parser_output, case parser_output when Hash then iterator(parser_output, ) when NilClass then nil when String then parser_output # this should be removed, since the matcher will not support it else raise "return data of type #{ parser_output.class } not supported" end end |
#add_bundle(name) ⇒ Object
29 30 31 |
# File 'lib/hash_conditions/core.rb', line 29 def add_bundle name bundles << name end |
#bundles ⇒ Object
25 26 27 |
# File 'lib/hash_conditions/core.rb', line 25 def bundles @@bundles ||= [] end |
#contains_bundle(name) ⇒ Object
32 33 34 |
# File 'lib/hash_conditions/core.rb', line 32 def contains_bundle name bundles.include? name end |
#eval_expression(value) ⇒ Object
72 73 74 75 76 77 78 |
# File 'lib/hash_conditions/core.rb', line 72 def eval_expression value raise "Invalid eval expression" unless value.is_a? Array and value.length == 3 Hash[ [ :key, :operator, :value ].zip( value ) ].tap do | exp | exp[ :operator ] = get_op exp[ :operator ] end end |
#eval_operand(hash, key, options = {}) ⇒ Object
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/hash_conditions/core.rb', line 163 def eval_operand hash, key, = {} __get_values = lambda do | values | values.map{ |x| eval_operand hash, x, } end case key when String, Symbol if key.to_s == '$now' [:current_time] || Time.now else val = [:is_key] ? get_key( hash, key ) : key re_type val end when Array __get_values.call( key ) when Hash op, values = key.to_a.first case op.to_s when *ARITMETIC_OPERATORS.keys #TODO: Test feature: when applying aritmetics it forces that the values are floats __get_values.call( values ).each{ |v| v.to_f }.inject( ARITMETIC_OPERATORS[ op ] ) when '$ifNull' __get_values.call( values ).drop_while{ |n| n.nil? }.shift when '$concat' __get_values.call( values ).join('') when '$concatWithSeparator' separator = values[0] __get_values.call( values[1..-1] ).join( separator ) end else key end end |
#extract_expression(key, value) ⇒ Object
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/hash_conditions/core.rb', line 80 def extract_expression key, value result = {} result[:key] = key case value when String, Integer, Float result[:operator] = :== result[:value] = value when Array result[:operator] = :in result[:value] = value when Hash if value.length == 1 key, value = value.to_a.first result[:operator] = get_op key result[:value] = value else case when value.keys.include?('$between') result[:operator] = :between result[:value] = value.values_at [ '$between', '$and' ] end end end result[:value] = re_type result[:value] result end |
#get_condition_from_expression(expression) ⇒ Object
111 112 113 114 115 |
# File 'lib/hash_conditions/core.rb', line 111 def get_condition_from_expression expression {}.tap do | condition | condition[ rev_op( expression[:operator] ) ] = expression[:value] end end |
#get_key(hash, key) ⇒ Object
150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/hash_conditions/core.rb', line 150 def get_key hash, key if hash.has_key? key hash[ key ] else key_type = key.class key.to_s.split('.').inject(hash) do |ret, k| typed_key = key_type == Symbol ? k.to_sym : k raise KeyNotFound, "key #{key} not found" unless ret.has_key? typed_key ret = ret[ typed_key ] end end end |
#get_op(key) ⇒ Object
134 135 136 137 |
# File 'lib/hash_conditions/core.rb', line 134 def get_op key pair = ops.find{ |k, v| Array(v).include? key } pair && pair.first or key end |
#iterator(conditions, options = {}) ⇒ Object
Iterator
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/hash_conditions/core.rb', line 43 def iterator conditions, = {} = { glue: :and }.merge result = case conditions when ::Hash conditions.map do | key, value | case key when '$and' then iterator(value, .merge( glue: :and )) when '$or' then iterator(value, .merge( glue: :or)) when '$eval' then results_from_expression( eval_expression( value ), ) when _ext_match( value, ) then _ext_parse( extract_expression(key, value) , ) else results_from_expression( extract_expression( key, value ), ) end end when ::Array conditions.map do | condition | iterator condition, end else raise "Unexpected expression found: #{ conditions }" end [:finalize].call result, end |
#log(*args) ⇒ Object
230 231 232 |
# File 'lib/hash_conditions/core.rb', line 230 def log *args puts args.map(&:to_s).join(" ") if(DEBUG) end |
#module_match(matcher, writer = nil, operations = [], &block) ⇒ Object
36 37 38 39 |
# File 'lib/hash_conditions/core.rb', line 36 def module_match matcher, writer = nil, operations = [], &block writer = block if block modules << ModuleMatcher.new(matcher, writer, operations) end |
#modules ⇒ Object
17 18 19 |
# File 'lib/hash_conditions/core.rb', line 17 def modules @@modules ||= [] end |
#ops ⇒ Object
117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/hash_conditions/core.rb', line 117 def ops { :== => [ '$eq', '$equal' ], :!= => [ '$ne', '$not_equal' ], :> => [ '$gt' ], :< => [ '$lt' ], :>= => [ '$gte' ], :<= => [ '$lte' ], :between => [ '$between' ], :in => [ "$in" ], :contains => [ "$contains" ] } end |
#re_type(data) ⇒ Object
139 140 141 142 143 144 145 146 147 148 |
# File 'lib/hash_conditions/core.rb', line 139 def re_type data if data.is_a? String case data when /\d{4}-\d{2}-\d{2}[\sT]\d{2}:\d{2}:\d{2}(\.\d{3})?Z?/ then DateTime.parse( data ).to_time else data end else data end end |
#reset ⇒ Object
21 22 23 |
# File 'lib/hash_conditions/core.rb', line 21 def reset @@modules = [] end |
#results_from_expression(expression, options) ⇒ Object
68 69 70 |
# File 'lib/hash_conditions/core.rb', line 68 def results_from_expression expression, [:result].call( expression, ) end |
#rev_op(key) ⇒ Object
131 132 133 |
# File 'lib/hash_conditions/core.rb', line 131 def rev_op key ops[ key ] && ops[ key ].first or key end |