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