class ReeMapper::MapperFactory
def self.call(register_as: nil, &blk)
def self.call(register_as: nil, &blk) ReeMapper::MapperFactoryProxy.new(self, register_as: register_as, &blk) end
def self.register(name, type)
def self.register(name, type) raise ArgumentError, "name of mapper type should not include `?`" if name.to_s.end_with?('?') raise ArgumentError, "type :#{name} already registered" if types.key?(name) raise ArgumentError, "method :#{name} already defined" if method_defined?(name) type = type.dup type.name = name type.freeze types[name] = type class_eval(<<~RUBY, __FILE__, __LINE__ + 1) def #{name}(field_name = nil, optional: false, **opts) raise ReeMapper::Error, "invalid DSL usage" unless @mapper raise ArgumentError, "array item can't be optional" if field_name.nil? && optional type = self.class.types.fetch(:#{name}) @mapper.strategy_methods.each do |method| next if type.respond_to?(method) raise ReeMapper::UnsupportedTypeError, "type :#{name} should implement method `\#{method}`" end return ReeMapper::Field.new(type, optional: optional, **opts) unless field_name @mapper.add_field(type, field_name, optional: optional, **opts) end def #{name}?(field_name, **opts) #{name}(field_name, optional: true, **opts) end RUBY self end
def self.register_type(name, object_type)
def self.register_type(name, object_type) register( name, ReeMapper::Mapper.build(strategies, object_type) ) end
def array(field_name = nil, each: nil, optional: false, key: nil, **opts, &blk)
def array(field_name = nil, each: nil, optional: false, key: nil, **opts, &blk) raise ReeMapper::Error, "invalid DSL usage" unless @mapper raise ArgumentError, "array item can't be optional" if field_name.nil? && optional raise ArgumentError, 'array type should use either :each or :block' if each && blk || !each && !blk raise ArgumentError, 'invalid :key option value' unless HASH_KEY_OPTION_VALUES.include?(key) if blk each = ReeMapper::Field.new( hash_from_blk(key: key, &blk) ) end type = ReeMapper::Mapper.build(@mapper.strategies, ReeMapper::Array.new(each)) return ReeMapper::Field.new(type, optional: optional, **opts) unless field_name @mapper.add_field(type, field_name, optional: optional, **opts) end
def array?(field_name, each:, **opts)
def array?(field_name, each:, **opts) raise ArgumentError if opts.key?(:optional) array(field_name, each: each, optional: true, **opts) end
def hash(field_name, key: nil, **opts, &blk)
def hash(field_name, key: nil, **opts, &blk) raise ReeMapper::Error, "invalid DSL usage" unless @mapper raise ArgumentError, 'invalid :key option value' unless HASH_KEY_OPTION_VALUES.include?(key) type = hash_from_blk(key: key, &blk) @mapper.add_field(type, field_name, **opts) end
def hash?(field_name, **opts, &blk)
def hash?(field_name, **opts, &blk) hash(field_name, optional: true, **opts, &blk) end
def hash_from_blk(key:, &blk)
def hash_from_blk(key:, &blk) mapper_proxy = self.class.call strategies = @mapper.strategies.map do |strategy| strategy = strategy.dup output = strategy.output if key strategy.output = HASH_KEY_OPTION_MAP.fetch(key).new elsif !(output.is_a?(ReeMapper::SymbolKeyHashOutput) || output.is_a?(ReeMapper::StringKeyHashOutput)) strategy.output = ReeMapper::SymbolKeyHashOutput.new end strategy end strategies[0..-2].each do |strategy| mapper_proxy.use(strategy) end _hsh_mapper = mapper_proxy.use(strategies.last, &blk) end
def initialize(mapper)
def initialize(mapper) @mapper = mapper end