module HashToModelMapper

Constants

VERSION

Public Class Methods

call(model_name, type = nil, source) click to toggle source
# File lib/hash_to_model_mapper.rb, line 37
def self.call(model_name, type = nil, source)
  raise('source needs to be present') unless source.present?

  instance = model_name.to_s.classify.constantize.new
  instance.readonly!
  mapper = registry[model_name][type] || raise("Mapper not defined for #{model_name} -> #{type}")
  attributes = mapper.attributes

  case source
  when Hash
    source = source.with_indifferent_access
    get_value = ->(path) { source.dig(*path) }
  else
    get_value = ->(path) { path.reduce(source) { |source, method| source.__send__(method) } }
  end

  attributes.each do |attribute_name, path|
    value = if path.respond_to? :call
              path.call(source)
            elsif path.first.respond_to? :call
              path.first.call(source)
            else
              get_value.call(path)
            end

    if (transformer = mapper.transformers[attribute_name])
      if transformer.is_a? Hash
        old_value = value
        value = transformer.with_indifferent_access[value]

        if value.nil? && !transformer.keys.any? { |key| key == :nil }
          raise("Key not present in tansformer: \
                Wrong key: #{old_value}\
                Valid keys: #{transformer.keys.inspect}\
                Path: #{path}")
        end

      elsif transformer.respond_to? :call
        value = transformer.call(value)
      else
        raise('transformer is neither a hash or a callable object')
      end
    end
    instance.__send__("#{attribute_name}=", value)
  end

  instance.id = nil if instance.respond_to? :id

  instance
end
define(&block) click to toggle source
# File lib/hash_to_model_mapper.rb, line 32
def self.define(&block)
  definition_proxy = DefinitionProxy.new
  definition_proxy.instance_eval(&block)
end
defined_fields_for(model_name) click to toggle source
# File lib/hash_to_model_mapper.rb, line 24
def self.defined_fields_for(model_name)
  defined_mappings_for(model_name).values
                                  .map(&:attributes)
                                  .map(&:keys)
                                  .flatten
                                  .uniq
end
defined_mappings_for(model_name) click to toggle source
# File lib/hash_to_model_mapper.rb, line 20
def self.defined_mappings_for(model_name)
  @registry[model_name]
end
register(model_name, type, mapper) click to toggle source
# File lib/hash_to_model_mapper.rb, line 11
def self.register(model_name, type, mapper)
  @registry[model_name] ||= {}
  @registry[model_name][type] = mapper
end
registry() click to toggle source
# File lib/hash_to_model_mapper.rb, line 16
def self.registry
  @registry
end