Sha256: 37e9035a06b8cbac5a16b09412f3a4855a75ab73280fe7a9fdeb3ebea079ceaa

Contents?: true

Size: 1.7 KB

Versions: 1

Compression:

Stored size: 1.7 KB

Contents

module AttributeCartographer
  class InvalidArgumentError < StandardError; end

  class << self
    def included base
      base.send :extend, AttributeCartographer::ClassMethods
      base.send :include, AttributeCartographer::InstanceMethods
    end
  end

  module ClassMethods
    def map *args
      @mapper ||= {}

      (from, to), (f1, f2) = args.partition { |a| !(Proc === a) }

      passthrough = ->(v) { v }
      f1 ||= passthrough

      if Array === from
        if f1.arity == 1
          from.each { |k| @mapper[k] = [k, f1] }
        else
          from.each { |k| @mapper[k] = f1 }
        end
      else
        raise AttributeCartographer::InvalidArgumentError if to && f1.arity == 2

        to ||= from
        @mapper[from] = (f1.arity == 1 ? [to, f1] : f1)
        @mapper[to] = [from, (f2 ? f2 : passthrough)] if to != from
      end
    end
  end

  module InstanceMethods
    def initialize attributes
      @_original_attributes = attributes
      @_mapped_attributes = {}

      map_attributes! attributes

      super
    end

    def original_attributes
      @_original_attributes
    end

    def mapped_attributes
      @_mapped_attributes
    end

  private

    def map_attributes! attributes
      mapper = self.class.instance_variable_get(:@mapper)
      return unless mapper

      (mapper.keys & attributes.keys).each do |key|
        mapping = mapper[key]

        if Array === mapping
          mapped_key, f = mapping
          value = f.call(attributes[key])
        else
          mapped_key, value = mapping.call(key, attributes[key])
        end

        self.send :define_singleton_method, mapped_key, ->{ value }
        @_mapped_attributes[mapped_key] = value
      end
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
attribute_cartographer-0.0.5 lib/attribute_cartographer.rb