snusnu-dm-accepts_nested_attributes 0.10.0 → 0.11.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.
@@ -3,7 +3,18 @@ module DataMapper
3
3
 
4
4
  module TransactionalSave
5
5
 
6
- def save(*args)
6
+ ##
7
+ # Overrides @see DataMapper::Resource#save to perform inside a transaction.
8
+ # The current implementation simply wraps the saving of the complete object tree
9
+ # inside a transaction and rolls back in case any exceptions are raised,
10
+ # or any of the calls to
11
+ #
12
+ # @see DataMapper::Resource#save
13
+ #
14
+ # @return [true, false]
15
+ # true if all related resources were saved properly
16
+ #
17
+ def save(*)
7
18
  saved = false
8
19
  transaction { |t| t.rollback unless saved = super }
9
20
  saved
@@ -1,7 +1,7 @@
1
1
  module DataMapper
2
2
  module NestedAttributes
3
3
 
4
- VERSION = '0.10.0'.freeze
4
+ VERSION = '0.11.0'.freeze
5
5
 
6
6
  end
7
7
  end
@@ -1,6 +1,7 @@
1
1
  class Person
2
2
 
3
3
  include DataMapper::Resource
4
+ extend ConstraintSupport
4
5
 
5
6
  # properties
6
7
 
@@ -9,8 +10,19 @@ class Person
9
10
 
10
11
  # associations
11
12
 
12
- has 1, :profile
13
- has n, :project_memberships
14
- has n, :projects, :through => :project_memberships
13
+ has 1, :profile,
14
+ constraint_options(:destroy)
15
+
16
+ # has 1, :address,
17
+ # :through => :profile
18
+
19
+ has n, :project_memberships,
20
+ constraint_options(:destroy)
21
+
22
+ has n, :projects,
23
+ :through => :project_memberships
24
+
25
+ # has n, :tasks,
26
+ # :through => :projects
15
27
 
16
28
  end
@@ -13,4 +13,6 @@ class Profile
13
13
 
14
14
  belongs_to :person
15
15
 
16
+ has 1, :address
17
+
16
18
  end
@@ -1,6 +1,7 @@
1
1
  class Project
2
2
 
3
3
  include DataMapper::Resource
4
+ extend ConstraintSupport
4
5
 
5
6
  # properties
6
7
 
@@ -9,8 +10,13 @@ class Project
9
10
 
10
11
  # associations
11
12
 
12
- has n, :tasks
13
- has n, :project_memberships
14
- has n, :people, :through => :project_memberships
15
-
13
+ has n, :tasks,
14
+ constraint_options(:destroy)
15
+
16
+ has n, :project_memberships,
17
+ constraint_options(:destroy)
18
+
19
+ has n, :people,
20
+ :through => :project_memberships
21
+
16
22
  end
@@ -0,0 +1,11 @@
1
+ module ConstraintSupport
2
+
3
+ def constraint_options(type)
4
+ if DataMapper.const_defined?('Constraints')
5
+ { :constraint => type }
6
+ else
7
+ {}
8
+ end
9
+ end
10
+
11
+ end
@@ -55,6 +55,10 @@ describe "every accessible belongs_to association with a valid reject_if proc",
55
55
  Person.all.size.should == 0
56
56
 
57
57
  @profile.person_attributes = { :name => 'Martin' }
58
+
59
+ Profile.all.size.should == 0
60
+ Person.all.size.should == 0
61
+
58
62
  @profile.save.should be_false
59
63
 
60
64
  Profile.all.size.should == 0
@@ -70,6 +74,10 @@ describe "every accessible belongs_to association with no reject_if proc", :shar
70
74
  Person.all.size.should == 0
71
75
 
72
76
  @profile.person_attributes = { :name => 'Martin' }
77
+
78
+ Profile.all.size.should == 0
79
+ Person.all.size.should == 0
80
+
73
81
  @profile.save.should be_true
74
82
 
75
83
  Profile.all.size.should == 1
@@ -87,12 +95,16 @@ describe "every accessible belongs_to association with :allow_destroy => false",
87
95
 
88
96
  person = Person.create(:name => 'Martin')
89
97
  @profile.person = person
90
- @profile.save.should be_true
98
+ @profile.save
91
99
 
92
100
  Profile.all.size.should == 1
93
101
  Person.all.size.should == 1
94
102
 
95
103
  @profile.person_attributes = { :id => person.id, :_delete => true }
104
+
105
+ Profile.all.size.should == 1
106
+ Person.all.size.should == 1
107
+
96
108
  @profile.save
97
109
 
98
110
  Profile.all.size.should == 1
@@ -115,10 +127,13 @@ describe "every accessible belongs_to association with :allow_destroy => true",
115
127
  Person.all.size.should == 1
116
128
 
117
129
  @profile.person_attributes = { :id => person.id, :_delete => true }
130
+
131
+ Profile.all.size.should == 1
132
+ Person.all.size.should == 1
133
+
118
134
  @profile.save
119
135
 
120
- Profile.all.size.should == 1 # project.person_id must not be nil
121
- Person.all.size.should == 1
136
+ Person.all.size.should == 0
122
137
 
123
138
  # TODO also test this behavior in situations where setting the FK to nil is allowed
124
139
 
@@ -5,6 +5,9 @@ describe "every accessible has(1) association", :shared => true do
5
5
  profile = Profile.create(:person_id => @person.id, :nick => 'snusnu')
6
6
  @person.reload
7
7
 
8
+ Person.all.size.should == 1
9
+ Profile.all.size.should == 1
10
+
8
11
  @person.profile_attributes = { :id => profile.id, :nick => 'still snusnu somehow' }
9
12
  @person.save.should be_true
10
13
 
@@ -13,24 +16,6 @@ describe "every accessible has(1) association", :shared => true do
13
16
  Profile.first.nick.should == 'still snusnu somehow'
14
17
  end
15
18
 
16
- it "should perform atomic commits" do
17
-
18
- # related resource is invalid
19
- @person.profile_attributes = { :nick => nil } # will fail because of validations
20
- @person.save.should be_false
21
-
22
- Person.all.size.should == 0
23
- Profile.all.size.should == 0
24
-
25
- # self is invalid
26
- @person.name = nil # will fail because of validations
27
- @person.profile_attributes = { :nick => 'snusnu' }
28
- @person.save.should be_false
29
-
30
- Person.all.size.should == 0
31
- Profile.all.size.should == 0
32
- end
33
-
34
19
  it "should return the attributes written to Person#profile_attributes from the Person#profile_attributes reader" do
35
20
  @person.profile_attributes.should be_nil
36
21
  @person.profile_attributes = { :nick => 'snusnu' }
@@ -61,6 +46,10 @@ describe "every accessible has(1) association with no reject_if proc", :shared =
61
46
  Profile.all.size.should == 0
62
47
 
63
48
  @person.profile_attributes = { :nick => 'snusnu' }
49
+
50
+ Person.all.size.should == 0
51
+ Profile.all.size.should == 0
52
+
64
53
  @person.save.should be_true
65
54
 
66
55
  Person.all.size.should == 1
@@ -68,6 +57,24 @@ describe "every accessible has(1) association with no reject_if proc", :shared =
68
57
  Profile.first.nick.should == 'snusnu'
69
58
  end
70
59
 
60
+ it "should perform atomic commits" do
61
+
62
+ # related resource is invalid
63
+ @person.profile_attributes = { :nick => nil } # will fail because of validations
64
+ @person.save.should be_false
65
+
66
+ Person.all.size.should == 0
67
+ Profile.all.size.should == 0
68
+
69
+ # self is invalid
70
+ @person.name = nil # will fail because of validations
71
+ @person.profile_attributes = { :nick => 'snusnu' }
72
+ @person.save.should be_false
73
+
74
+ Person.all.size.should == 0
75
+ Profile.all.size.should == 0
76
+ end
77
+
71
78
  end
72
79
 
73
80
  describe "every accessible has(1) association with :allow_destroy => false", :shared => true do
@@ -76,9 +83,17 @@ describe "every accessible has(1) association with :allow_destroy => false", :sh
76
83
  @person.save
77
84
  profile = Profile.create(:person_id => @person.id, :nick => 'snusnu')
78
85
  @person.reload
79
-
86
+
87
+ Person.all.size.should == 1
88
+ Profile.all.size.should == 1
89
+
80
90
  @person.profile_attributes = { :id => profile.id, :_delete => true }
91
+
92
+ Person.all.size.should == 1
93
+ Profile.all.size.should == 1
94
+
81
95
  @person.save
96
+
82
97
  Person.all.size.should == 1
83
98
  Profile.all.size.should == 1
84
99
  end
@@ -90,10 +105,16 @@ describe "every accessible has(1) association with :allow_destroy => true", :sha
90
105
  it "should allow to delete an existing profile via Person#profile_attributes" do
91
106
  @person.save
92
107
  profile = Profile.create(:person_id => @person.id, :nick => 'snusnu')
93
-
94
108
  @person.profile = profile
109
+
110
+ Person.all.size.should == 1
111
+ Profile.all.size.should == 1
112
+
95
113
  @person.profile_attributes = { :id => profile.id, :_delete => true }
96
114
 
115
+ Person.all.size.should == 1
116
+ Profile.all.size.should == 1
117
+
97
118
  @person.save
98
119
 
99
120
  Person.all.size.should == 1
@@ -14,27 +14,6 @@ describe "every accessible has(n) association", :shared => true do
14
14
  Task.first.name.should == 'write more specs'
15
15
  end
16
16
 
17
- it "should perform atomic commits" do
18
- Project.all.size.should == 0
19
- Task.all.size.should == 0
20
-
21
- # self is invalid
22
- @project.name = nil # will fail because of validations
23
- @project.tasks_attributes = { 'new_1' => { :name => 'write specs' } }
24
- @project.save
25
-
26
- Project.all.size.should == 0
27
- Task.all.size.should == 0
28
-
29
- # related resource is invalid
30
- @project.name = 'dm-accepts_nested_attributes'
31
- @project.tasks_attributes = { 'new_1' => { :name => nil } } # will fail because of validations
32
- @project.save
33
-
34
- Project.all.size.should == 0
35
- Task.all.size.should == 0
36
- end
37
-
38
17
  it "should return the attributes written to Project#task_attributes from the Project#task_attributes reader" do
39
18
  @project.tasks_attributes.should be_nil
40
19
  @project.tasks_attributes = { 'new_1' => { :name => 'write specs' } }
@@ -67,6 +46,10 @@ describe "every accessible has(n) association with no reject_if proc", :shared =
67
46
  Task.all.size.should == 0
68
47
 
69
48
  @project.tasks_attributes = { 'new_1' => { :name => 'write specs' } }
49
+
50
+ Project.all.size.should == 1
51
+ Task.all.size.should == 0
52
+
70
53
  @project.save.should be_true
71
54
 
72
55
  Project.all.size.should == 1
@@ -74,6 +57,27 @@ describe "every accessible has(n) association with no reject_if proc", :shared =
74
57
  Task.first.name.should == 'write specs'
75
58
  end
76
59
 
60
+ it "should perform atomic commits" do
61
+ Project.all.size.should == 0
62
+ Task.all.size.should == 0
63
+
64
+ # self is invalid
65
+ @project.name = nil # will fail because of validations
66
+ @project.tasks_attributes = { 'new_1' => { :name => 'write specs' } }
67
+ @project.save
68
+
69
+ Project.all.size.should == 0
70
+ Task.all.size.should == 0
71
+
72
+ # related resource is invalid
73
+ @project.name = 'dm-accepts_nested_attributes'
74
+ @project.tasks_attributes = { 'new_1' => { :name => nil } } # will fail because of validations
75
+ @project.save
76
+
77
+ Project.all.size.should == 0
78
+ Task.all.size.should == 0
79
+ end
80
+
77
81
  end
78
82
 
79
83
  describe "every accessible has(n) association with :allow_destroy => false", :shared => true do
@@ -99,14 +103,18 @@ describe "every accessible has(n) association with :allow_destroy => true", :sha
99
103
  it "should allow to delete an existing task via Profile#tasks_attributes" do
100
104
  @project.save
101
105
  task = Task.create(:project => @project, :name => 'write specs')
106
+ @project.tasks.reload
102
107
 
103
108
  Project.all.size.should == 1
104
109
  Task.all.size.should == 1
105
-
106
- @project.tasks << task
110
+
107
111
  @project.tasks_attributes = { '1' => { :id => task.id, :_delete => true } }
112
+
113
+ Project.all.size.should == 1
114
+ Task.all.size.should == 1
115
+
108
116
  @project.save
109
-
117
+
110
118
  Project.all.size.should == 1
111
119
  Task.all.size.should == 0
112
120
  end
@@ -23,25 +23,6 @@ describe "every accessible has(n, :through) association", :shared => true do
23
23
  Project.first.name.should == 'still dm-accepts_nested_attributes'
24
24
  end
25
25
 
26
- it "should perform atomic commits" do
27
-
28
- @person.projects_attributes = { 'new_1' => { :name => nil } } # should fail because of validations
29
- @person.save
30
-
31
- Person.all.size.should == 0 # TODO think more if this should be '1'
32
- ProjectMembership.all.size.should == 0
33
- Project.all.size.should == 0
34
-
35
- @person.name = nil # should fail because of validations
36
- @person.projects_attributes = { 'new_1' => { :name => nil } }
37
- @person.save
38
-
39
- Person.all.size.should == 0
40
- ProjectMembership.all.size.should == 0
41
- Project.all.size.should == 0
42
-
43
- end
44
-
45
26
  it "should return the attributes written to Person#projects_attributes from the Person#projects_attributes reader" do
46
27
  @person.projects_attributes.should be_nil
47
28
  @person.projects_attributes = { 'new_1' => { :name => 'write specs' } }
@@ -85,6 +66,11 @@ describe "every accessible has(n, :through) association with no reject_if proc",
85
66
  Project.all.size.should == 0
86
67
 
87
68
  @person.projects_attributes = { 'new_1' => { :name => 'dm-accepts_nested_attributes' } }
69
+
70
+ Person.all.size.should == 1
71
+ ProjectMembership.all.size.should == 0
72
+ Project.all.size.should == 0
73
+
88
74
  @person.save
89
75
 
90
76
  Person.all.size.should == 1
@@ -94,6 +80,25 @@ describe "every accessible has(n, :through) association with no reject_if proc",
94
80
  Project.first.name.should == 'dm-accepts_nested_attributes'
95
81
  end
96
82
 
83
+ it "should perform atomic commits" do
84
+
85
+ @person.projects_attributes = { 'new_1' => { :name => nil } } # should fail because of validations
86
+ @person.save
87
+
88
+ Person.all.size.should == 0 # TODO think more if this should be '1'
89
+ ProjectMembership.all.size.should == 0
90
+ Project.all.size.should == 0
91
+
92
+ @person.name = nil # should fail because of validations
93
+ @person.projects_attributes = { 'new_1' => { :name => nil } }
94
+ @person.save
95
+
96
+ Person.all.size.should == 0
97
+ ProjectMembership.all.size.should == 0
98
+ Project.all.size.should == 0
99
+
100
+ end
101
+
97
102
  end
98
103
 
99
104
  describe "every accessible has(n, :through) association with :allow_destroy => false", :shared => true do
@@ -108,6 +113,11 @@ describe "every accessible has(n, :through) association with :allow_destroy => f
108
113
  Project.all.size.should == 1
109
114
 
110
115
  @person.projects_attributes = { '1' => { :id => project.id, :_delete => true } }
116
+
117
+ Person.all.size.should == 1
118
+ ProjectMembership.all.size.should == 1
119
+ Project.all.size.should == 1
120
+
111
121
  @person.save
112
122
 
113
123
  Person.all.size.should == 1
@@ -121,19 +131,26 @@ describe "every accessible has(n, :through) association with :allow_destroy => t
121
131
 
122
132
  it "should allow to delete an existing project via Person#projects_attributes" do
123
133
  @person.save
124
- project = Project.create(:name => 'dm-accepts_nested_attributes')
125
- project_membership = ProjectMembership.create(:person => @person, :project => project)
134
+ project_1 = Project.create(:name => 'dm-accepts_nested_attributes')
135
+ project_2 = Project.create(:name => 'dm-is-localizable')
136
+ project_membership_1 = ProjectMembership.create(:person => @person, :project => project_1)
137
+ project_membership_2 = ProjectMembership.create(:person => @person, :project => project_2)
126
138
 
127
139
  Person.all.size.should == 1
128
- ProjectMembership.all.size.should == 1
129
- Project.all.size.should == 1
130
-
131
- @person.projects_attributes = { '1' => { :id => project.id, :_delete => true } }
140
+ ProjectMembership.all.size.should == 2
141
+ Project.all.size.should == 2
142
+
143
+ @person.projects_attributes = { '1' => { :id => project_1.id, :_delete => true } }
144
+
145
+ Person.all.size.should == 1
146
+ ProjectMembership.all.size.should == 2
147
+ Project.all.size.should == 2
148
+
132
149
  @person.save
133
-
150
+
134
151
  Person.all.size.should == 1
135
- ProjectMembership.all.size.should == 0
136
- Project.all.size.should == 0
152
+ ProjectMembership.all.size.should == 1
153
+ Project.all.size.should == 1
137
154
  end
138
155
 
139
156
  end