dm-accepts_nested_attributes 0.12.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 +26 -0
- data/CHANGELOG +970 -0
- data/LICENSE +20 -0
- data/README.textile +94 -0
- data/Rakefile +35 -0
- data/TODO +6 -0
- data/dm-accepts_nested_attributes.gemspec +90 -0
- data/lib/dm-accepts_nested_attributes.rb +7 -0
- data/lib/dm-accepts_nested_attributes/error_collecting.rb +35 -0
- data/lib/dm-accepts_nested_attributes/model.rb +155 -0
- data/lib/dm-accepts_nested_attributes/resource.rb +259 -0
- data/lib/dm-accepts_nested_attributes/transactional_save.rb +24 -0
- data/lib/dm-accepts_nested_attributes/version.rb +7 -0
- data/spec/accepts_nested_attributes_for_spec.rb +408 -0
- data/spec/many_to_many_spec.rb +129 -0
- data/spec/many_to_one_spec.rb +101 -0
- data/spec/one_to_many_spec.rb +100 -0
- data/spec/one_to_one_spec.rb +115 -0
- data/spec/rcov.opts +6 -0
- data/spec/shared/many_to_many_spec.rb +162 -0
- data/spec/shared/many_to_one_spec.rb +150 -0
- data/spec/shared/one_to_many_spec.rb +128 -0
- data/spec/shared/one_to_one_spec.rb +130 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +53 -0
- data/tasks/changelog.rake +20 -0
- data/tasks/ci.rake +1 -0
- data/tasks/metrics.rake +36 -0
- data/tasks/spec.rake +25 -0
- data/tasks/yard.rake +9 -0
- data/tasks/yardstick.rake +19 -0
- metadata +125 -0
data/spec/rcov.opts
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
describe "every accessible many_to_many association", :shared => true do
|
2
|
+
|
3
|
+
it "should allow to update an existing project via Person#projects_attributes" do
|
4
|
+
Person.all.size.should == 0
|
5
|
+
Project.all.size.should == 0
|
6
|
+
ProjectMembership.all.size.should == 0
|
7
|
+
|
8
|
+
person = Person.create :name => 'snusnu'
|
9
|
+
project = Project.create(:name => 'dm-accepts_nested_attributes')
|
10
|
+
project_membership = ProjectMembership.create(:person => person, :project => project)
|
11
|
+
|
12
|
+
Person.all.size.should == 1
|
13
|
+
Project.all.size.should == 1
|
14
|
+
ProjectMembership.all.size.should == 1
|
15
|
+
|
16
|
+
person.projects_attributes = [{ :id => project.id, :name => 'still dm-accepts_nested_attributes' }]
|
17
|
+
person.save
|
18
|
+
|
19
|
+
Person.all.size.should == 1
|
20
|
+
ProjectMembership.all.size.should == 1
|
21
|
+
Project.all.size.should == 1
|
22
|
+
|
23
|
+
Project.first.name.should == 'still dm-accepts_nested_attributes'
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should return the attributes written to Person#projects_attributes from the Person#projects_attributes reader" do
|
27
|
+
person = Person.new :name => 'snusnu'
|
28
|
+
person.projects_attributes.should be_nil
|
29
|
+
person.projects_attributes = [{ :name => 'write specs' }]
|
30
|
+
person.projects_attributes.should == [{ :name => 'write specs' }]
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "every accessible many_to_many association with a valid reject_if proc", :shared => true do
|
36
|
+
|
37
|
+
it "should not allow to create a new project via Person#projects_attributes" do
|
38
|
+
Person.all.size.should == 0
|
39
|
+
Project.all.size.should == 0
|
40
|
+
ProjectMembership.all.size.should == 0
|
41
|
+
|
42
|
+
person = Person.create :name => 'snusnu'
|
43
|
+
|
44
|
+
Person.all.size.should == 1
|
45
|
+
ProjectMembership.all.size.should == 0
|
46
|
+
Project.all.size.should == 0
|
47
|
+
|
48
|
+
person.projects_attributes = [{ :name => 'dm-accepts_nested_attributes' }]
|
49
|
+
person.save
|
50
|
+
|
51
|
+
Person.all.size.should == 1
|
52
|
+
ProjectMembership.all.size.should == 0
|
53
|
+
Project.all.size.should == 0
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "every accessible many_to_many association with no reject_if proc", :shared => true do
|
59
|
+
|
60
|
+
it "should allow to create a new project via Person#projects_attributes" do
|
61
|
+
Person.all.size.should == 0
|
62
|
+
Project.all.size.should == 0
|
63
|
+
ProjectMembership.all.size.should == 0
|
64
|
+
|
65
|
+
person = Person.create :name => 'snusnu'
|
66
|
+
|
67
|
+
Person.all.size.should == 1
|
68
|
+
ProjectMembership.all.size.should == 0
|
69
|
+
Project.all.size.should == 0
|
70
|
+
|
71
|
+
person.projects_attributes = [{ :name => 'dm-accepts_nested_attributes' }]
|
72
|
+
|
73
|
+
Person.all.size.should == 1
|
74
|
+
ProjectMembership.all.size.should == 0
|
75
|
+
Project.all.size.should == 0
|
76
|
+
|
77
|
+
person.save
|
78
|
+
|
79
|
+
Person.all.size.should == 1
|
80
|
+
ProjectMembership.all.size.should == 1
|
81
|
+
Project.all.size.should == 1
|
82
|
+
|
83
|
+
Project.first.name.should == 'dm-accepts_nested_attributes'
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should perform atomic commits" do
|
87
|
+
|
88
|
+
person = Person.new :name => 'snusnu'
|
89
|
+
person.projects_attributes = [{ :name => nil }] # should fail because of validations
|
90
|
+
person.save
|
91
|
+
|
92
|
+
Person.all.size.should == 0 # TODO think more if this should be '1'
|
93
|
+
ProjectMembership.all.size.should == 0
|
94
|
+
Project.all.size.should == 0
|
95
|
+
|
96
|
+
person.name = nil # should fail because of validations
|
97
|
+
person.projects_attributes = [{ :name => nil }]
|
98
|
+
person.save
|
99
|
+
|
100
|
+
Person.all.size.should == 0
|
101
|
+
ProjectMembership.all.size.should == 0
|
102
|
+
Project.all.size.should == 0
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
describe "every accessible many_to_many association with :allow_destroy => false", :shared => true do
|
109
|
+
|
110
|
+
it "should not allow to delete an existing project via Person#projects_attributes" do
|
111
|
+
person = Person.create :name => 'snusnu'
|
112
|
+
|
113
|
+
project = Project.create(:name => 'dm-accepts_nested_attributes')
|
114
|
+
project_membership = ProjectMembership.create(:person => person, :project => project)
|
115
|
+
|
116
|
+
Person.all.size.should == 1
|
117
|
+
ProjectMembership.all.size.should == 1
|
118
|
+
Project.all.size.should == 1
|
119
|
+
|
120
|
+
person.projects_attributes = [{ :id => project.id, :_delete => true }]
|
121
|
+
|
122
|
+
Person.all.size.should == 1
|
123
|
+
ProjectMembership.all.size.should == 1
|
124
|
+
Project.all.size.should == 1
|
125
|
+
|
126
|
+
person.save
|
127
|
+
|
128
|
+
Person.all.size.should == 1
|
129
|
+
ProjectMembership.all.size.should == 1
|
130
|
+
Project.all.size.should == 1
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
|
135
|
+
describe "every accessible many_to_many association with :allow_destroy => true", :shared => true do
|
136
|
+
|
137
|
+
it "should allow to delete an existing project via Person#projects_attributes" do
|
138
|
+
person = Person.create :name => 'snusnu'
|
139
|
+
|
140
|
+
project_1 = Project.create(:name => 'dm-accepts_nested_attributes')
|
141
|
+
project_2 = Project.create(:name => 'dm-is-localizable')
|
142
|
+
project_membership_1 = ProjectMembership.create(:person => person, :project => project_1)
|
143
|
+
project_membership_2 = ProjectMembership.create(:person => person, :project => project_2)
|
144
|
+
|
145
|
+
Person.all.size.should == 1
|
146
|
+
ProjectMembership.all.size.should == 2
|
147
|
+
Project.all.size.should == 2
|
148
|
+
|
149
|
+
person.projects_attributes = [{ :id => project_1.id, :_delete => true }]
|
150
|
+
|
151
|
+
Person.all.size.should == 1
|
152
|
+
ProjectMembership.all.size.should == 2
|
153
|
+
Project.all.size.should == 2
|
154
|
+
|
155
|
+
person.save
|
156
|
+
|
157
|
+
Person.all.size.should == 1
|
158
|
+
ProjectMembership.all.size.should == 1
|
159
|
+
Project.all.size.should == 1
|
160
|
+
end
|
161
|
+
|
162
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
describe "every accessible many_to_one association", :shared => true do
|
2
|
+
|
3
|
+
it "should allow to update an existing person via Profile#person_attributes" do
|
4
|
+
Profile.all.size.should == 0
|
5
|
+
Person.all.size.should == 0
|
6
|
+
|
7
|
+
profile = Profile.new :nick => 'snusnu'
|
8
|
+
person = Person.create(:name => 'Martin')
|
9
|
+
profile.person = person
|
10
|
+
profile.save.should be_true
|
11
|
+
|
12
|
+
Profile.all.size.should == 1
|
13
|
+
Person.all.size.should == 1
|
14
|
+
Person.first.name.should == 'Martin'
|
15
|
+
|
16
|
+
profile.person_attributes = { :id => person.id, :name => 'Martin Gamsjaeger' }
|
17
|
+
profile.save.should be_true
|
18
|
+
|
19
|
+
Profile.all.size.should == 1
|
20
|
+
Person.all.size.should == 1
|
21
|
+
Person.first.name.should == 'Martin Gamsjaeger'
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should perform atomic commits" do
|
25
|
+
Profile.all.size.should == 0
|
26
|
+
Person.all.size.should == 0
|
27
|
+
|
28
|
+
# related resource is invalid
|
29
|
+
profile = Profile.new :nick => 'snusnu'
|
30
|
+
profile.person_attributes = { :name => nil }
|
31
|
+
profile.save.should be_false
|
32
|
+
|
33
|
+
Profile.all.size.should == 0
|
34
|
+
Person.all.size.should == 0
|
35
|
+
|
36
|
+
# self is invalid
|
37
|
+
profile.nick = nil
|
38
|
+
profile.person_attributes = { :name => 'Martin' }
|
39
|
+
profile.save.should be_false
|
40
|
+
|
41
|
+
Profile.all.size.should == 0
|
42
|
+
Person.all.size.should == 0
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should return the attributes written to Profile#person_attributes from the Profile#person_attributes reader" do
|
46
|
+
profile = Profile.new :nick => 'snusnu'
|
47
|
+
profile.person_attributes.should be_nil
|
48
|
+
profile.person_attributes = { :name => 'Martin' }
|
49
|
+
profile.person_attributes.should == { :name => 'Martin' }
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "every accessible many_to_one association with a valid reject_if proc", :shared => true do
|
55
|
+
|
56
|
+
it "should not allow to create a new person via Profile#person_attributes" do
|
57
|
+
Profile.all.size.should == 0
|
58
|
+
Person.all.size.should == 0
|
59
|
+
|
60
|
+
profile = Profile.new :nick => 'snusnu'
|
61
|
+
profile.person_attributes = { :name => 'Martin' }
|
62
|
+
|
63
|
+
Profile.all.size.should == 0
|
64
|
+
Person.all.size.should == 0
|
65
|
+
|
66
|
+
profile.save.should be_false
|
67
|
+
|
68
|
+
Profile.all.size.should == 0
|
69
|
+
Person.all.size.should == 0
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "every accessible many_to_one association with no reject_if proc", :shared => true do
|
75
|
+
|
76
|
+
it "should allow to create a new person via Profile#person_attributes" do
|
77
|
+
Profile.all.size.should == 0
|
78
|
+
Person.all.size.should == 0
|
79
|
+
|
80
|
+
profile = Profile.new :nick => 'snusnu'
|
81
|
+
profile.person_attributes = { :name => 'Martin' }
|
82
|
+
|
83
|
+
Profile.all.size.should == 0
|
84
|
+
Person.all.size.should == 0
|
85
|
+
|
86
|
+
profile.save.should be_true
|
87
|
+
|
88
|
+
Profile.all.size.should == 1
|
89
|
+
Person.all.size.should == 1
|
90
|
+
Person.first.name.should == 'Martin'
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
describe "every accessible many_to_one association with :allow_destroy => false", :shared => true do
|
96
|
+
|
97
|
+
it "should not allow to delete an existing person via Profile#person_attributes" do
|
98
|
+
Profile.all.size.should == 0
|
99
|
+
Person.all.size.should == 0
|
100
|
+
|
101
|
+
person = Person.create(:name => 'Martin')
|
102
|
+
profile = Profile.new :nick => 'snusnu'
|
103
|
+
profile.person = person
|
104
|
+
profile.save
|
105
|
+
|
106
|
+
Profile.all.size.should == 1
|
107
|
+
Person.all.size.should == 1
|
108
|
+
|
109
|
+
profile.person_attributes = { :id => person.id, :_delete => true }
|
110
|
+
|
111
|
+
Profile.all.size.should == 1
|
112
|
+
Person.all.size.should == 1
|
113
|
+
|
114
|
+
profile.save
|
115
|
+
|
116
|
+
Profile.all.size.should == 1
|
117
|
+
Person.all.size.should == 1
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
describe "every accessible many_to_one association with :allow_destroy => true", :shared => true do
|
123
|
+
|
124
|
+
it "should allow to delete an existing person via Profile#person_attributes" do
|
125
|
+
Profile.all.size.should == 0
|
126
|
+
Person.all.size.should == 0
|
127
|
+
|
128
|
+
person = Person.create(:name => 'Martin')
|
129
|
+
|
130
|
+
profile = Profile.new :nick => 'snusnu'
|
131
|
+
profile.person = person
|
132
|
+
profile.save.should be_true
|
133
|
+
|
134
|
+
Profile.all.size.should == 1
|
135
|
+
Person.all.size.should == 1
|
136
|
+
|
137
|
+
profile.person_attributes = { :id => person.id, :_delete => true }
|
138
|
+
|
139
|
+
Profile.all.size.should == 1
|
140
|
+
Person.all.size.should == 1
|
141
|
+
|
142
|
+
profile.save
|
143
|
+
|
144
|
+
Person.all.size.should == 0
|
145
|
+
|
146
|
+
# TODO also test this behavior in situations where setting the FK to nil is allowed
|
147
|
+
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
@@ -0,0 +1,128 @@
|
|
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
|
+
it "should perform atomic commits" do
|
65
|
+
Project.all.size.should == 0
|
66
|
+
Task.all.size.should == 0
|
67
|
+
|
68
|
+
# self is invalid
|
69
|
+
project = Project.new :name => nil
|
70
|
+
project.tasks_attributes = [{ :name => 'write specs' }]
|
71
|
+
project.save.should be_false
|
72
|
+
|
73
|
+
Project.all.size.should == 0
|
74
|
+
Task.all.size.should == 0
|
75
|
+
|
76
|
+
# related resource is invalid
|
77
|
+
project.name = 'dm-accepts_nested_attributes'
|
78
|
+
project.tasks_attributes = [{ :name => nil }] # will fail because of validations
|
79
|
+
project.save
|
80
|
+
|
81
|
+
Project.all.size.should == 0
|
82
|
+
Task.all.size.should == 0
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "every accessible one_to_many association with :allow_destroy => false", :shared => true do
|
88
|
+
|
89
|
+
it "should not allow to delete an existing task via Profile#tasks_attributes" do
|
90
|
+
project = Project.create :name => 'trippings'
|
91
|
+
|
92
|
+
task = Task.create(:project => project, :name => 'write specs')
|
93
|
+
|
94
|
+
Project.all.size.should == 1
|
95
|
+
Task.all.size.should == 1
|
96
|
+
|
97
|
+
project.tasks_attributes = [{ :id => task.id, :_delete => true }]
|
98
|
+
project.save
|
99
|
+
|
100
|
+
Project.all.size.should == 1
|
101
|
+
Task.all.size.should == 1
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
describe "every accessible one_to_many association with :allow_destroy => true", :shared => true do
|
107
|
+
|
108
|
+
it "should allow to delete an existing task via Profile#tasks_attributes" do
|
109
|
+
project = Project.create :name => 'trippings'
|
110
|
+
|
111
|
+
task = Task.create(:project => project, :name => 'write specs')
|
112
|
+
project.tasks.reload
|
113
|
+
|
114
|
+
Project.all.size.should == 1
|
115
|
+
Task.all.size.should == 1
|
116
|
+
|
117
|
+
project.tasks_attributes = [{ :id => task.id, :_delete => true }]
|
118
|
+
|
119
|
+
Project.all.size.should == 1
|
120
|
+
Task.all.size.should == 1
|
121
|
+
|
122
|
+
project.save
|
123
|
+
|
124
|
+
Project.all.size.should == 1
|
125
|
+
Task.all.size.should == 0
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|