mm-nested-attributes 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ # The list of files that should be ignored by Mr Bones.
2
+ # Lines that start with '#' are comments.
3
+ #
4
+ # A .gitignore file can be used instead by setting it as the ignore
5
+ # file in your Rakefile:
6
+ #
7
+ # Bones {
8
+ # ignore_file '.gitignore'
9
+ # }
10
+ #
11
+ # For a project with a C extension, the following would be a good set of
12
+ # exclude patterns (uncomment them if you want to use them):
13
+ # *.[oa]
14
+ # *~
15
+ announcement.txt
16
+ coverage
17
+ doc
18
+ pkg
data/History.txt ADDED
@@ -0,0 +1,2 @@
1
+ == 0.1.0 / 2010-07-10
2
+ * Nested attributes functionality for collections.
data/README.txt ADDED
@@ -0,0 +1,62 @@
1
+ mm-nested-attributes
2
+ by Toni Tuominen
3
+ http://github.com/tjtuom/mm-nested-attributes
4
+
5
+ == DESCRIPTION:
6
+
7
+ A port of ActiveRecord's nested attributes functionality for MongoMapper.
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ At the moment only collection functionality is supported.
12
+
13
+ == SYNOPSIS:
14
+
15
+ class Parent
16
+ include MongoMapper::Document
17
+ plugin MongoMapper::Plugins::Associations::NestedAttributes
18
+
19
+ many :children
20
+ accepts_nested_attributes_for :children
21
+ end
22
+
23
+ class Child
24
+ include MongoMapper::Document
25
+
26
+ key :foo, String
27
+ end
28
+
29
+ == REQUIREMENTS:
30
+
31
+ * MongoMapper
32
+
33
+ == INSTALL:
34
+
35
+ Add
36
+ gem 'mm-nested-attributes'
37
+ to your Gemfile.
38
+
39
+ == LICENSE:
40
+
41
+ (The MIT License)
42
+
43
+ Copyright (c) 2010
44
+
45
+ Permission is hereby granted, free of charge, to any person obtaining
46
+ a copy of this software and associated documentation files (the
47
+ 'Software'), to deal in the Software without restriction, including
48
+ without limitation the rights to use, copy, modify, merge, publish,
49
+ distribute, sublicense, and/or sell copies of the Software, and to
50
+ permit persons to whom the Software is furnished to do so, subject to
51
+ the following conditions:
52
+
53
+ The above copyright notice and this permission notice shall be
54
+ included in all copies or substantial portions of the Software.
55
+
56
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
57
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
58
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
59
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
60
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
61
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
62
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,23 @@
1
+
2
+ begin
3
+ require 'bones'
4
+ rescue LoadError
5
+ abort '### Please install the "bones" gem ###'
6
+ end
7
+
8
+ task :default => 'spec:run'
9
+ task 'gem:release' => 'spec:run'
10
+
11
+ Bones {
12
+ name 'mm-nested-attributes'
13
+ authors 'Toni Tuominen'
14
+ email 'toni@piranhadigital.fi'
15
+ url 'http://github.com/tjtuom/mm-nested-attributes'
16
+
17
+ ignore_file '.gitignore'
18
+
19
+ depend_on 'mongo_mapper', '0.8.2'
20
+
21
+ depend_on 'rspec', :development => true
22
+ }
23
+
@@ -0,0 +1,36 @@
1
+ require 'mongo_mapper/plugins/associations/nested_attributes'
2
+
3
+ module MongoMapper
4
+ module Plugins
5
+ module Document
6
+ module InstanceMethods
7
+ def mark_for_destruction
8
+ @marked_for_destruction = true
9
+ end
10
+
11
+ def marked_for_destruction?
12
+ @marked_for_destruction
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ module MongoMapper
20
+ module Plugins
21
+ module Associations
22
+ class ManyDocumentsProxy
23
+ def save_to_collection_with_delete(options={})
24
+ if @target
25
+ to_delete = @target.delete_if { |doc| doc.marked_for_destruction? }
26
+ to_delete.each { |doc| doc.destroy }
27
+ end
28
+ save_to_collection_without_delete(options)
29
+ end
30
+
31
+ alias :save_to_collection_without_delete :save_to_collection
32
+ alias :save_to_collection :save_to_collection_with_delete
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,124 @@
1
+ module MongoMapper
2
+
3
+ class TooManyRecords < MongoMapper::Error
4
+ end
5
+
6
+ module Plugins
7
+ module Associations
8
+ module NestedAttributes
9
+
10
+ REJECT_ALL_BLANK_PROC = proc { |attributes| attributes.all? { |_, value| value.blank? } }
11
+
12
+ def self.configure(model)
13
+ model.class_eval do
14
+ class_inheritable_accessor :nested_attributes_options, :instance_writer => false
15
+ self.nested_attributes_options = {}
16
+ end
17
+ end
18
+
19
+ module ClassMethods
20
+ def accepts_nested_attributes_for(*attr_names)
21
+ options = { :allow_destroy => false, :update_only => false }
22
+ options.update(attr_names.extract_options!)
23
+ options.assert_valid_keys(:allow_destroy, :reject_if, :limit, :update_only)
24
+ options[:reject_if] = REJECT_ALL_BLANK_PROC if options[:reject_if] == :all_blank
25
+
26
+ attr_names.each do |association_name|
27
+ if association = associations[association_name]
28
+ type = (association.many? ? :collection : :one_to_one)
29
+ nested_attributes_options[association_name.to_sym] = options
30
+
31
+ class_eval %{
32
+ if method_defined?(:#{association_name}_attributes=)
33
+ remove_method(:#{association_name}_attributes=)
34
+ end
35
+ def #{association_name}_attributes=(attributes)
36
+ assign_nested_attributes_for_#{type}_association(:#{association_name}, attributes)
37
+ end
38
+ }, __FILE__, __LINE__
39
+ else
40
+ raise ArgumentError, "No association found for name '#{association_name}'. Has it been defined yet?"
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ module InstanceMethods
47
+
48
+ private
49
+
50
+ # Attribute hash keys that should not be assigned as normal attributes.
51
+ # These hash keys are nested attributes implementation details.
52
+ UNASSIGNABLE_KEYS = %w( id _destroy )
53
+
54
+ def assign_nested_attributes_for_collection_association(association_name, attributes_collection)
55
+ options = nested_attributes_options[association_name]
56
+
57
+ unless attributes_collection.is_a?(Hash) || attributes_collection.is_a?(Array)
58
+ raise ArgumentError, "Hash or Array expected, got #{attributes_collection.class.name} (#{attributes_collection.inspect})"
59
+ end
60
+
61
+ if options[:limit] && attributes_collection.size > options[:limit]
62
+ raise TooManyRecords, "Maximum #{options[:limit]} records are allowed. Got #{attributes_collection.size} records instead."
63
+ end
64
+
65
+ if attributes_collection.is_a? Hash
66
+ attributes_collection = attributes_collection.sort_by { |index, _| index.to_i }.map { |_, attributes| attributes }
67
+ end
68
+
69
+ attributes_collection.each do |attributes|
70
+ attributes = attributes.with_indifferent_access
71
+
72
+ if attributes['id'].blank?
73
+ unless reject_new_record?(association_name, attributes)
74
+ send(association_name).build(attributes.except(*UNASSIGNABLE_KEYS))
75
+ end
76
+ elsif existing_record = send(association_name).detect { |record| record.id.to_s == attributes['id'].to_s }
77
+ assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy])
78
+ else
79
+ raise_nested_attributes_record_not_found(association_name, attributes['id'])
80
+ end
81
+ end
82
+ end
83
+
84
+ # Updates a record with the +attributes+ or marks it for destruction if
85
+ # +allow_destroy+ is +true+ and has_destroy_flag? returns +true+.
86
+ def assign_to_or_mark_for_destruction(record, attributes, allow_destroy)
87
+ if has_destroy_flag?(attributes) && allow_destroy
88
+ record.mark_for_destruction
89
+ else
90
+ record.attributes = attributes.except(*UNASSIGNABLE_KEYS)
91
+ end
92
+ end
93
+
94
+ # Determines if a hash contains a truthy _destroy key.
95
+ TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE'].to_set
96
+ def has_destroy_flag?(hash)
97
+ hash['_destroy'].present? && TRUE_VALUES.include?(hash['_destroy'])
98
+ end
99
+
100
+ # Determines if a new record should be build by checking for
101
+ # has_destroy_flag? or if a <tt>:reject_if</tt> proc exists for this
102
+ # association and evaluates to +true+.
103
+ def reject_new_record?(association_name, attributes)
104
+ has_destroy_flag?(attributes) || call_reject_if(association_name, attributes)
105
+ end
106
+
107
+ def call_reject_if(association_name, attributes)
108
+ case callback = nested_attributes_options[association_name][:reject_if]
109
+ when Symbol
110
+ method(callback).arity == 0 ? send(callback) : send(callback, attributes)
111
+ when Proc
112
+ callback.call(attributes)
113
+ end
114
+ end
115
+
116
+ def raise_nested_attributes_record_not_found(association_name, record_id)
117
+ assoc = self.class.associations[association_name]
118
+ raise DocumentNotFound, "Couldn't find #{assoc.klass.name} with ID=#{record_id} for #{self.class.name} with ID=#{id}"
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,39 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{mm-nested-attributes}
5
+ s.version = "0.1.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Toni Tuominen"]
9
+ s.date = %q{2010-07-10}
10
+ s.description = %q{A port of ActiveRecord's nested attributes functionality for MongoMapper.}
11
+ s.email = %q{toni@piranhadigital.fi}
12
+ s.extra_rdoc_files = ["History.txt", "README.txt", "version.txt"]
13
+ s.files = [".gitignore", "History.txt", "README.txt", "Rakefile", "lib/mm-nested-attributes.rb", "lib/mongo_mapper/plugins/associations/nested_attributes.rb", "mm-nested-attributes.gemspec", "spec/mm-nested-attributes_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "version.txt"]
14
+ s.homepage = %q{http://github.com/tjtuom/mm-nested-attributes}
15
+ s.rdoc_options = ["--main", "README.txt"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = %q{mm-nested-attributes}
18
+ s.rubygems_version = %q{1.3.6}
19
+ s.summary = %q{A port of ActiveRecord's nested attributes functionality for MongoMapper}
20
+
21
+ if s.respond_to? :specification_version then
22
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
23
+ s.specification_version = 3
24
+
25
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
26
+ s.add_runtime_dependency(%q<mongo_mapper>, [">= 0.8.2"])
27
+ s.add_development_dependency(%q<rspec>, [">= 1.3.0"])
28
+ s.add_development_dependency(%q<bones>, [">= 3.4.3"])
29
+ else
30
+ s.add_dependency(%q<mongo_mapper>, [">= 0.8.2"])
31
+ s.add_dependency(%q<rspec>, [">= 1.3.0"])
32
+ s.add_dependency(%q<bones>, [">= 3.4.3"])
33
+ end
34
+ else
35
+ s.add_dependency(%q<mongo_mapper>, [">= 0.8.2"])
36
+ s.add_dependency(%q<rspec>, [">= 1.3.0"])
37
+ s.add_dependency(%q<bones>, [">= 3.4.3"])
38
+ end
39
+ end
@@ -0,0 +1,174 @@
1
+ require File.join(File.dirname(__FILE__), %w[spec_helper])
2
+
3
+ describe "Nested attributes plugin" do
4
+ before do
5
+ @klass = Doc('Parent') do
6
+ plugin MongoMapper::Plugins::Associations::NestedAttributes
7
+ key :body, String
8
+ end
9
+
10
+ @child_klass = Doc('Child') do
11
+ key :value, String
12
+ end
13
+
14
+ @klass.many :children, :class => @child_klass
15
+ @klass.accepts_nested_attributes_for :children
16
+
17
+ @parent = @klass.new
18
+ end
19
+
20
+ it "responds to #<association>_attributes=" do
21
+ @parent.should respond_to(:children_attributes=)
22
+ end
23
+
24
+ it "raises an error for undefined associations" do
25
+ doing { @klass.accepts_nested_attributes_for :foo }.should(
26
+ raise_error(ArgumentError, "No association found for name 'foo'. Has it been defined yet?"))
27
+ end
28
+
29
+ it 'rejects the document if _destroy flag is present' do
30
+ @parent = @klass.new(:children_attributes => [ { :value => 'ok' }, { :value => 'not ok', :_destroy => '1' } ])
31
+ @parent.children.size.should == 1
32
+ @parent.children[0].value.should == 'ok'
33
+ end
34
+ end
35
+
36
+ describe "Nested attributes plugin for collections" do
37
+ before do
38
+ @klass = Doc('Parent') do
39
+ plugin MongoMapper::Plugins::Associations::NestedAttributes
40
+ key :body, String
41
+ end
42
+
43
+ @child_klass = Doc('Child') do
44
+ key :value, String
45
+ end
46
+
47
+ @klass.many :children, :class => @child_klass
48
+ @klass.accepts_nested_attributes_for :children
49
+
50
+ @parent = @klass.new
51
+ end
52
+
53
+ describe "assigning attributes" do
54
+ it "creates the child model when given an array" do
55
+ @parent.children_attributes = [ { :value => "foo" } ]
56
+ @parent.children.size.should == 1
57
+ @parent.children[0].value.should == "foo"
58
+ end
59
+
60
+ it "creates the child model when given a hash" do
61
+ @parent.children_attributes = { 0 => { :value => "foo" } }
62
+ @parent.children.size.should == 1
63
+ @parent.children[0].value.should == "foo"
64
+ end
65
+ end
66
+
67
+ describe "initializing a new model" do
68
+ it "creates the child model when given an array" do
69
+ @parent = @klass.new(:children_attributes => [ { :value => "foo"} ])
70
+ @parent.children.size.should == 1
71
+ @parent.children[0].value.should == "foo"
72
+ end
73
+
74
+ it "creates the child model when given a hash" do
75
+ @parent = @klass.new(:children_attributes => { 0 => { :value => "foo" } })
76
+ @parent.children.size.should == 1
77
+ @parent.children[0].value.should == "foo"
78
+ end
79
+ end
80
+
81
+ describe "editing an existing document" do
82
+ it "raises an error if the document isn't found" do
83
+ @parent = @klass.new
84
+ @child = @parent.children.create!(:value => 'foo')
85
+
86
+ id = BSON::ObjectID.new
87
+ doing do
88
+ @parent.children_attributes = [ { :id => id, :value => 'bar' } ]
89
+ end.should raise_error(MongoMapper::DocumentNotFound, "Couldn't find Child with ID=#{id} for Parent with ID=#{@parent.id}")
90
+ end
91
+
92
+ it 'updates the document' do
93
+ @parent = @klass.new
94
+ @child = @parent.children.create!(:value => 'foo')
95
+
96
+ @parent.children_attributes = [ { :id => @child.id, :value => 'bar' } ]
97
+ @parent.children[0].value.should == 'bar'
98
+
99
+ # has not been saved so the db should have the old value
100
+ @klass.first.children[0].value.should == 'foo'
101
+
102
+ @parent.save!
103
+
104
+ # after save the db should have the new value
105
+ @klass.first.children[0].value.should == 'bar'
106
+ end
107
+ end
108
+
109
+ describe "deleting an existing document" do
110
+ it 'does nothing unless :allow_destroy is true' do
111
+ @klass.accepts_nested_attributes_for :children
112
+
113
+ @parent = @klass.new
114
+ @child = @parent.children.create!(:value => 'foo')
115
+
116
+ @parent.children_attributes = [ { :id => @child.id, :_destroy => '1' } ]
117
+ doing do
118
+ @parent.save!
119
+ end.should_not change(@parent.children, :size)
120
+ end
121
+
122
+ it 'deletes the document when _destroy is present' do
123
+ @klass.accepts_nested_attributes_for :children, :allow_destroy => true
124
+
125
+ @parent = @klass.new
126
+ @child = @parent.children.create!(:value => 'foo')
127
+
128
+ @parent.children_attributes = [ { :id => @child.id, :_destroy => '1' } ]
129
+
130
+ doing do
131
+ @parent.save!
132
+ end.should change(@parent.children, :size).by(-1)
133
+ end
134
+
135
+ it "does not delete the document until save is called" do
136
+ @klass.accepts_nested_attributes_for :children, :allow_destroy => true
137
+
138
+ @parent = @klass.new
139
+ @child = @parent.children.create!(:value => 'foo')
140
+
141
+ doing do
142
+ @parent.children_attributes = [ { :id => @child.id, :_destroy => '1' } ]
143
+ end.should_not change(@parent.children, :size)
144
+ end
145
+ end
146
+
147
+ describe "limit option" do
148
+ it "raises an error if more docs are given than are allowed" do
149
+ @klass.accepts_nested_attributes_for :children, :limit => 1
150
+
151
+ doing do
152
+ @parent = @klass.new(:children_attributes => [ { :value => 'foo' }, { :bar => 'bar'} ])
153
+ end.should raise_error(MongoMapper::TooManyRecords, "Maximum 1 records are allowed. Got 2 records instead.")
154
+ end
155
+ end
156
+
157
+ describe "reject_if option" do
158
+ it 'rejects docs that the block returns true for' do
159
+ @klass.accepts_nested_attributes_for :children, :reject_if => proc { |attrs| attrs['value'] == 'reject' }
160
+
161
+ @parent = @klass.new(:children_attributes => [ { :value => 'ok' }, { :value => 'reject' } ])
162
+ @parent.children.size.should == 1
163
+ @parent.children[0].value.should == 'ok'
164
+ end
165
+
166
+ it 'rejects fully empty objects if the reject_if option is set to :all_blank' do
167
+ @klass.accepts_nested_attributes_for :children, :reject_if => :all_blank
168
+
169
+ @parent = @klass.new(:children_attributes => [ { :value => '' }, { :value => 'ok' } ])
170
+ @parent.children.size.should == 1
171
+ @parent.children[0].value.should == 'ok'
172
+ end
173
+ end
174
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,42 @@
1
+ require 'rubygems'
2
+ require 'mongo_mapper'
3
+
4
+ require File.expand_path(
5
+ File.join(File.dirname(__FILE__), %w[.. lib mm-nested-attributes]))
6
+
7
+ Spec::Runner.configure do |config|
8
+ # == Mock Framework
9
+ #
10
+ # RSpec uses it's own mocking framework by default. If you prefer to
11
+ # use mocha, flexmock or RR, uncomment the appropriate line:
12
+ #
13
+ # config.mock_with :mocha
14
+ # config.mock_with :flexmock
15
+ # config.mock_with :rr
16
+
17
+ def Doc(name=nil, &block)
18
+ klass = Class.new do
19
+ include MongoMapper::Document
20
+ set_collection_name :test
21
+
22
+ if name
23
+ class_eval "def self.name; '#{name}' end"
24
+ class_eval "def self.to_s; '#{name}' end"
25
+ end
26
+ end
27
+
28
+ klass.class_eval(&block) if block_given?
29
+ klass.collection.remove
30
+ klass
31
+ end
32
+
33
+ def doing(&block)
34
+ block
35
+ end
36
+
37
+ MongoMapper.connection = Mongo::Connection.new('127.0.0.1', 27017)
38
+ MongoMapper.database = "mm-nested-attributes-test-#{RUBY_VERSION.gsub('.', '-')}"
39
+ MongoMapper.database.collections.each { |c| c.drop_indexes }
40
+
41
+ end
42
+
data/version.txt ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mm-nested-attributes
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - Toni Tuominen
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-07-10 00:00:00 +03:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: mongo_mapper
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ - 8
30
+ - 2
31
+ version: 0.8.2
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: rspec
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 1
43
+ - 3
44
+ - 0
45
+ version: 1.3.0
46
+ type: :development
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: bones
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ segments:
56
+ - 3
57
+ - 4
58
+ - 3
59
+ version: 3.4.3
60
+ type: :development
61
+ version_requirements: *id003
62
+ description: A port of ActiveRecord's nested attributes functionality for MongoMapper.
63
+ email: toni@piranhadigital.fi
64
+ executables: []
65
+
66
+ extensions: []
67
+
68
+ extra_rdoc_files:
69
+ - History.txt
70
+ - README.txt
71
+ - version.txt
72
+ files:
73
+ - .gitignore
74
+ - History.txt
75
+ - README.txt
76
+ - Rakefile
77
+ - lib/mm-nested-attributes.rb
78
+ - lib/mongo_mapper/plugins/associations/nested_attributes.rb
79
+ - mm-nested-attributes.gemspec
80
+ - spec/mm-nested-attributes_spec.rb
81
+ - spec/spec.opts
82
+ - spec/spec_helper.rb
83
+ - version.txt
84
+ has_rdoc: true
85
+ homepage: http://github.com/tjtuom/mm-nested-attributes
86
+ licenses: []
87
+
88
+ post_install_message:
89
+ rdoc_options:
90
+ - --main
91
+ - README.txt
92
+ require_paths:
93
+ - lib
94
+ required_ruby_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ segments:
99
+ - 0
100
+ version: "0"
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ segments:
106
+ - 0
107
+ version: "0"
108
+ requirements: []
109
+
110
+ rubyforge_project: mm-nested-attributes
111
+ rubygems_version: 1.3.6
112
+ signing_key:
113
+ specification_version: 3
114
+ summary: A port of ActiveRecord's nested attributes functionality for MongoMapper
115
+ test_files: []
116
+