Module: Moribus::Macros

Defined in:
lib/moribus/macros.rb

Overview

Declares a set of helper methods for more efficient use of aggregated and tracked models.

Instance Method Summary collapse

Instance Method Details

#delegate_associated(*args) ⇒ Object

For each of the passed arguments, which may either be method or association names, define its delegation to the specified association. If it responds to the effective reader, delegate to it. If the subject of delegation is a method name, delegate both reader and writer. If the subject of delegation is an association name, and the association was defined via the has_aggregated helper method, include the association’s delegation module, effectively using attribute readers, and write the associated object. See the example below for a more expressive explanation:

class CustomerAttributes < ActiveRecord::Base
  # has date_of_birth and is_military attributes
  acts_as_aggregated
end

class PersonName < ActiveRecord::Base
  # has first_name and last_name attributes
  acts_as_aggregated
end

class CustomerInfo < ActiveRecord::Base
  belongs_to :customer, :inverse_of => :customer_info

  has_aggregated :customer_attributes
  has_aggregated :person_name
  acts_as_tracked
end

class Customer < ActiveRecord::Base
  has_one_current :customer_info, :inverse_of => :customer

  delegate_associated :customer_attributes, :person_name, :to => :customer_info
end

customer = Customer.new
info = customer.effective_customer_info

# note here we're skipping info.person_name building for readers and writers.
info.first_name # => nil
info.first_name = 'John'
info.date_of_birth = Date.today

customer.first_name # => 'John'
customer.is_military = true
customer.is_military == info.is_military # => true
info.is_military == info.customer_attributes.is_military # => true


51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/moribus/macros.rb', line 51

def delegate_associated(*args)
  options = args.extract_options!
  name = options[:to] or raise ArgumentError.new(":to option should be provided")
  include Extensions::DelegateAssociated unless self < Extensions::DelegateAssociated
  effective_name = "effective_#{name}".to_sym.in?(instance_methods(false)) ? "effective_#{name}" : name
  klass = reflect_on_association(name).klass

  args.each do |association_name|
    delegate(association_name, :to => effective_name)

    if (association_reflection = klass.reflect_on_association(association_name)).present?
      self.classes_delegating_to += [association_reflection.klass]
      if association_reflection.respond_to?(:delegated_attribute_methods)
        delegate("effective_#{association_name}", :to => effective_name)
        include association_reflection.delegated_attribute_methods
      else
        delegate :"#{association_name}=", :to => effective_name
      end
    else
      delegate :"#{association_name}=", :to => effective_name
    end
  end
end