Module: Ripple::NestedAttributes::ClassMethods

Defined in:
lib/ripple/nested_attributes.rb

Overview

Nested Attributes

This is similar to the accepts_nested_attributes functionality as found in AR. This allows the use update attributes and create new child records through the parent. It also allows the use of the fields_for form view helper, using a presenter pattern.

To enable in the model, call the class method, using the same relationship as defined in the one or many.

class Shipment
include Ripple::Document
one :box
many :addresses
accepts_nested_attributes_for :box, :addresses
end

One

Given this model:

class Shipment
include Ripple::Document
one :box
accepts_nested_attributes_for :box
end

This allows creating a box child during creation:

shipment = Shipment.create(:box_attributes => { :shape => 'square' })
shipment.box.shape # => 'square'

This also allows updating box attributes:

shipment.update_attributes(:box_attributes => { :key => 'xxx', :shape => 'triangle' })
shipment.box.shape # => 'triangle'

Many

Given this model

class Manifest
include Ripple::Document
many :shipments
accepts_nested_attributes_for :shipments
end

This allows creating several shipments during manifest creation:

manifest = Manifest.create(:shipments_attributes => [ { :reference => "foo1" }, { :reference => "foo2" } ])
manifest.shipments.size # => 2
manifest.shipments.first.reference # => foo1
manifest.shipments.second.reference # => foo2

And updating shipment attributes:

manifest.update_attributes(:shipment_attributes => [ { :key => 'xxx', :reference => 'updated foo1' },
                                                   { :key => 'yyy', :reference => 'updated foo2' } ])
manifest.shipments.first.reference # => updated foo1
manifest.shipments.second.reference # => updated foo2

NOTE: On many embedded, then entire collection of embedded documents is replaced, as there is no key to specifically update.

Given

class Manifest
include Ripple::Documnet
many :signatures
accepts_nested_attributes_for :signatures
end

class Signature
include Ripple::EmbeddedDocument
property :esignature, String
end

The assigning of attributes replaces existing:

manifest = Manifest.create(:signature_attributes => [ { :esig => 'a00001' }, { :esig => 'b00001' } ]
manifest.signatures # => [<Signature esig="a00001">, <Signature esig="b00001">]

manifest.signature_attributes = [ { :esig => 'c00001' } ]
manifest.signatures # => [<Signature esig="c00001">]

Instance Method Summary collapse

Instance Method Details

#accepts_nested_attributes_for(*attr_names) ⇒ Object



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/ripple/nested_attributes.rb', line 111

def accepts_nested_attributes_for(*attr_names)
  options = { :allow_destroy => false }
  options.update(attr_names.extract_options!)

  attr_names.each do |association_name|
    if association = self.associations[association_name]
      nested_attributes_options[association_name.to_sym] = options

      define_method "#{association_name}_attributes=" do |attributes|
        send("assign_nested_attributes_for_#{association.type}_association",
          association_name, attributes
        )
      end

      before_save :"autosave_nested_attributes_for_#{association_name}"
      before_save :destroy_marked_for_destruction

      define_method "autosave_nested_attributes_for_#{association_name}" do
        if self.autosave[association_name]
          send("save_nested_attributes_for_#{association.type}_association",
            association_name
          )
        end
      end
      private :"autosave_nested_attributes_for_#{association_name}"

    else
      raise ArgumentError, "Association #{association_name} not found!"
    end
  end
end