lib/looksist/hashed.rb in looksist-0.3.6 vs lib/looksist/hashed.rb in looksist-0.3.7

- old
+ new

@@ -24,149 +24,144 @@ end def inject_instance_methods(after) define_method("#{after}_with_inject") do |*args| hash = send("#{after}_without_inject".to_sym, *args) - self.class.instance_variable_get(:@rules)[after].each do |opts| - if opts[:at].nil? or opts[:at].is_a? String - hash = self.class.update_using_json_path(hash, opts) + rules_group_by_at = self.class.instance_variable_get(:@rules)[after].group_by { |e| e[:at] } + rules_group_by_at.each do |at, opts| + if at.nil? or at.is_a? String + hash = self.class.update_using_json_path(hash, at, opts) else - self.class.inject_attributes_at(hash[opts[:at]], opts) + self.class.inject_attributes_at(hash[at], opts) end end hash end alias_method_chain after, :inject end def inject_class_methods(after) define_singleton_method("#{after}_with_inject") do |*args| hash = send("#{after}_without_inject".to_sym, *args) - @rules[after].each do |opts| - if opts[:at].nil? or opts[:at].is_a? String - hash = update_using_json_path(hash, opts) + rules_group_by_at = @rules[after].group_by { |e| e[:at] } + rules_group_by_at.each do |at, opts| + if at.nil? or at.is_a? String + hash = update_using_json_path(hash, at, opts) else - inject_attributes_at(hash[opts[:at]], opts) + inject_attributes_at(hash[at], opts) end end hash end self.singleton_class.send(:alias_method_chain, after, :inject) end def inject_attributes_at(hash_offset, opts) return hash_offset if hash_offset.nil? or hash_offset.empty? - keys = hash_offset[opts[:using]] - entity_name = __entity__(opts[:bucket_name] || opts[:using]) - values = Looksist.redis_service.send("#{entity_name}_for", keys) - if opts[:populate].is_a? Array - opts[:populate].each do |elt| - value_hash = values.each_with_object([]) do |i, acc| - acc << JSON.parse(i || '{}').deep_symbolize_keys[elt] + opts.each do |opt| + keys = hash_offset[opt[:using]] + entity_name = __entity__(opt[:bucket_name] || opt[:using]) + values = Looksist.redis_service.send("#{entity_name}_for", keys) + if opt[:populate].is_a? Array + opt[:populate].each do |elt| + value_hash = values.each_with_object([]) do |i, acc| + acc << JSON.parse(i || '{}').deep_symbolize_keys[elt] + end + alias_method = find_alias(opt[:as], elt) + hash_offset[alias_method] = value_hash end - alias_method = find_alias(opts[:as], elt) - hash_offset[alias_method] = value_hash + else + alias_method = find_alias(opt[:as], opt[:populate]) + hash_offset[alias_method] = values end - else - alias_method = find_alias(opts[:as], opts[:populate]) - hash_offset[alias_method] = values - hash_offset end + hash_offset end - def update_using_json_path(hash, opts) + def update_using_json_path(hash, at, opts) if hash.is_a?(Hash) - if opts[:at].present? - JsonPath.for(hash.with_indifferent_access).gsub!(opts[:at]) do |i| - i.is_a?(Array) ? inject_attributes_for(i, opts) : inject_attributes_at(i, opts) unless (i.nil? or i.empty?) + if at.present? + JsonPath.for(hash.with_indifferent_access).gsub!(at) do |i| + i.is_a?(Array) ? inject_attributes_for(i, at, opts) : inject_attributes_at(i, opts) unless (i.nil? or i.empty?) i end else inject_attributes_at(hash, opts) - end.to_hash.deep_symbolize_keys else - inject_attributes_for_array(hash, opts) + inject_attributes_for_array(hash, at, opts) end end - def inject_attributes_for(array_of_hashes, opts) - entity_name = __entity__(opts[:bucket_name] || opts[:using]) - keys = (array_of_hashes.collect { |i| i[opts[:using]] }).compact.uniq - values = Hash[keys.zip(Looksist.redis_service.send("#{entity_name}_for", keys))] - opts[:populate].is_a?(Array) ? composite_attribute_lookup(array_of_hashes, opts, values) : single_attribute_lookup(array_of_hashes, opts, values) - end - - def inject_attributes_for_array(array_of_hashes, opts) - entity_name = __entity__(opts[:bucket_name] || opts[:using]) - modified_array = if opts[:at].nil? - array_of_hashes.map(&:values) - else - json_path = JsonPath.new("#{opts[:at]}..#{opts[:using]}") - json_path.on(array_of_hashes.to_json) - end - keys = modified_array.flatten.compact.uniq - values = Hash[keys.zip(Looksist.redis_service.send("#{entity_name}_for", keys))] - opts[:populate].is_a?(Array) ? composite_attribute_lookup(array_of_hashes, opts, values) : single_attribute_lookup_for_array(array_of_hashes, opts, values) - end - - def single_attribute_lookup(array_of_hashes, opts, values) - array_of_hashes.each do |elt| - alias_method = find_alias(opts[:as], opts[:populate]) - elt[alias_method] = values[elt[opts[:using]]] + def inject_attributes_for(array_of_hashes, at, opts) + all_values = opts.each_with_object({}) do |opt, acc| + entity_name = __entity__(opt[:bucket_name] || opt[:using]) + keys = (array_of_hashes.collect { |i| i[opt[:using]] }).compact.uniq + values = Hash[keys.zip(Looksist.redis_service.send("#{entity_name}_for", keys))] + acc[opt[:using]] = values end + smart_lookup(array_of_hashes, opts, all_values, nil) end - def single_attribute_lookup_for_array(array_of_hashes, opts, values) - array_of_hashes.collect do |elt| - alias_method = find_alias(opts[:as], opts[:populate]) - if opts[:at].present? - JsonPath.for(elt.with_indifferent_access).gsub!(opts[:at]) do |node| - if node.is_a? Array - node.each { |x| x[alias_method] = values[x.with_indifferent_access[opts[:using]]] } - else - node[alias_method] = values[node.with_indifferent_access[opts[:using]]] - end - node - end.to_hash.deep_symbolize_keys - else - elt[alias_method] = values[elt[opts[:using]]] - elt - end + def inject_attributes_for_array(array_of_hashes, at, opts) + all_values = opts.each_with_object({}) do |opt, acc| + entity_name = __entity__(opt[:bucket_name] || opt[:using]) + modified_array = if at.nil? + array_of_hashes.map(&:values) + else + json_path = JsonPath.new("#{at}..#{opt[:using]}") + json_path.on(array_of_hashes.to_json) + end + keys = modified_array.flatten.compact.uniq + values = Hash[keys.zip(Looksist.redis_service.send("#{entity_name}_for", keys))] + acc[opt[:using]] = values end + smart_lookup(array_of_hashes, opts, all_values, at) end - def composite_attribute_lookup(array_of_hashes, opts, values) + def smart_lookup(array_of_hashes, opts, all_values, at) + ## populate is not a array array_of_hashes.collect do |elt| - if opts[:at].present? - JsonPath.for(elt.with_indifferent_access).gsub!(opts[:at]) do |node| + if at.present? + JsonPath.for(elt.with_indifferent_access).gsub!(at) do |node| if node.is_a? Array - node.collect do |x| - opts[:populate].collect do |_key| - alias_method = find_alias(opts[:as], _key) - parsed_key = JSON.parse(values[x.with_indifferent_access[opts[:using]]]).deep_symbolize_keys - x[alias_method] = parsed_key[_key] + node.each do |x| + opts.each do |opt| + values = all_values[opt[:using]] + do_populate(x, values, opt[:using], opt[:as], opt[:populate]) end end else - parsed_key = JSON.parse(values[node.with_indifferent_access[opts[:using]]]).deep_symbolize_keys - opts[:populate].collect do |_key| - alias_method = find_alias(opts[:as], _key) - node[alias_method] = parsed_key[_key] + opts.each do |opt| + values = all_values[opt[:using]] + do_populate(node, values, opt[:using], opt[:as], opt[:populate]) end end node end.to_hash.deep_symbolize_keys else - parsed_key = JSON.parse(values[elt[opts[:using]]]).deep_symbolize_keys - opts[:populate].collect do |_key| - alias_method = find_alias(opts[:as], _key) - elt[alias_method] = parsed_key[_key] + opts.each do |opt| + values = all_values[opt[:using]] + do_populate(elt, values, opt[:using], opt[:as], opt[:populate]) end elt end end end + + def do_populate(elt, values, using, as, populate) + if populate.is_a? Array + populate.collect do |_key| + alias_method = find_alias(as, _key) + parsed_key = JSON.parse(values[elt.with_indifferent_access[using]]).deep_symbolize_keys + elt[alias_method] = parsed_key[_key] + end + else + alias_method = find_alias(as, populate) + elt[alias_method] = values[elt.with_indifferent_access[using]] + end + end + def __entity__(entity) entity.to_s.gsub('_id', '') end