require 'stockboy/attribute_map'
require 'stockboy/mapped_record'
require 'stockboy/source_record'
require 'stockboy/translations'
module Stockboy
class CandidateRecord
def initialize(attrs, map)
@map = map
@table = reuse_frozen_hash_keys(attrs, map)
@tr_table = Hash.new
@ignored_fields = []
freeze
end
def to_hash
bulk_hash.tap do |out|
tmp_context = SourceRecord.new(out, @table)
@map.each_with_object(out) do |col|
out.delete(col.to) if ignore?(col, tmp_context)
end
end
end
alias_method :attributes, :to_hash
def bulk_hash
Hash.new.tap do |out|
@map.each { |col| out[col.to] = translate(col) }
end
end
def raw_hash
Hash.new.tap do |out|
@map.each { |col| out[col.to] = @table[col.from] }
end
end
alias_method :raw_attributes, :raw_hash
def to_model(model)
model.new(attributes)
end
def partition(filters={})
input, output = self.input, self.output
filters.each_pair do |filter_key, f|
if f.call(input, output)
return filter_key
end
end
nil
end
def input
SourceRecord.new(raw_hash, @table)
end
def output
MappedRecord.new(bulk_hash)
end
private
def translate(col)
@tr_table.fetch(col.to) do |key|
return @tr_table[key] = sanitize(@table[col.from]) if col.translators.empty?
fields = raw_hash
tr_input = col.translators.reduce(input) do |value, tr|
begin
fields[key] = tr[value]
SourceRecord.new(fields, @table)
rescue
fields[key] = nil
break SourceRecord.new(fields, @table)
end
end
@tr_table[key] = tr_input.public_send(key)
end
end
def ignore?(col, context)
return true if @ignored_fields.include? col.to
if col.ignore?(context)
@ignored_fields << col.to
true
else
false
end
end
def sanitize(value)
case value
when String value.to_s
else
value
end
end
def reuse_frozen_hash_keys(attrs, map)
return attrs unless attrs.is_a? Hash
attrs.reduce(Hash.new) do |new_hash, (field, value)|
key = map.attribute_from(field).from
new_hash[key] = value
new_hash
end
end
end
end