class Stockboy::CandidateRecord

Joins the raw data values to an attribute mapping to allow comparison of input/output values, conversion, and filtering

Public Class Methods

new(attrs, map) click to toggle source

Initialize a new candidate record

@param [Hash] attrs Raw key-values from source data @param [AttributeMap] map Mapping and translations

# File lib/stockboy/candidate_record.rb, line 18
def initialize(attrs, map)
  @map = map
  @table = reuse_frozen_hash_keys(attrs, map)
  @tr_table = Hash.new
  @ignored_fields = []
  freeze
end

Public Instance Methods

attributes()
Alias for: to_hash
bulk_hash() click to toggle source

Mapped output hash including ignored values

@return [Hash]

# File lib/stockboy/candidate_record.rb, line 44
def bulk_hash
  Hash.new.tap do |out|
    @map.each { |col| out[col.to] = translate(col) }
  end
end
input() click to toggle source

Data structure representing the record's raw input values

Values can be accessed like hash keys, or attribute names that correspond to a :from attribute mapping option

@return [SourceRecord] @example

input = candidate.input
input["RawEmail"] # => "ME@EXAMPLE.COM  "
input.email       # => "ME@EXAMPLE.COM  "
# File lib/stockboy/candidate_record.rb, line 96
def input
  SourceRecord.new(raw_hash, @table)
end
output() click to toggle source

Data structure representing the record's mapped & translated output values

@return [MappedRecord] @example

input = candidate.output
output.email       # => "me@example.com"
# File lib/stockboy/candidate_record.rb, line 107
def output
  MappedRecord.new(bulk_hash)
end
partition(filters={}) click to toggle source

Find the filter key that captures this record

@param [FilterChain] filters List of filters to apply @return [Symbol] Name of the matched filter

# File lib/stockboy/candidate_record.rb, line 75
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
raw_attributes()
Alias for: raw_hash
raw_hash() click to toggle source

Return the original values mapped to attribute keys

@return [Hash]

# File lib/stockboy/candidate_record.rb, line 54
def raw_hash
  Hash.new.tap do |out|
    @map.each { |col| out[col.to] = @table[col.from] }
  end
end
Also aliased as: raw_attributes
to_hash() click to toggle source

Convert the mapped output to a hash

@return [Hash]

# File lib/stockboy/candidate_record.rb, line 30
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
Also aliased as: attributes
to_model(model) click to toggle source

Wrap the mapped attributes in a new ActiveModel or ActiveRecord object

@param [Class] model ActiveModel class @return [Class] ActiveModel class

# File lib/stockboy/candidate_record.rb, line 66
def to_model(model)
  model.new(attributes)
end

Private Instance Methods

ignore?(col, context) click to toggle source
# File lib/stockboy/candidate_record.rb, line 131
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
reuse_frozen_hash_keys(attrs, map) click to toggle source

Optimization to reuse the same hash key string instances

The need for this is fixed for CSV in: bugs.ruby-lang.org/issues/9143 (ruby >= 2.1) and can be managed by applying str.freeze in other readers.

# File lib/stockboy/candidate_record.rb, line 157
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
sanitize(value) click to toggle source

Clean output values that are a subclass of a standard type

# File lib/stockboy/candidate_record.rb, line 143
def sanitize(value)
  case value
  when String # e.g. Nori::StringWithAttributes
    value.to_s
  else
    value
  end
end
translate(col) click to toggle source
# File lib/stockboy/candidate_record.rb, line 113
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
        translation_error = TranslationError.new(key, self)
        fields[key] = Stockboy.configuration.translation_error_handler.call(translation_error)
        break SourceRecord.new(fields, @table)
      end
    end
    @tr_table[key] = tr_input.public_send(key)
  end
end