avit/stockboy

View on GitHub
lib/stockboy/mapped_record.rb

Summary

Maintainability
A
0 mins
Test Coverage
module Stockboy

  # This represents the "output" side of a {CandidateRecord}
  #
  # Based on the current attribute map, it will have reader methods for the
  # output values of each attribute. This is similar to an OpenStruct, but
  # more efficient since we cache the defined methods.
  #
  # @example
  #   output = MappedRecord.new(first_name: "Zaphod")
  #   output.first_name # => "Zaphod"
  #
  class MappedRecord

    # This is an optimization to avoid relying on method_missing.
    #
    # This module holds a pool of already-defined accessor methods for sets of
    # record attributes. Each set of methods is held in a module that gets
    # extended into new MappedRecords.
    #
    # @visibility private
    #
    module AccessorMethods
      def self.for(attrs)
        @module_registry        ||= Hash.new
        @module_registry[attrs] ||= build_module(attrs)
      end

      def self.build_module(attr_accessor_keys)
        Module.new do
          attr_accessor_keys.each do |key|
            define_method key do
              @fields[key]
            end
          end
        end
      end
    end

    # Initialize a new MappedRecord
    #
    # @param [Hash<Symbol>] fields
    #   Keys map to reader methods
    #
    def initialize(fields)
      mod = AccessorMethods.for(fields.keys)
      extend mod
      @fields = fields
      freeze
    end
  end
end