Class: Hash
- Inherits:
-
Object
- Object
- Hash
- Includes:
- Funcml
- Defined in:
- lib/funcml-core/patch/hash.rb,
lib/funcml-core/patch/funcs/cast.rb,
lib/funcml-core/patch/funcs/list.rb,
lib/funcml-core/patch/funcs/math.rb,
lib/funcml-core/patch/funcs/time.rb,
lib/funcml-core/patch/funcs/encoding.rb,
lib/funcml-core/patch/funcs/dictionary.rb,
lib/funcml-core/patch/funcs/cryptography.rb
Constant Summary
Constants included from Funcml
Instance Method Summary collapse
- #_add(mutations) ⇒ Object
- #_ago(mutations) ⇒ Object
- #_base64decode(mutations) ⇒ Object
- #_base64encode(mutations) ⇒ Object
- #_capitalize(mutations) ⇒ Object
- #_ceil(mutations) ⇒ Object
-
#_concat(mutations) ⇒ Object
_concat concatenates items elements as a string with sep as separator.
-
#_decryptAES(mutations) ⇒ Object
source gist.github.com/wteuber/5318013.
- #_div(mutations) ⇒ Object
- #_downcase(mutations) ⇒ Object
-
#_encryptAES(mutations) ⇒ Object
source gist.github.com/wteuber/5318013.
- #_first(mutations) ⇒ Object
- #_float(mutations) ⇒ Object
- #_floor(mutations) ⇒ Object
- #_fromJson(mutations) ⇒ Object
- #_head(mutations) ⇒ Object
- #_if(mutations) ⇒ Object
- #_index(mutations) ⇒ Object
- #_int(mutations) ⇒ Object
- #_json(mutations) ⇒ Object
- #_keys(mutations) ⇒ Object
- #_last(mutations) ⇒ Object
- #_len(mutations) ⇒ Object
- #_loop(mutations) ⇒ Object
- #_map(mutations) ⇒ Object
- #_max(mutations) ⇒ Object
-
#_merge(mutations) ⇒ Object
_merge merges a hash found at mutation path with caller hash and removes the _merge reference.
- #_min(mutations) ⇒ Object
- #_mod(mutations) ⇒ Object
- #_mul(mutations) ⇒ Object
- #_readfile(mutations) ⇒ Object
- #_replace(mutations) ⇒ Object
- #_reverse(mutations) ⇒ Object
- #_round(mutations) ⇒ Object
- #_sha1sum(mutations) ⇒ Object
- #_sha256sum(mutations) ⇒ Object
- #_string(mutations) ⇒ Object
- #_sub(mutations) ⇒ Object
-
#_sum(mutations) ⇒ Object
_sum takes and mutates all elements in array and sums them.
- #_tail(mutations) ⇒ Object
- #_time(mutations) ⇒ Object
- #_uniq(mutations) ⇒ Object
- #_until(mutations) ⇒ Object
- #_upcase(mutations) ⇒ Object
- #_values(mutations) ⇒ Object
- #dig_from_str(path, mutations) ⇒ Object
- #mutate(mutations = {}) ⇒ Object
Instance Method Details
#_add(mutations) ⇒ Object
4 5 6 7 8 |
# File 'lib/funcml-core/patch/funcs/math.rb', line 4 def _add(mutations) self.fetch(:_add, []).then do |numbers| numbers.mutate(mutations).reduce(:+) end end |
#_ago(mutations) ⇒ Object
19 20 21 22 23 24 25 26 27 |
# File 'lib/funcml-core/patch/funcs/time.rb', line 19 def _ago(mutations) self.fetch(:_ago).then do |blk| unless blk.is_a?(Integer) raise IncorrectSecondsException, "_ago only supports seconds as value in #{self.to_s}" end (Time.now - blk).to_s end end |
#_base64decode(mutations) ⇒ Object
11 12 13 14 15 |
# File 'lib/funcml-core/patch/funcs/encoding.rb', line 11 def _base64decode(mutations) self.fetch(:_base64decode, "").then do |value| return Base64.decode64(value.mutate(mutations)).strip end end |
#_base64encode(mutations) ⇒ Object
5 6 7 8 9 |
# File 'lib/funcml-core/patch/funcs/encoding.rb', line 5 def _base64encode(mutations) self.fetch(:_base64encode, "").then do |value| return Base64.encode64(value.mutate(mutations)).strip end end |
#_capitalize(mutations) ⇒ Object
203 204 205 206 207 |
# File 'lib/funcml-core/patch/hash.rb', line 203 def _capitalize(mutations) self.fetch(:_capitalize).then do |ctx| return ctx.mutate(mutations).capitalize end end |
#_ceil(mutations) ⇒ Object
53 54 55 56 57 |
# File 'lib/funcml-core/patch/funcs/math.rb', line 53 def _ceil(mutations) self.fetch(:_ceil).then do |number| number.mutate(mutations).ceil end end |
#_concat(mutations) ⇒ Object
_concat concatenates items elements as a string with sep as separator. eg: {items: [“a”, “b”, “c”], sep: “ ”} = “a b c”
166 167 168 169 170 171 172 |
# File 'lib/funcml-core/patch/hash.rb', line 166 def _concat(mutations) self.fetch(:_concat).then do |concat| return concat.fetch(:items, []) .mutate(mutations) .join(concat.fetch(:sep, "").mutate(mutations)) end end |
#_decryptAES(mutations) ⇒ Object
36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/funcml-core/patch/funcs/cryptography.rb', line 36 def _decryptAES(mutations) self.fetch(:_decryptAES).then do |blk| case blk in {data: data, encryptionKey: encryption_key} cipher = OpenSSL::Cipher.new("aes-256-cbc").decrypt cipher.key = Digest::MD5.hexdigest(encryption_key.mutate(mutations)) s = [data.mutate(mutations)].pack('H*').unpack('C*').pack('c*') cipher.update(s) + cipher.final else raise MissingEncryptionKeyException, "encryptionKey field missing in #{self.to_s}" end end end |
#_div(mutations) ⇒ Object
16 17 18 19 20 |
# File 'lib/funcml-core/patch/funcs/math.rb', line 16 def _div(mutations) self.fetch(:_div, []).then do |numbers| numbers.mutate(mutations).reduce(:/) end end |
#_downcase(mutations) ⇒ Object
197 198 199 200 201 |
# File 'lib/funcml-core/patch/hash.rb', line 197 def _downcase(mutations) self.fetch(:_downcase).then do |ctx| return ctx.mutate(mutations).downcase end end |
#_encryptAES(mutations) ⇒ Object
21 22 23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/funcml-core/patch/funcs/cryptography.rb', line 21 def _encryptAES(mutations) self.fetch(:_encryptAES).then do |blk| case blk in {data: data, encryptionKey: encryption_key} cipher = OpenSSL::Cipher.new("aes-256-cbc").encrypt cipher.key = Digest::MD5.hexdigest(encryption_key.mutate(mutations)) s = cipher.update(data.mutate(mutations)) + cipher.final s.unpack('H*')[0].upcase else raise MissingEncryptionKeyException, "encryptionKey field missing in #{self.to_s}" end end end |
#_first(mutations) ⇒ Object
6 7 8 9 10 |
# File 'lib/funcml-core/patch/funcs/list.rb', line 6 def _first(mutations) self.fetch(:_first).mutate(mutations).then do |elems| return elems.first end end |
#_float(mutations) ⇒ Object
17 18 19 20 21 |
# File 'lib/funcml-core/patch/funcs/cast.rb', line 17 def _float(mutations) self.fetch(:_float).then do |obj| obj.mutate(mutations).to_f end end |
#_floor(mutations) ⇒ Object
47 48 49 50 51 |
# File 'lib/funcml-core/patch/funcs/math.rb', line 47 def _floor(mutations) self.fetch(:_floor).then do |number| number.mutate(mutations).floor end end |
#_fromJson(mutations) ⇒ Object
29 30 31 32 33 34 35 36 37 |
# File 'lib/funcml-core/patch/funcs/cast.rb', line 29 def _fromJson(mutations) self.fetch(:_fromJson).then do |obj| # usage of symbolize_names instead of deep_symbolize_keys as it is only # implemented in funcml-cli. JSON.parse(obj, symbolize_names: true).then do |struct| struct.mutate(mutations) end end end |
#_head(mutations) ⇒ Object
28 29 30 31 32 |
# File 'lib/funcml-core/patch/funcs/list.rb', line 28 def _head(mutations) self.fetch(:_head).mutate(mutations).then do |elems| return elems[0][0..(elems[1]-1)] end end |
#_if(mutations) ⇒ Object
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 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 |
# File 'lib/funcml-core/patch/hash.rb', line 43 def _if(mutations) _runcond = Proc.new do |cond, mutations| case cond in {in: [needle, haystack]} haystack.mutate(mutations).include?(needle.mutate(mutations)) in {null: vars} vars.all? {|x| x.mutate(mutations).nil? } in {present: vars} vars.all? {|x| !x.mutate(mutations).nil? } in {eq: [first, second]} first.mutate(mutations).eql?(second.mutate(mutations)) in {ne: [first, second]} !first.mutate(mutations).eql?(second.mutate(mutations)) in {gt: [first, second]} first.mutate(mutations) > second.mutate(mutations) in {lt: [first, second]} first.mutate(mutations) < second.mutate(mutations) in {ge: [first, second]} first.mutate(mutations) >= second.mutate(mutations) in {le: [first, second]} first.mutate(mutations) <= second.mutate(mutations) in {match: [first, second]} first.match?(Regexp.new(second)) in {unmatch: [first, second]} !first.match?(Regexp.new(second)) # or should evaluated by top-level if as true or false. in {or: or_conds} or_conds.any? do |cond| _runcond.call(cond, mutations) end else raise UnknownConditionException, "#{cond.to_s} is not a valid condition" end end self.fetch(:_if).then do |conditions| all_conditions_state = conditions.all? do |cond| _runcond.call(cond, mutations) end if all_conditions_state self.delete(:_if) self.delete(:_else) return self else return self[:_else] # returns nil if nothing has been set. end nil end end |
#_index(mutations) ⇒ Object
46 47 48 49 50 |
# File 'lib/funcml-core/patch/funcs/list.rb', line 46 def _index(mutations) self.fetch(:_index).mutate(mutations).then do |elems| return elems[0].index(elems[1]) end end |
#_int(mutations) ⇒ Object
11 12 13 14 15 |
# File 'lib/funcml-core/patch/funcs/cast.rb', line 11 def _int(mutations) self.fetch(:_int).then do |obj| obj.mutate(mutations).to_i end end |
#_json(mutations) ⇒ Object
23 24 25 26 27 |
# File 'lib/funcml-core/patch/funcs/cast.rb', line 23 def _json(mutations) self.fetch(:_json).then do |obj| obj.mutate(mutations).to_json end end |
#_keys(mutations) ⇒ Object
4 5 6 7 8 9 10 11 12 13 14 |
# File 'lib/funcml-core/patch/funcs/dictionary.rb', line 4 def _keys(mutations) self.fetch(:_keys).mutate(mutations).then do |elems| return elems.map do |elem| if elem.is_a?(Hash) elem.keys else elem end end.flatten end end |
#_last(mutations) ⇒ Object
12 13 14 15 16 17 18 19 20 |
# File 'lib/funcml-core/patch/funcs/list.rb', line 12 def _last(mutations) self.fetch(:_last).mutate(mutations).then do |elems| if elems.is_a?(Hash) return elems.values.last else return elems.last end end end |
#_len(mutations) ⇒ Object
52 53 54 55 56 |
# File 'lib/funcml-core/patch/funcs/list.rb', line 52 def _len(mutations) self.fetch(:_len).then do |elems| elems.mutate(mutations).length end end |
#_loop(mutations) ⇒ Object
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/funcml-core/patch/hash.rb', line 108 def _loop(mutations) self.fetch(:_loop).then do |_loop| items = _loop.fetch(:items, []).mutate(mutations) _results = [] # guard clause related to allowed types unless items.is_a?(Array) raise LoopTypeException, "_loop only supports Array as items" end # always mutate all items as they could be variable calling hashes. # when caller is a string, will be callable as $item for String # when caller is a Hash, will be callable as $item.path.to.value for String items.each do |item| _results << _loop[:block] .dup # required to avoid duplicates in code .mutate(mutations.merge(item: item)) end return _results end end |
#_map(mutations) ⇒ Object
35 36 37 38 39 40 41 |
# File 'lib/funcml-core/patch/hash.rb', line 35 def _map(mutations) self.fetch(:_map).then do |ctx| ctx.fetch(:items, []).mutate(mutations).map do |item| {ctx.fetch(:call).to_sym => item}.mutate(mutations) end end end |
#_max(mutations) ⇒ Object
41 42 43 44 45 |
# File 'lib/funcml-core/patch/funcs/math.rb', line 41 def _max(mutations) self.fetch(:_max, []).then do |numbers| numbers.mutate(mutations).max end end |
#_merge(mutations) ⇒ Object
_merge merges a hash found at mutation path with caller hash and removes the _merge reference. eg: {key: value, _merge: path.to_mutation } = value, imported_key: value
154 155 156 157 158 159 160 161 162 |
# File 'lib/funcml-core/patch/hash.rb', line 154 def _merge(mutations) self.fetch(:_merge).mutate(mutations).then do |result| self.merge!(result).then do self.delete(:_merge) end end self end |
#_min(mutations) ⇒ Object
35 36 37 38 39 |
# File 'lib/funcml-core/patch/funcs/math.rb', line 35 def _min(mutations) self.fetch(:_min, []).then do |numbers| numbers.mutate(mutations).min end end |
#_mod(mutations) ⇒ Object
22 23 24 25 26 27 |
# File 'lib/funcml-core/patch/funcs/math.rb', line 22 def _mod(mutations) self.fetch(:_mod).then do |numbers| first, second = numbers.mutate(mutations) first % second end end |
#_mul(mutations) ⇒ Object
29 30 31 32 33 |
# File 'lib/funcml-core/patch/funcs/math.rb', line 29 def _mul(mutations) self.fetch(:_mul, []).then do |numbers| numbers.mutate(mutations).reduce(:*) end end |
#_readfile(mutations) ⇒ Object
174 175 176 177 178 |
# File 'lib/funcml-core/patch/hash.rb', line 174 def _readfile(mutations) self.fetch(:_readfile).then do |path| File.read(path) end end |
#_replace(mutations) ⇒ Object
180 181 182 183 184 185 186 187 188 189 |
# File 'lib/funcml-core/patch/hash.rb', line 180 def _replace(mutations) self.fetch(:_replace).then do |ctx| content = ctx.fetch(:content) ctx.fetch(:substitutions).each do |from, to| content = content.gsub(from.mutate(mutations), to.mutate(mutations)) end content end end |
#_reverse(mutations) ⇒ Object
34 35 36 37 38 |
# File 'lib/funcml-core/patch/funcs/list.rb', line 34 def _reverse(mutations) self.fetch(:_reverse).mutate(mutations).then do |elems| return elems.reverse end end |
#_round(mutations) ⇒ Object
59 60 61 62 63 |
# File 'lib/funcml-core/patch/funcs/math.rb', line 59 def _round(mutations) self.fetch(:_round).then do |number| number.mutate(mutations).round end end |
#_sha1sum(mutations) ⇒ Object
8 9 10 11 12 |
# File 'lib/funcml-core/patch/funcs/cryptography.rb', line 8 def _sha1sum(mutations) self.fetch(:_sha1sum).then do |value| return Digest::SHA1.hexdigest(value.mutate(mutations)) end end |
#_sha256sum(mutations) ⇒ Object
14 15 16 17 18 |
# File 'lib/funcml-core/patch/funcs/cryptography.rb', line 14 def _sha256sum(mutations) self.fetch(:_sha256sum).then do |value| return Digest::SHA256.hexdigest(value.mutate(mutations)) end end |
#_string(mutations) ⇒ Object
5 6 7 8 9 |
# File 'lib/funcml-core/patch/funcs/cast.rb', line 5 def _string(mutations) self.fetch(:_string).then do |obj| obj.mutate(mutations).to_s end end |
#_sub(mutations) ⇒ Object
10 11 12 13 14 |
# File 'lib/funcml-core/patch/funcs/math.rb', line 10 def _sub(mutations) self.fetch(:_sub, []).then do |numbers| numbers.mutate(mutations).reduce(:-) end end |
#_sum(mutations) ⇒ Object
_sum takes and mutates all elements in array and sums them. eg: [1, 2, 3] = 6
145 146 147 148 149 |
# File 'lib/funcml-core/patch/hash.rb', line 145 def _sum(mutations) self.fetch(:_sum).map do |item| item.mutate(mutations) end.sum end |
#_tail(mutations) ⇒ Object
22 23 24 25 26 |
# File 'lib/funcml-core/patch/funcs/list.rb', line 22 def _tail(mutations) self.fetch(:_tail).mutate(mutations).then do |elems| return elems[0].last(elems[1]) end end |
#_time(mutations) ⇒ Object
8 9 10 11 12 13 14 15 16 17 |
# File 'lib/funcml-core/patch/funcs/time.rb', line 8 def _time(mutations) self.fetch(:_time).then do |blk| _value = blk.fetch(:value) _format = blk.fetch(:format, "%d/%m/%Y %H:%M:%S") _value.mutate(mutations).then do |value| return Time.parse(value).strftime(_format.mutate(mutations)) end end end |
#_uniq(mutations) ⇒ Object
40 41 42 43 44 |
# File 'lib/funcml-core/patch/funcs/list.rb', line 40 def _uniq(mutations) self.fetch(:_uniq).mutate(mutations).then do |elems| return elems.uniq end end |
#_until(mutations) ⇒ Object
131 132 133 134 135 136 137 138 139 140 |
# File 'lib/funcml-core/patch/hash.rb', line 131 def _until(mutations) _results = [] amount = self.fetch(:_until) amount.times do |i| _results << self.dup.select{|k, v| k != :_until} .mutate(mutations.merge(item: i)) end return _results end |
#_upcase(mutations) ⇒ Object
191 192 193 194 195 |
# File 'lib/funcml-core/patch/hash.rb', line 191 def _upcase(mutations) self.fetch(:_upcase).then do |ctx| return ctx.mutate(mutations).upcase end end |
#_values(mutations) ⇒ Object
16 17 18 19 20 21 22 23 24 25 26 |
# File 'lib/funcml-core/patch/funcs/dictionary.rb', line 16 def _values(mutations) self.fetch(:_values).mutate(mutations).then do |elems| return elems.map do |elem| if elem.is_a?(Hash) elem.values else elem end end.flatten end end |
#dig_from_str(path, mutations) ⇒ Object
209 210 211 212 213 214 215 |
# File 'lib/funcml-core/patch/hash.rb', line 209 def dig_from_str(path, mutations) path_array_sym = path.split('.').map do |sub| sub.to_sym end self.dig(*path_array_sym).mutate(mutations) end |
#mutate(mutations = {}) ⇒ Object
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/funcml-core/patch/hash.rb', line 6 def mutate(mutations = {}) # dup is here to avoid iteration error on #delete/#merge self.dup.each do |key, value| case key in /^\\_.*$/ # escapes keys starting with backslash (\). # gsub is only implemented on String, not Symbol - this is why # we cast the key to string before re-casting it to sym later. escaped_key = key.to_s .gsub('\\_', '_') self[escaped_key.to_sym] = value.mutate(mutations) self.delete(key) in /^_.*$/ # recursive mutation of result from pattern-matched _method # once recursively mutated, we return the final object by guard # clause instead of mutating the current object. return self.send(key, mutations) .mutate(mutations) else # no monkey-patch method found (_ prefix), we mutate anyway # in case of variables or sub-functions. self[key] = value.mutate(mutations) end end self end |