FinalCAD/csv_row_model

View on GitHub
lib/csv_row_model/concerns/attributes_base.rb

Summary

Maintainability
A
0 mins
Test Coverage
require 'csv_row_model/concerns/model/attributes'
require 'csv_row_model/concerns/hidden_module'

# Shared between Import and Export, see test fixture for basic setup
module CsvRowModel
  module AttributesBase
    extend ActiveSupport::Concern
    include Model::Attributes
    include HiddenModule

    # @return [Hash] a map of `column_name => public_send(column_name)`
    def attributes
      attributes_from_method_names self.class.column_names
    end

    # Export:
    # source_value - row_model.column1 --> source_model.column1
    # formatted_value - format_cell(source_value)
    # vale - formatted_value
    #
    # Import:
    # source_value - form source_row
    # formatted_value - format_cell(source_value)
    # value - calculated_value from a bunch of stuff
    ATTRIBUTE_METHODS = {
      original_attributes: :value, # a map of `column_name => original_attribute(column_name)`
      formatted_attributes: :formatted_value, # a map of `column_name => format_cell(column_name, ...)`
      source_attributes: :source_value # a map of `column_name => source (source_row[index_of_column_name] or row_model.public_send(column_name)) `
    }.freeze
    ATTRIBUTE_METHODS.each do |method_name, attribute_method|
      define_method(method_name) do
        column_names_to_attribute_value(self.class.column_names, attribute_method)
      end
    end

    # @return [Object] the column's attribute (the csv_row_model default value to be used for import/export)
    def original_attribute(column_name)
      attribute_objects[column_name].try(:value)
    end

    def to_json
      attributes.to_json
    end

    def eql?(other)
      other.try(:attributes) == attributes
    end

    def hash
      attributes.hash
    end

    protected
    def attributes_from_method_names(column_names)
      array_to_block_hash(column_names) { |column_name| try(column_name) }
    end

    def column_names_to_attribute_value(column_names, attribute_method)
      array_to_block_hash(column_names) { |column_name| attribute_objects[column_name].public_send(attribute_method)}
    end

    def array_to_block_hash(array, &block)
      array.zip(array.map(&block)).to_h
    end

    class_methods do
      protected
      # See {Model#column}
      def column(column_name, options={})
        super
        define_attribute_method(column_name)
      end

      # Define default attribute method for a column
      # @param column_name [Symbol] the cell's column_name
      def define_attribute_method(column_name, &block)
        return if method_defined? column_name
        define_proxy_method(column_name, &block)
      end

      def ensure_attribute_method
        self.column_names.each { |*args| define_attribute_method(*args) }
      end
    end
  end
end