class RedMatryoshka::Doll

Constants

KEY_SEPARATOR

Public Class Methods

new(hash, cache_klass = nil) click to toggle source
# File lib/red_matryoshka/doll.rb, line 5
def initialize(hash, cache_klass = nil)
  @hash = hash
  @cache_klass = cache_klass
end

Public Instance Methods

expand() click to toggle source
# File lib/red_matryoshka/doll.rb, line 10
def expand
  @hash.inject({}) do |hash, (k, v)|
    row = expand_row k, v

    if array_with_hashes?(row)
      array_deep_merge hash, row
    else
      hash.deep_merge row
    end
  end
end
flatten() click to toggle source
# File lib/red_matryoshka/doll.rb, line 22
def flatten
  @hash.inject({}) { |flatten_hash, (k, v)| flatten_hash.merge flatten_row([], k, v) }
end

Private Instance Methods

array_deep_merge(main_hash, new_row) click to toggle source
# File lib/red_matryoshka/doll.rb, line 66
def array_deep_merge(main_hash, new_row)
  # Validate if the new row if part of the main hash
  key = new_row.keys.first
  id = new_row.values.flatten.first[:id]

  if main_hash[key].present?
    # Validate if hash with id already in hash
    # It will be useful for the deep merge
    array_hash_index = main_hash[key].find_index { |hash| hash[:id] == id }
  end

  new_row[key].each do |hash|
    if array_hash_index.present?
      main_hash[key][array_hash_index].deep_merge! hash
    else
      main_hash[key] = [] if main_hash[key].nil?
      main_hash[key] << hash
    end
  end

  main_hash
end
array_with_hashes?(row) click to toggle source
# File lib/red_matryoshka/doll.rb, line 89
def array_with_hashes?(row)
  row.values[0].is_a?(Array) && row.values[0][0].is_a?(Hash)
end
cache_klass_with_module(klass) click to toggle source
# File lib/red_matryoshka/doll.rb, line 113
def cache_klass_with_module(klass)
  if RedMatryoshka.configuration.module.present?
    "#{RedMatryoshka.configuration.module}::#{klass}"
  else
    klass
  end
end
dependent_klass?(transform_klass) click to toggle source
# File lib/red_matryoshka/doll.rb, line 103
def dependent_klass?(transform_klass)
  !@cache_klass.classes_to_depends_on.nil? &&
    @cache_klass.classes_to_depends_on.include?(transform_klass)
end
expand_row(key, value) click to toggle source
# File lib/red_matryoshka/doll.rb, line 28
def expand_row(key, value)
  return { key.to_sym => expand_value(value) } unless key.to_s.include? KEY_SEPARATOR

  split_keys = key.split KEY_SEPARATOR
  key = split_keys.shift
  id_hash = {}
  transform_klass = RedMatryoshka::Base.transformed_class(key)

  if dependent_klass?(transform_klass)
    key = row_key(transform_klass)
    id_hash = { id: split_keys.shift }
  end

  expended_row = id_hash.merge expand_row(split_keys.join(KEY_SEPARATOR), value)
  expended_row = [expended_row] if expend_in_array? transform_klass

  { key.to_sym => expended_row }
end
expand_value(value) click to toggle source
# File lib/red_matryoshka/doll.rb, line 108
def expand_value(value)
  return value if value.is_a?(Hash) || value.is_a?(Array)
  value.to_s
end
expend_in_array?(transform_klass) click to toggle source
# File lib/red_matryoshka/doll.rb, line 93
def expend_in_array?(transform_klass)
  @cache_klass.classes_to_depends_on.keys.include?(transform_klass) &&
    @cache_klass.classes_to_depends_on[transform_klass][:as] == :array
end
flatten_row(flat_key, key, value) click to toggle source
# File lib/red_matryoshka/doll.rb, line 47
def flatten_row(flat_key, key, value)
  new_flat_key = flat_key + [key]

  if value.is_a? Hash
    value.inject({}) { |hash, (k, v)| hash.merge flatten_row(new_flat_key, k, v) }
  elsif value.is_a?(Array) && !value.any?
    {} # In some case, an array expecting ids, could be empty
  elsif value.is_a?(Array) && value.any? && value[0].is_a?(Hash)
    value.inject({}) do |hashes, hash|
      hash.each do |k, v|
        hashes.merge! flatten_row(new_flat_key + [hash[:id].to_s], k, v)
      end
      hashes
    end
  else
    { new_flat_key.join(KEY_SEPARATOR) => value.to_s }
  end
end
row_key(transform_klass) click to toggle source
# File lib/red_matryoshka/doll.rb, line 98
def row_key(transform_klass)
  @cache_klass.classes_to_depends_on[transform_klass][:for] ||
    cache_klass_with_module(transform_klass).constantize.class_to_fetch_from.downcase
end