class ACH::Component
Base class for ACH::File
and ACH::Batch
. Every component has its own number of entities, header and control records. So it provides ACH::Component#header
, ACH::Component#control
, ACH::Component.has_many
methods to manage them.
Example¶ ↑
class File < Component has_many :batches # implementation end
Attributes
Public Class Methods
Creates a has_many
association.
Example¶ ↑
class File < Component has_many :batches end file = File.new do batch :foo => 1, :bar => 2 end file.batches # => [#<Batch ...>]
The example above extends File
with batches and batch instance methods:
-
batch is used to add new instance of
Batch
. -
batches is used to get an array of batches which belong to file.
@param [Symbol] plural_name @param [Hash] options
# File lib/ach/component.rb, line 195 def self.has_many(plural_name, options = {}) association = HasManyAssociation.new(plural_name, options) association_variable_name = "@#{plural_name}_association" association.delegation_methods.each do |method_name| delegate method_name, :to => association_variable_name end after_initialize_hooks << lambda{ instance_variable_set(association_variable_name, association.for(self)) } end
When inherited, clone class-related properties.
@param [Class] klass
# File lib/ach/component.rb, line 41 def self.inherited(klass) klass.default_attributes = default_attributes.dup klass.after_initialize_hooks = after_initialize_hooks.dup end
Uses method_missing
pattern to specify default attributes for a Component
. If method name is one of the defined rules, saves it to default_attributes
hash.
These attributes are passed to inner components in a cascade way, i.e. when ACH
File
was defined with default value for ‘company_name’, this value will be passed to every Batch
component within file, and from every Batch
to corresponding batch header record.
Note that default values may be overwritten when building records.
@param [Symbol] meth @param [*Object] args
# File lib/ach/component.rb, line 59 def self.method_missing(meth, *args) if Formatter.defined?(meth) default_attributes[meth] = args.first else super end end
Initialize component with field values. If block is given, it is evaluated in context of component, allowing setting fields via method calls and declarations of nested components.
@param [Hash] fields @raise [UnknownAttributeError]
# File lib/ach/component.rb, line 73 def initialize(fields = {}) @attributes = self.class.default_attributes.dup fields.each do |name, value| raise UnknownAttributeError.new(name, self) unless Formatter.defined?(name) @attributes[name] = value end after_initialize instance_eval(&Proc.new) if block_given? end
Public Instance Methods
Execute all Proc
objects contained in the after_initialize_hooks
array in the context of the object.
# File lib/ach/component.rb, line 171 def after_initialize self.class.after_initialize_hooks.each{ |hook| instance_exec(&hook) } end
Build a component-related Control
record from a given string.
@param [String] str @return [ACH::Record::Base]
# File lib/ach/component.rb, line 151 def build_control(str) @control = self.class::Control.from_s(str) end
Build a component (File
or Batch
) related Header
record from a given string.
@param [String] str @return [ACH::Record::Base]
# File lib/ach/component.rb, line 132 def build_header(str) @header = self.class::Header.from_s(str) end
Build a component-related Control
record.
@return [ACH::Record::Base]
# File lib/ach/component.rb, line 139 def control @control ||= begin klass = self.class::Control fields = klass.fields.select{ |f| respond_to?(f) || attributes[f] } klass.new Hash[*fields.zip(fields.map{ |f| send(f) }).flatten] end end
Return a set of fields, that is a subset of attributes
that can be used to initialize an instance of a klass
. Component
uses attributes
itself.
@param [Class] klass @return [Hash]
# File lib/ach/component.rb, line 160 def fields_for(klass) if klass < Component attributes else attrs = attributes.find_all{ |k, v| klass.fields.include?(k) && attributes[k] } Hash[*attrs.flatten] end end
Sets header fields if fields or block passed. Returns header record.
Example 1¶ ↑
header :foo => "value 1", :bar => "value 2"
Example 2¶ ↑
header do foo "value 1" bar "value 2" end
Example 3¶ ↑
header # => just returns a header object
# File lib/ach/component.rb, line 119 def header(fields = {}) before_header merged_fields = fields_for(self.class::Header).merge(fields) @header ||= self.class::Header.new(merged_fields) @header.tap do |head| head.instance_eval(&Proc.new) if block_given? end end
Missing messages are treated as accessor methods for a component if their message name is defined by {ACH::Formatter}.
@param [Symbol] meth @param [*Object] args @return [String]
# File lib/ach/component.rb, line 89 def method_missing(meth, *args) if Formatter.defined?(meth) args.empty? ? @attributes[meth] : (@attributes[meth] = args.first) else super end end
Private Instance Methods
Hook that is called whenever component header record is created. To be overridden in subclasses.
# File lib/ach/component.rb, line 99 def before_header end