module FreeForm::Nested::ClassMethods

Attributes

nested_forms[RW]

Nested Forms

Public Instance Methods

has_many(attribute, options={}, &block)
Alias for: nested_form
has_one(attribute, options={}, &block)
Alias for: nested_form
nested_form(attribute, options={}, &block) click to toggle source
# File lib/freeform/form/nested.rb, line 12
def nested_form(attribute, options={}, &block)
  # Initialize the instance variables on the parent class
  initialize_instance_variables(attribute)

  # Define new nested class
  klass = define_nested_class(attribute, options, &block)

  # Define methods for working with nested models
  define_nested_model_methods(attribute, klass)
end
Also aliased as: has_many, has_one

Protected Instance Methods

attribute_to_form_class(attribute) click to toggle source
# File lib/freeform/form/nested.rb, line 45
def attribute_to_form_class(attribute)
  singularized_attribute(attribute).camelize
end
define_nested_attribute_methods(attribute, nested_form_class) click to toggle source

TODO: Clean up this method!

# File lib/freeform/form/nested.rb, line 94
def define_nested_attribute_methods(attribute, nested_form_class)
  # Equivalent of "address_attributes=" for "address" attribute
  define_method(:"#{attribute}_attributes=") do |params|
    build_models_from_param_count(attribute, params)

    self.send(:"#{attribute}").zip(params).each do |model, params_array|
      identifier = params_array[0]
      attributes = params_array[1]
      #TODO: Check the key against id?
      model.fill(attributes)
    end
  end
end
define_nested_class(attribute, options={}, &block) click to toggle source
# File lib/freeform/form/nested.rb, line 49
def define_nested_class(attribute, options={}, &block)
  # Define new nested class
  klass = Class.new(FreeForm::Form) do
  end

  # Add whatever passed in methods, properties, etc. to the class
  if block_given?
    klass.class_eval(&block)
  end

  # Set the class name
  form_class = attribute_to_form_class(attribute)
  parent_class.const_set(form_class, klass)

  # Register the class as being nested under the current class
  register_nested_form(klass)
  klass
end
define_nested_model_methods(attribute, form_class, options={}) click to toggle source
# File lib/freeform/form/nested.rb, line 68
def define_nested_model_methods(attribute, form_class, options={})
  singular = singularized_attribute(attribute)

  # Example: form.build_addresses (optional custom initializer)
  define_method(:"build_#{attribute}") do |initializer=nil|
    initializer ||= self.send("#{singular}_initializer")

    form_class.new(initializer).tap do |obj|
      # Add new object to parent model collection (e.g. the new address is in parent.addresses)
      current_models = self.send(attribute)
      current_models ||= []
      current_models << obj
      self.send("#{attribute}=", current_models)
    end
  end
  alias_method :"build_#{singular}", :"build_#{attribute}"

  # Define methods for working with nested models
  define_nested_attribute_methods(attribute, form_class)
end
initialize_instance_variables(attribute) click to toggle source
# File lib/freeform/form/nested.rb, line 26
def initialize_instance_variables(attribute)
  declared_model attribute

  define_method(:"#{attribute}") do
    value = instance_variable_get("@nested_#{attribute}")
    value ||= []
    instance_variable_set("@nested_#{attribute}", value)
  end
end
parent_class() click to toggle source
# File lib/freeform/form/nested.rb, line 41
def parent_class
  self
end
register_nested_form(klass) click to toggle source
# File lib/freeform/form/nested.rb, line 36
def register_nested_form(klass)
  @nested_forms ||= []
  @nested_forms << klass
end
singularized_attribute(attribute) click to toggle source
# File lib/freeform/form/nested.rb, line 89
def singularized_attribute(attribute)
  attribute.to_s.singularize
end