dm-accepts_nested_attributes_for 1.2.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/CHANGELOG +970 -0
- data/Gemfile +84 -0
- data/LICENSE +20 -0
- data/README.textile +94 -0
- data/Rakefile +25 -0
- data/TODO +6 -0
- data/VERSION +1 -0
- data/dm-accepts_nested_attributes.gemspec +114 -0
- data/lib/dm-accepts_nested_attributes.rb +13 -0
- data/lib/dm-accepts_nested_attributes/model.rb +144 -0
- data/lib/dm-accepts_nested_attributes/relationship.rb +82 -0
- data/lib/dm-accepts_nested_attributes/resource.rb +382 -0
- data/lib/dm-accepts_nested_attributes/version.rb +7 -0
- data/spec/accepts_nested_attributes_for_spec.rb +408 -0
- data/spec/assign_nested_attributes_for_spec.rb +101 -0
- data/spec/comb/1-1_disjoint_spec.rb +67 -0
- data/spec/comb/1-1_overlapping_spec.rb +66 -0
- data/spec/comb/1-1_subset_spec.rb +65 -0
- data/spec/comb/1-1_superset_spec.rb +67 -0
- data/spec/comb/1-m_disjoint_spec.rb +71 -0
- data/spec/comb/1-m_overlapping_spec.rb +70 -0
- data/spec/comb/1-m_subset_spec.rb +65 -0
- data/spec/comb/1-m_superset_spec.rb +71 -0
- data/spec/comb/m-1_disjoint_spec.rb +71 -0
- data/spec/comb/m-1_overlapping_spec.rb +70 -0
- data/spec/comb/m-1_subset_spec.rb +65 -0
- data/spec/comb/m-1_superset_spec.rb +71 -0
- data/spec/comb/n-m_composite_spec.rb +141 -0
- data/spec/comb/n-m_surrogate_spec.rb +154 -0
- data/spec/many_to_many_composite_spec.rb +120 -0
- data/spec/many_to_many_spec.rb +129 -0
- data/spec/many_to_one_composite_spec.rb +120 -0
- data/spec/many_to_one_spec.rb +101 -0
- data/spec/one_to_many_composite_spec.rb +120 -0
- data/spec/one_to_many_spec.rb +100 -0
- data/spec/one_to_one_composite_spec.rb +150 -0
- data/spec/one_to_one_spec.rb +115 -0
- data/spec/rcov.opts +6 -0
- data/spec/resource_spec.rb +65 -0
- data/spec/shared/many_to_many_composite_spec.rb +149 -0
- data/spec/shared/many_to_many_spec.rb +146 -0
- data/spec/shared/many_to_one_composite_spec.rb +160 -0
- data/spec/shared/many_to_one_spec.rb +130 -0
- data/spec/shared/one_to_many_composite_spec.rb +159 -0
- data/spec/shared/one_to_many_spec.rb +107 -0
- data/spec/shared/one_to_one_composite_spec.rb +114 -0
- data/spec/shared/one_to_one_spec.rb +111 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +50 -0
- data/spec/update_dirty_spec.rb +113 -0
- data/spec/update_multiple_spec.rb +79 -0
- data/tasks/changelog.rake +20 -0
- data/tasks/ci.rake +1 -0
- data/tasks/local_gemfile.rake +18 -0
- data/tasks/spec.rake +22 -0
- data/tasks/yard.rake +9 -0
- data/tasks/yardstick.rake +19 -0
- metadata +216 -0
@@ -0,0 +1,107 @@
|
|
1
|
+
describe "every accessible one_to_many association", :shared => true do
|
2
|
+
|
3
|
+
it "should allow to update an existing task via Project#tasks_attributes" do
|
4
|
+
project = Project.create :name => 'trippings'
|
5
|
+
task = Task.create(:project => project, :name => 'write specs')
|
6
|
+
|
7
|
+
Project.all.size.should == 1
|
8
|
+
Task.all.size.should == 1
|
9
|
+
|
10
|
+
project.tasks_attributes = [{ :id => task.id, :name => 'write more specs' }]
|
11
|
+
project.save.should be_true
|
12
|
+
|
13
|
+
Project.all.size.should == 1
|
14
|
+
Task.all.size.should == 1
|
15
|
+
Task.first.name.should == 'write more specs'
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should return the attributes written with Project#task_attributes= from the Project#task_attributes reader" do
|
19
|
+
project = Project.new :name => 'trippings'
|
20
|
+
project.tasks_attributes.should be_nil
|
21
|
+
project.tasks_attributes = [{ :name => 'write specs' }]
|
22
|
+
project.tasks_attributes.should == [{ :name => 'write specs' }]
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "every accessible one_to_many association with a valid reject_if proc", :shared => true do
|
28
|
+
|
29
|
+
it "should not allow to create a new task via Project#tasks_attributes" do
|
30
|
+
project = Project.create :name => 'trippings'
|
31
|
+
|
32
|
+
Project.all.size.should == 1
|
33
|
+
Task.all.size.should == 0
|
34
|
+
|
35
|
+
project.tasks_attributes = [{ :name => 'write specs' }]
|
36
|
+
project.save.should be_true
|
37
|
+
|
38
|
+
Project.all.size.should == 1
|
39
|
+
Task.all.size.should == 0
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "every accessible one_to_many association with no reject_if proc", :shared => true do
|
45
|
+
|
46
|
+
it "should allow to create a new task via Project#tasks_attributes" do
|
47
|
+
project = Project.create :name => 'trippings'
|
48
|
+
|
49
|
+
Project.all.size.should == 1
|
50
|
+
Task.all.size.should == 0
|
51
|
+
|
52
|
+
project.tasks_attributes = [{ :name => 'write specs' }]
|
53
|
+
|
54
|
+
Project.all.size.should == 1
|
55
|
+
Task.all.size.should == 0
|
56
|
+
|
57
|
+
project.save.should be_true
|
58
|
+
|
59
|
+
Project.all.size.should == 1
|
60
|
+
Task.all.size.should == 1
|
61
|
+
Task.first.name.should == 'write specs'
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "every accessible one_to_many association with :allow_destroy => false", :shared => true do
|
67
|
+
|
68
|
+
it "should not allow to delete an existing task via Profile#tasks_attributes" do
|
69
|
+
project = Project.create :name => 'trippings'
|
70
|
+
|
71
|
+
task = Task.create(:project => project, :name => 'write specs')
|
72
|
+
|
73
|
+
Project.all.size.should == 1
|
74
|
+
Task.all.size.should == 1
|
75
|
+
|
76
|
+
project.tasks_attributes = [{ :id => task.id, :_delete => true }]
|
77
|
+
project.save
|
78
|
+
|
79
|
+
Project.all.size.should == 1
|
80
|
+
Task.all.size.should == 1
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "every accessible one_to_many association with :allow_destroy => true", :shared => true do
|
86
|
+
|
87
|
+
it "should allow to delete an existing task via Profile#tasks_attributes" do
|
88
|
+
project = Project.create :name => 'trippings'
|
89
|
+
|
90
|
+
task = Task.create(:project => project, :name => 'write specs')
|
91
|
+
project.tasks.reload
|
92
|
+
|
93
|
+
Project.all.size.should == 1
|
94
|
+
Task.all.size.should == 1
|
95
|
+
|
96
|
+
project.tasks_attributes = [{ :id => task.id, :_delete => true }]
|
97
|
+
|
98
|
+
Project.all.size.should == 1
|
99
|
+
Task.all.size.should == 1
|
100
|
+
|
101
|
+
project.save
|
102
|
+
|
103
|
+
Project.all.size.should == 1
|
104
|
+
Task.all.size.should == 0
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
describe "every accessible one_to_one composite association", :shared => true do
|
2
|
+
|
3
|
+
it "should allow to update an existing profile via Person#profile_attributes" do
|
4
|
+
person = Person.create(:audit_id => 1, :name => 'Martin')
|
5
|
+
profile = Profile.create(:person => person, :nick => 'snusnu')
|
6
|
+
person.reload
|
7
|
+
|
8
|
+
Person.all.size.should == 1
|
9
|
+
Profile.all.size.should == 1
|
10
|
+
|
11
|
+
person.profile_attributes = { :nick => 'still snusnu somehow' }
|
12
|
+
person.save.should be_true
|
13
|
+
|
14
|
+
Person.all.size.should == 1
|
15
|
+
Profile.all.size.should == 1
|
16
|
+
Profile.first.nick.should == 'still snusnu somehow'
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should return the attributes written to Person#profile_attributes from the Person#profile_attributes reader" do
|
20
|
+
person = Person.new :name => 'Martin'
|
21
|
+
person.profile_attributes.should be_nil
|
22
|
+
person.profile_attributes = { :nick => 'snusnu' }
|
23
|
+
person.profile_attributes.should == { :nick => 'snusnu' }
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "every accessible one_to_one composite association with a valid reject_if proc", :shared => true do
|
29
|
+
|
30
|
+
it "should not allow to create a new profile via Person#profile_attributes" do
|
31
|
+
Person.all.size.should == 0
|
32
|
+
Profile.all.size.should == 0
|
33
|
+
|
34
|
+
person = Person.new(:audit_id => 1, :name => 'Martin')
|
35
|
+
person.profile_attributes = { :nick => 'snusnu' }
|
36
|
+
person.save
|
37
|
+
|
38
|
+
Person.all.size.should == 1
|
39
|
+
Profile.all.size.should == 0
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "every accessible one_to_one composite association with no reject_if proc", :shared => true do
|
45
|
+
|
46
|
+
[[:new, 'a new'], [:create, 'an existing']].each do |ctor, ctor_desc|
|
47
|
+
it "should allow to create a new profile via Person#profile_attributes on #{ctor_desc} person" do
|
48
|
+
Person.all.size.should == 0
|
49
|
+
Profile.all.size.should == 0
|
50
|
+
|
51
|
+
person = Person.send(ctor, :audit_id => 1, :name => 'Martin')
|
52
|
+
person.profile_attributes = { :nick => 'snusnu' }
|
53
|
+
|
54
|
+
Person.all.size.should == (ctor == :new ? 0 : 1)
|
55
|
+
Profile.all.size.should == 0
|
56
|
+
|
57
|
+
person.save.should be_true
|
58
|
+
|
59
|
+
Person.all.size.should == 1
|
60
|
+
Profile.all.size.should == 1
|
61
|
+
Profile.first.nick.should == 'snusnu'
|
62
|
+
Profile.first.person_audit_id.should == person.audit_id
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "every accessible one_to_one composite association with :allow_destroy => false", :shared => true do
|
69
|
+
|
70
|
+
it "should not allow to delete an existing profile via Person#profile_attributes" do
|
71
|
+
person = Person.create(:audit_id => 1, :name => 'Martin')
|
72
|
+
|
73
|
+
profile = Profile.create(:person => person, :nick => 'snusnu')
|
74
|
+
person.reload
|
75
|
+
|
76
|
+
Person.all.size.should == 1
|
77
|
+
Profile.all.size.should == 1
|
78
|
+
|
79
|
+
person.profile_attributes = { :_delete => true }
|
80
|
+
|
81
|
+
Person.all.size.should == 1
|
82
|
+
Profile.all.size.should == 1
|
83
|
+
|
84
|
+
person.save
|
85
|
+
|
86
|
+
Person.all.size.should == 1
|
87
|
+
Profile.all.size.should == 1
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
describe "every accessible one_to_one composite association with :allow_destroy => true", :shared => true do
|
93
|
+
|
94
|
+
it "should allow to delete an existing profile via Person#profile_attributes" do
|
95
|
+
person = Person.create(:audit_id => 1, :name => 'Martin')
|
96
|
+
|
97
|
+
profile = Profile.create(:person => person, :nick => 'snusnu')
|
98
|
+
person.profile = profile
|
99
|
+
|
100
|
+
Person.all.size.should == 1
|
101
|
+
Profile.all.size.should == 1
|
102
|
+
|
103
|
+
person.profile_attributes = { :_delete => true }
|
104
|
+
|
105
|
+
Person.all.size.should == 1
|
106
|
+
Profile.all.size.should == 1
|
107
|
+
|
108
|
+
person.save
|
109
|
+
|
110
|
+
Person.all.size.should == 1
|
111
|
+
Profile.all.size.should == 0
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
describe "every accessible one_to_one association", :shared => true do
|
2
|
+
|
3
|
+
it "should allow to update an existing profile via Person#profile_attributes" do
|
4
|
+
person = Person.create :name => 'Martin'
|
5
|
+
profile = Profile.create(:person => person, :nick => 'snusnu')
|
6
|
+
person.reload
|
7
|
+
|
8
|
+
Person.all.size.should == 1
|
9
|
+
Profile.all.size.should == 1
|
10
|
+
|
11
|
+
person.profile_attributes = { :id => profile.id, :nick => 'still snusnu somehow' }
|
12
|
+
person.save.should be_true
|
13
|
+
|
14
|
+
Person.all.size.should == 1
|
15
|
+
Profile.all.size.should == 1
|
16
|
+
Profile.first.nick.should == 'still snusnu somehow'
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should return the attributes written to Person#profile_attributes from the Person#profile_attributes reader" do
|
20
|
+
person = Person.new :name => 'Martin'
|
21
|
+
person.profile_attributes.should be_nil
|
22
|
+
person.profile_attributes = { :nick => 'snusnu' }
|
23
|
+
person.profile_attributes.should == { :nick => 'snusnu' }
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "every accessible one_to_one association with a valid reject_if proc", :shared => true do
|
29
|
+
|
30
|
+
it "should not allow to create a new profile via Person#profile_attributes" do
|
31
|
+
Person.all.size.should == 0
|
32
|
+
Profile.all.size.should == 0
|
33
|
+
|
34
|
+
person = Person.new :name => 'Martin'
|
35
|
+
person.profile_attributes = { :nick => 'snusnu' }
|
36
|
+
person.save
|
37
|
+
|
38
|
+
Person.all.size.should == 1
|
39
|
+
Profile.all.size.should == 0
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "every accessible one_to_one association with no reject_if proc", :shared => true do
|
45
|
+
|
46
|
+
it "should allow to create a new profile via Person#profile_attributes" do
|
47
|
+
Person.all.size.should == 0
|
48
|
+
Profile.all.size.should == 0
|
49
|
+
|
50
|
+
person = Person.new :name => 'Martin'
|
51
|
+
person.profile_attributes = { :nick => 'snusnu' }
|
52
|
+
|
53
|
+
Person.all.size.should == 0
|
54
|
+
Profile.all.size.should == 0
|
55
|
+
|
56
|
+
person.save.should be_true
|
57
|
+
|
58
|
+
Person.all.size.should == 1
|
59
|
+
Profile.all.size.should == 1
|
60
|
+
Profile.first.nick.should == 'snusnu'
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "every accessible one_to_one association with :allow_destroy => false", :shared => true do
|
66
|
+
|
67
|
+
it "should not allow to delete an existing profile via Person#profile_attributes" do
|
68
|
+
person = Person.create :name => 'Martin'
|
69
|
+
|
70
|
+
profile = Profile.create(:person => person, :nick => 'snusnu')
|
71
|
+
person.reload
|
72
|
+
|
73
|
+
Person.all.size.should == 1
|
74
|
+
Profile.all.size.should == 1
|
75
|
+
|
76
|
+
person.profile_attributes = { :id => profile.id, :_delete => true }
|
77
|
+
|
78
|
+
Person.all.size.should == 1
|
79
|
+
Profile.all.size.should == 1
|
80
|
+
|
81
|
+
person.save
|
82
|
+
|
83
|
+
Person.all.size.should == 1
|
84
|
+
Profile.all.size.should == 1
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "every accessible one_to_one association with :allow_destroy => true", :shared => true do
|
90
|
+
|
91
|
+
it "should allow to delete an existing profile via Person#profile_attributes" do
|
92
|
+
person = Person.create :name => 'Martin'
|
93
|
+
|
94
|
+
profile = Profile.create(:person => person, :nick => 'snusnu')
|
95
|
+
person.profile = profile
|
96
|
+
|
97
|
+
Person.all.size.should == 1
|
98
|
+
Profile.all.size.should == 1
|
99
|
+
|
100
|
+
person.profile_attributes = { :id => profile.id, :_delete => true }
|
101
|
+
|
102
|
+
Person.all.size.should == 1
|
103
|
+
Profile.all.size.should == 1
|
104
|
+
|
105
|
+
person.save
|
106
|
+
|
107
|
+
Person.all.size.should == 1
|
108
|
+
Profile.all.size.should == 0
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'dm-core/spec/setup'
|
2
|
+
require 'dm-core/spec/lib/pending_helpers'
|
3
|
+
require 'dm-core/spec/lib/spec_helper'
|
4
|
+
|
5
|
+
require 'dm-accepts_nested_attributes'
|
6
|
+
|
7
|
+
require 'shared/many_to_many_spec'
|
8
|
+
require 'shared/many_to_one_spec'
|
9
|
+
require 'shared/one_to_many_spec'
|
10
|
+
require 'shared/one_to_one_spec'
|
11
|
+
require 'shared/many_to_many_composite_spec'
|
12
|
+
require 'shared/many_to_one_composite_spec'
|
13
|
+
require 'shared/one_to_many_composite_spec'
|
14
|
+
require 'shared/one_to_one_composite_spec'
|
15
|
+
|
16
|
+
DataMapper::Spec.setup
|
17
|
+
|
18
|
+
HAS_M2M_SUPPORT = !%w[in_memory yaml].include?(DataMapper::Spec.adapter_name)
|
19
|
+
|
20
|
+
module ConstraintSupport
|
21
|
+
|
22
|
+
def constraint(type)
|
23
|
+
if DataMapper.const_defined?('Constraints')
|
24
|
+
{ :constraint => type }
|
25
|
+
else
|
26
|
+
{}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
Spec::Runner.configure do |config|
|
33
|
+
|
34
|
+
config.include(DataMapper::Spec::PendingHelpers)
|
35
|
+
|
36
|
+
config.after(:all) do
|
37
|
+
if DataMapper.respond_to?(:auto_migrate_down!, true)
|
38
|
+
DataMapper.send(:auto_migrate_down!, DataMapper::Spec.adapter.name)
|
39
|
+
end
|
40
|
+
|
41
|
+
DataMapper::Spec.cleanup_models
|
42
|
+
end
|
43
|
+
|
44
|
+
config.after(:suite) do
|
45
|
+
if DataMapper.respond_to?(:auto_migrate_down!, true)
|
46
|
+
DataMapper.send(:auto_migrate_down!, DataMapper::Spec.adapter.name)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Person.has(n, :memberships)" do
|
4
|
+
|
5
|
+
before(:all) do
|
6
|
+
class ::Project
|
7
|
+
include DataMapper::Resource
|
8
|
+
extend ConstraintSupport
|
9
|
+
|
10
|
+
property :id, Integer, :key => true, :min => 0
|
11
|
+
property :name, String, :required => true
|
12
|
+
|
13
|
+
has n, :memberships, constraint(:destroy)
|
14
|
+
has n, :people, :through => :memberships
|
15
|
+
end
|
16
|
+
|
17
|
+
class ::Person
|
18
|
+
include DataMapper::Resource
|
19
|
+
extend ConstraintSupport
|
20
|
+
|
21
|
+
property :id, Integer, :key => true, :min => 0
|
22
|
+
property :name, String, :required => true
|
23
|
+
|
24
|
+
has n, :memberships, constraint(:destroy)
|
25
|
+
has n, :projects, :through => :memberships
|
26
|
+
accepts_nested_attributes_for :memberships, :allow_destroy => true
|
27
|
+
end
|
28
|
+
|
29
|
+
class ::Membership
|
30
|
+
include DataMapper::Resource
|
31
|
+
|
32
|
+
property :person_id, Integer, :key => true, :min => 0
|
33
|
+
property :project_id, Integer, :key => true, :min => 0
|
34
|
+
property :role, String, :required => true
|
35
|
+
|
36
|
+
belongs_to :person
|
37
|
+
belongs_to :project
|
38
|
+
|
39
|
+
accepts_nested_attributes_for :person
|
40
|
+
accepts_nested_attributes_for :project
|
41
|
+
end
|
42
|
+
|
43
|
+
DataMapper.auto_migrate!
|
44
|
+
end
|
45
|
+
|
46
|
+
before(:each) do
|
47
|
+
Membership.all.destroy!
|
48
|
+
Person.all.destroy!
|
49
|
+
Project.all.destroy!
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should allow to update an existing person, membership and project at the same time" do
|
53
|
+
person = Person.create(:id => 1, :name => 'snusnu')
|
54
|
+
project = Project.create(:id => 10, :name => 'dm-accepts_nested_attributes')
|
55
|
+
membership = Membership.create(:person => person, :project => project, :role => 'maintainer')
|
56
|
+
|
57
|
+
params = {
|
58
|
+
:name => 'Martin',
|
59
|
+
:memberships_attributes => [{
|
60
|
+
:project_id => project.id,
|
61
|
+
:role => 'still maintainer',
|
62
|
+
:project_attributes => { :name => 'tripping' }
|
63
|
+
}]
|
64
|
+
}
|
65
|
+
|
66
|
+
# Quick ordered hash hack: make sure the name attribute is updated first,
|
67
|
+
# making the person dirty.
|
68
|
+
class << params
|
69
|
+
def each
|
70
|
+
[:name, :memberships_attributes].each { |key| yield key, self[key] }
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
person.update params
|
75
|
+
|
76
|
+
Person.all.size.should == 1
|
77
|
+
Project.all.size.should == 1
|
78
|
+
Membership.all.size.should == 1
|
79
|
+
|
80
|
+
Person.first.attributes.should == { :id => 1, :name => 'Martin' }
|
81
|
+
Project.first.attributes.should == { :id => 10, :name => 'tripping' }
|
82
|
+
Membership.first.attributes.should == { :person_id => 1, :project_id => 10, :role => 'still maintainer' }
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should not allow to update a dirty parent resource with nested attributes" do
|
86
|
+
person = Person.create(:id => 1, :name => 'snusnu')
|
87
|
+
project = Project.create(:id => 10, :name => 'dm-accepts_nested_attributes')
|
88
|
+
membership = Membership.create(:person => person, :project => project, :role => 'maintainer')
|
89
|
+
|
90
|
+
params = {
|
91
|
+
:name => 'Martin',
|
92
|
+
:memberships_attributes => [{
|
93
|
+
:project_id => project.id,
|
94
|
+
:role => 'still maintainer',
|
95
|
+
:person_attributes => { :name => 'Martin Gamsjaeger' }
|
96
|
+
}]
|
97
|
+
}
|
98
|
+
class <<params
|
99
|
+
def each
|
100
|
+
[:name, :memberships_attributes].each { |key| yield key, self[key] }
|
101
|
+
end
|
102
|
+
end
|
103
|
+
lambda { person.update(params) }.should raise_error(DataMapper::UpdateConflictError)
|
104
|
+
|
105
|
+
Person.all.size.should == 1
|
106
|
+
Project.all.size.should == 1
|
107
|
+
Membership.all.size.should == 1
|
108
|
+
|
109
|
+
Person.first.attributes.should == { :id => 1, :name => 'snusnu' }
|
110
|
+
Project.first.attributes.should == { :id => 10, :name => 'dm-accepts_nested_attributes' }
|
111
|
+
Membership.first.attributes.should == { :person_id => 1, :project_id => 10, :role => 'maintainer' }
|
112
|
+
end
|
113
|
+
end
|