snusnu-dm-accepts_nested_attributes 0.0.1 → 0.0.2
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/Manifest.txt +4 -0
- data/README.textile +26 -5
- data/lib/dm-accepts_nested_attributes/nested_attributes.rb +104 -4
- data/lib/dm-accepts_nested_attributes/version.rb +1 -1
- data/spec/fixtures/photo.rb +9 -0
- data/spec/fixtures/profile.rb +1 -1
- data/spec/fixtures/project_membership.rb +2 -2
- data/spec/fixtures/tag.rb +12 -0
- data/spec/fixtures/tagging.rb +10 -0
- data/spec/fixtures/task.rb +1 -1
- data/spec/integration/belongs_to_spec.rb +16 -4
- data/spec/integration/has_1_spec.rb +14 -1
- data/spec/integration/has_n_spec.rb +14 -1
- data/spec/integration/has_n_through_renamed_spec.rb +214 -0
- data/spec/integration/has_n_through_spec.rb +15 -1
- data/spec/shared/rspec_tmbundle_support.rb +1 -1
- data/spec/spec_helper.rb +8 -10
- data/spec/unit/accepts_nested_attributes_for_spec.rb +34 -2
- metadata +6 -2
data/Manifest.txt
CHANGED
@@ -10,13 +10,17 @@ lib/dm-accepts_nested_attributes/associations.rb
|
|
10
10
|
lib/dm-accepts_nested_attributes/nested_attributes.rb
|
11
11
|
lib/dm-accepts_nested_attributes/version.rb
|
12
12
|
spec/fixtures/person.rb
|
13
|
+
spec/fixtures/photo.rb
|
13
14
|
spec/fixtures/profile.rb
|
14
15
|
spec/fixtures/project.rb
|
15
16
|
spec/fixtures/project_membership.rb
|
17
|
+
spec/fixtures/tag.rb
|
18
|
+
spec/fixtures/tagging.rb
|
16
19
|
spec/fixtures/task.rb
|
17
20
|
spec/integration/belongs_to_spec.rb
|
18
21
|
spec/integration/has_1_spec.rb
|
19
22
|
spec/integration/has_n_spec.rb
|
23
|
+
spec/integration/has_n_through_renamed_spec.rb
|
20
24
|
spec/integration/has_n_through_spec.rb
|
21
25
|
spec/shared/rspec_tmbundle_support.rb
|
22
26
|
spec/spec.opts
|
data/README.textile
CHANGED
@@ -8,6 +8,32 @@ For more information on the progress, have a look at this README and also at
|
|
8
8
|
"this article":http://sick.snusnu.info/2009/04/08/dm-accepts_nested_attributes/ on my blog, where I will try to comment on the
|
9
9
|
development (problems).
|
10
10
|
|
11
|
+
h2. Current limitations
|
12
|
+
|
13
|
+
Interaction with @dm-validations@ is actually possible but not very well specced atm. I added @not null@
|
14
|
+
constraints to all spec fixtures for now, but no other custom validations. All specs still pass. However,
|
15
|
+
as long as I'm not decided on where to put the specs for interaction with @dm-validations@ (most probably
|
16
|
+
inside @dm-validations@ would be the right place for these), I won't write many more specs for these scenarios,
|
17
|
+
since it's very hard to decide where to stop, once I start writing some.
|
18
|
+
|
19
|
+
Currently, the creation of the record together with all its join models, is not handled inside a transaction.
|
20
|
+
This must definitely change! As soon as I find out why my initial experiments with transactions consistently
|
21
|
+
yielded _no such table errors_ while migrating the specsuite (see "this pastie":http://pastie.org/446060), I
|
22
|
+
will do my best to add this feature.
|
23
|
+
|
24
|
+
h2. TODO
|
25
|
+
|
26
|
+
* use transactions
|
27
|
+
* update README to include more complete usecases
|
28
|
+
* specs for custom validations (dm-validations in general)
|
29
|
+
* specs for adding errors to the parent objects
|
30
|
+
* reorganize specs and fix bugs
|
31
|
+
* Adapt to datamapper/next
|
32
|
+
|
33
|
+
h2. Implementation details
|
34
|
+
|
35
|
+
This section mainly serves as a place for me to take notes during development.
|
36
|
+
|
11
37
|
h3. Why isn't this implemented as options on association declarations?
|
12
38
|
|
13
39
|
* I somehow like the declarative style of @accepts_nested_attributes_for@ better. it jumps out immediately.
|
@@ -243,8 +269,3 @@ DataMapper::NestedAttributes Person.has(n, :projects, :through => :project_membe
|
|
243
269
|
- should not allow to delete an existing project via Person#projects_attributes
|
244
270
|
</code>
|
245
271
|
</pre>
|
246
|
-
|
247
|
-
h2. TODO
|
248
|
-
|
249
|
-
* add more specs and fix bugs
|
250
|
-
* Adapt to datamapper/next
|
@@ -9,9 +9,14 @@ module DataMapper
|
|
9
9
|
|
10
10
|
module ClassMethods
|
11
11
|
|
12
|
-
# Defines an attributes writer for the specified association(s).
|
13
|
-
# are using <tt>attr_protected</tt> or <tt>attr_accessible</tt>,
|
14
|
-
# will need to add the attribute writer to the allowed list.
|
12
|
+
# Defines an attributes reader and writer for the specified association(s).
|
13
|
+
# If you are using <tt>attr_protected</tt> or <tt>attr_accessible</tt>,
|
14
|
+
# then you will need to add the attribute writer to the allowed list.
|
15
|
+
#
|
16
|
+
# After any params are passed to the attributes writer they are available
|
17
|
+
# via the attributes reader (they are stored in an instance variable of
|
18
|
+
# the same name). The attributes reader returns nil if the attributes
|
19
|
+
# writer has not been called.
|
15
20
|
#
|
16
21
|
# Supported options:
|
17
22
|
# [:allow_destroy]
|
@@ -26,8 +31,10 @@ module DataMapper
|
|
26
31
|
# do not have a <tt>_delete</tt> that evaluates to true.
|
27
32
|
#
|
28
33
|
# Examples:
|
34
|
+
# # creates avatar_attributes
|
29
35
|
# # creates avatar_attributes=
|
30
36
|
# accepts_nested_attributes_for :avatar, :reject_if => proc { |attributes| attributes['name'].blank? }
|
37
|
+
# # creates avatar_attributes and posts_attributes
|
31
38
|
# # creates avatar_attributes= and posts_attributes=
|
32
39
|
# accepts_nested_attributes_for :avatar, :posts, :allow_destroy => true
|
33
40
|
def accepts_nested_attributes_for(association_name, options = {})
|
@@ -56,7 +63,12 @@ module DataMapper
|
|
56
63
|
|
57
64
|
class_eval %{
|
58
65
|
|
66
|
+
def #{association_name}_attributes
|
67
|
+
@#{association_name}_attributes
|
68
|
+
end
|
69
|
+
|
59
70
|
def #{association_name}_attributes=(attributes)
|
71
|
+
@#{association_name}_attributes = attributes
|
60
72
|
assign_nested_attributes_for_#{type}_association(:#{association_name}, attributes, #{options[:allow_destroy]})
|
61
73
|
end
|
62
74
|
|
@@ -141,6 +153,94 @@ module DataMapper
|
|
141
153
|
|
142
154
|
# instance methods
|
143
155
|
|
156
|
+
|
157
|
+
if ::DataMapper.const_defined?('Validate')
|
158
|
+
|
159
|
+
# NOTE:
|
160
|
+
# overwriting Resource#save like this breaks the before(:save) hook stack
|
161
|
+
# this hopefully is no problem, since the current implementation doesn't rely on
|
162
|
+
# a before(:save) hook, but rather overwrites this hook with a no-op, and adds
|
163
|
+
# the desired behavior via overwriting Resource#save directly. I'd really appreciate
|
164
|
+
# any ideas for doing this differently, though. Anyways, I'm not really sure if this
|
165
|
+
# is the right approach. I don't even know if it works with custom validations,
|
166
|
+
# or maybe breaks other things. It's also really not well specced at all atm.
|
167
|
+
# Use at your own risk :-)
|
168
|
+
|
169
|
+
def save(context = :default)
|
170
|
+
|
171
|
+
# -----------------------------------------------------------------
|
172
|
+
# ORIGINAL CODE from Resource#save
|
173
|
+
# -----------------------------------------------------------------
|
174
|
+
#
|
175
|
+
# associations_saved = false
|
176
|
+
# child_associations.each { |a| associations_saved |= a.save }
|
177
|
+
#
|
178
|
+
# saved = new_record? ? create : update
|
179
|
+
#
|
180
|
+
# if saved
|
181
|
+
# original_values.clear
|
182
|
+
# end
|
183
|
+
#
|
184
|
+
# parent_associations.each { |a| associations_saved |= a.save }
|
185
|
+
#
|
186
|
+
# # We should return true if the model (or any of its associations)
|
187
|
+
# # were saved.
|
188
|
+
# (saved | associations_saved) == true
|
189
|
+
#
|
190
|
+
# -----------------------------------------------------------------
|
191
|
+
|
192
|
+
|
193
|
+
return super if context.nil? # preserve save! behavior
|
194
|
+
|
195
|
+
associations_saved = false
|
196
|
+
|
197
|
+
child_associations.each do |a|
|
198
|
+
|
199
|
+
if a.respond_to?(:valid?)
|
200
|
+
a.errors.each { |e| self.errors.add(:general, e) } unless a.valid?(context)
|
201
|
+
else
|
202
|
+
self.errors.add(:general, "child association is missing")
|
203
|
+
end
|
204
|
+
|
205
|
+
associations_saved |= a.save
|
206
|
+
|
207
|
+
end
|
208
|
+
|
209
|
+
saved = self.valid? && (new_record? ? create : update)
|
210
|
+
|
211
|
+
if saved
|
212
|
+
original_values.clear
|
213
|
+
end
|
214
|
+
|
215
|
+
parent_associations.each do |a|
|
216
|
+
|
217
|
+
if a.respond_to?(:each)
|
218
|
+
a.each do |r|
|
219
|
+
r.errors.each { |e| self.errors.add(:general, e) } unless r.valid?(context)
|
220
|
+
end
|
221
|
+
else
|
222
|
+
a.errors.each { |e| self.errors.add(:general, e) } unless a.valid?(context)
|
223
|
+
end
|
224
|
+
|
225
|
+
associations_saved |= a.save
|
226
|
+
|
227
|
+
end
|
228
|
+
|
229
|
+
(saved | associations_saved) == true
|
230
|
+
|
231
|
+
end
|
232
|
+
|
233
|
+
# everything works the same if this method isn't overwritten with a no-op
|
234
|
+
# however, i suspect that this is the case because the registered before(:save) hook
|
235
|
+
# somehow gets lost when overwriting Resource#save here in this module.
|
236
|
+
# I'll leave it in for now, to make the purpose clear
|
237
|
+
|
238
|
+
def check_validations(context = :default)
|
239
|
+
true # no-op, validations are checked inside #save
|
240
|
+
end
|
241
|
+
|
242
|
+
end
|
243
|
+
|
144
244
|
# returns nil if no resource has been associated yet
|
145
245
|
def associated_instance_get(association_name, repository = :default)
|
146
246
|
send(self.class.association_for_name(association_name, repository).name)
|
@@ -252,7 +352,7 @@ module DataMapper
|
|
252
352
|
# do what's done in dm-core/specs/integration/association_through_spec.rb
|
253
353
|
|
254
354
|
# explicitly build the join entry and assign it to the join association
|
255
|
-
join_entry =
|
355
|
+
join_entry = self.class.associated_model_for_name(association.name).new
|
256
356
|
self.send(association.name) << join_entry
|
257
357
|
self.save
|
258
358
|
# explicitly build the child entry and assign the join entry to its join association
|
data/spec/fixtures/profile.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
class ProjectMembership
|
2
2
|
include DataMapper::Resource
|
3
3
|
property :id, Serial
|
4
|
-
property :person_id, Integer
|
5
|
-
property :project_id, Integer
|
4
|
+
property :person_id, Integer, :nullable => false
|
5
|
+
property :project_id, Integer, :nullable => false
|
6
6
|
belongs_to :person
|
7
7
|
belongs_to :project
|
8
8
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class Tag
|
2
|
+
include DataMapper::Resource
|
3
|
+
|
4
|
+
property :id, Serial
|
5
|
+
property :name, String
|
6
|
+
|
7
|
+
has n, :tagged_things, :class_name => "Tagging"
|
8
|
+
has n, :pictures, :through => :tagged_things,
|
9
|
+
:class_name => 'Photo',
|
10
|
+
:child_key => [:tag_id],
|
11
|
+
:remote_name => :photo
|
12
|
+
end
|
data/spec/fixtures/task.rb
CHANGED
@@ -7,7 +7,6 @@ describe DataMapper::NestedAttributes do
|
|
7
7
|
describe "every accessible belongs_to association with no associated parent model", :shared => true do
|
8
8
|
|
9
9
|
it "should return a new_record from get_\#{association_name}" do
|
10
|
-
@profile.person_attributes = { :name => 'Martin' }
|
11
10
|
@profile.get_person.should_not be_nil
|
12
11
|
@profile.get_person.should be_new_record
|
13
12
|
end
|
@@ -33,8 +32,8 @@ describe DataMapper::NestedAttributes do
|
|
33
32
|
it "should not allow to create a new person via Profile#person_attributes" do
|
34
33
|
@profile.person_attributes = { :name => 'Martin' }
|
35
34
|
@profile.person.should be_nil
|
36
|
-
@profile.save
|
37
|
-
Profile.all.size.should ==
|
35
|
+
@profile.save # fails because of validations (not null on belongs_to)
|
36
|
+
Profile.all.size.should == 0
|
38
37
|
Person.all.size.should == 0
|
39
38
|
end
|
40
39
|
|
@@ -112,7 +111,19 @@ describe DataMapper::NestedAttributes do
|
|
112
111
|
Profile.all.size.should == 1
|
113
112
|
Person.all.size.should == 0
|
114
113
|
end
|
114
|
+
|
115
|
+
end
|
115
116
|
|
117
|
+
describe "every accessible belongs_to association with a nested attributes reader", :shared => true do
|
118
|
+
|
119
|
+
it "should return the attributes written to Profile#person_attributes from the Profile#person_attributes reader" do
|
120
|
+
@profile.person_attributes.should be_nil
|
121
|
+
|
122
|
+
@profile.person_attributes = { :name => 'Martin' }
|
123
|
+
|
124
|
+
@profile.person_attributes.should == { :name => 'Martin' }
|
125
|
+
end
|
126
|
+
|
116
127
|
end
|
117
128
|
|
118
129
|
describe "Profile.belongs_to(:person)" do
|
@@ -127,6 +138,7 @@ describe DataMapper::NestedAttributes do
|
|
127
138
|
|
128
139
|
it_should_behave_like "every accessible belongs_to association with no reject_if proc"
|
129
140
|
it_should_behave_like "every accessible belongs_to association with :allow_destroy => false"
|
141
|
+
it_should_behave_like "every accessible belongs_to association with a nested attributes reader"
|
130
142
|
|
131
143
|
end
|
132
144
|
|
@@ -201,4 +213,4 @@ describe DataMapper::NestedAttributes do
|
|
201
213
|
|
202
214
|
end
|
203
215
|
|
204
|
-
end
|
216
|
+
end
|
@@ -101,6 +101,18 @@ describe DataMapper::NestedAttributes do
|
|
101
101
|
end
|
102
102
|
|
103
103
|
end
|
104
|
+
|
105
|
+
describe "every accessible has(1) association with a nested attributes reader", :shared => true do
|
106
|
+
|
107
|
+
it "should return the attributes written to Person#profile_attributes from the Person#profile_attributes reader" do
|
108
|
+
@person.profile_attributes.should be_nil
|
109
|
+
|
110
|
+
@person.profile_attributes = { :nick => 'snusnu' }
|
111
|
+
|
112
|
+
@person.profile_attributes.should == { :nick => 'snusnu' }
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
104
116
|
|
105
117
|
describe "Person.has(1, :profile)" do
|
106
118
|
|
@@ -114,6 +126,7 @@ describe DataMapper::NestedAttributes do
|
|
114
126
|
|
115
127
|
it_should_behave_like "every accessible has(1) association with no reject_if proc"
|
116
128
|
it_should_behave_like "every accessible has(1) association with :allow_destroy => false"
|
129
|
+
it_should_behave_like "every accessible has(1) association with a nested attributes reader"
|
117
130
|
|
118
131
|
end
|
119
132
|
|
@@ -190,4 +203,4 @@ describe DataMapper::NestedAttributes do
|
|
190
203
|
|
191
204
|
end
|
192
205
|
|
193
|
-
end
|
206
|
+
end
|
@@ -91,6 +91,18 @@ describe DataMapper::NestedAttributes do
|
|
91
91
|
end
|
92
92
|
|
93
93
|
end
|
94
|
+
|
95
|
+
describe "every accessible has(n) association with a nested attributes reader", :shared => true do
|
96
|
+
|
97
|
+
it "should return the attributes written to Project#task_attributes from the Project#task_attributes reader" do
|
98
|
+
@project.tasks_attributes.should be_nil
|
99
|
+
|
100
|
+
@project.tasks_attributes = { 'new_1' => { :name => 'write specs' } }
|
101
|
+
|
102
|
+
@project.tasks_attributes.should == { 'new_1' => { :name => 'write specs' } }
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
94
106
|
|
95
107
|
describe "Project.has(n, :tasks)" do
|
96
108
|
|
@@ -104,6 +116,7 @@ describe DataMapper::NestedAttributes do
|
|
104
116
|
|
105
117
|
it_should_behave_like "every accessible has(n) association with no reject_if proc"
|
106
118
|
it_should_behave_like "every accessible has(n) association with :allow_destroy => false"
|
119
|
+
it_should_behave_like "every accessible has(n) association with a nested attributes reader"
|
107
120
|
|
108
121
|
end
|
109
122
|
|
@@ -178,4 +191,4 @@ describe DataMapper::NestedAttributes do
|
|
178
191
|
|
179
192
|
end
|
180
193
|
|
181
|
-
end
|
194
|
+
end
|
@@ -0,0 +1,214 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
|
3
|
+
|
4
|
+
# TODO: this is overkill - really should use some more focussed unit tests instead
|
5
|
+
describe DataMapper::NestedAttributes do
|
6
|
+
|
7
|
+
describe "every accessible has(n, :through) renamed association with a valid reject_if proc", :shared => true do
|
8
|
+
|
9
|
+
it "should not allow to create a new picture via Tag#pictures_attributes" do
|
10
|
+
@tag.save
|
11
|
+
Tag.all.size.should == 1
|
12
|
+
Tagging.all.size.should == 0
|
13
|
+
Photo.all.size.should == 0
|
14
|
+
|
15
|
+
@tag.pictures_attributes = { 'new_1' => { :name => 'dm-accepts_nested_attributes' } }
|
16
|
+
@tag.pictures.should be_empty
|
17
|
+
@tag.save
|
18
|
+
|
19
|
+
Tag.all.size.should == 1
|
20
|
+
Tagging.all.size.should == 0
|
21
|
+
Photo.all.size.should == 0
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "every accessible has(n, :through) renamed association with no reject_if proc", :shared => true do
|
27
|
+
|
28
|
+
it "should allow to create a new picture via Tag#pictures_attributes" do
|
29
|
+
@tag.save
|
30
|
+
Tag.all.size.should == 1
|
31
|
+
Tagging.all.size.should == 0
|
32
|
+
Photo.all.size.should == 0
|
33
|
+
|
34
|
+
@tag.pictures_attributes = { 'new_1' => { :name => 'dm-accepts_nested_attributes' } }
|
35
|
+
@tag.pictures.should_not be_empty
|
36
|
+
@tag.pictures.first.name.should == 'dm-accepts_nested_attributes'
|
37
|
+
@tag.save
|
38
|
+
@tag.pictures.first.should == Photo.first
|
39
|
+
|
40
|
+
Tag.all.size.should == 1
|
41
|
+
Tagging.all.size.should == 1
|
42
|
+
Photo.all.size.should == 1
|
43
|
+
|
44
|
+
Photo.first.name.should == 'dm-accepts_nested_attributes'
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should allow to update an existing picture via Tag#pictures_attributes" do
|
48
|
+
@tag.save
|
49
|
+
photo = Photo.create(:name => 'dm-accepts_nested_attributes')
|
50
|
+
tagging = Tagging.create(:tag => @tag, :photo => photo)
|
51
|
+
Tag.all.size.should == 1
|
52
|
+
Photo.all.size.should == 1
|
53
|
+
Tagging.all.size.should == 1
|
54
|
+
|
55
|
+
@tag.reload
|
56
|
+
|
57
|
+
@tag.pictures_attributes = { photo.id.to_s => { :id => photo.id, :name => 'still dm-accepts_nested_attributes' } }
|
58
|
+
@tag.pictures.should_not be_empty
|
59
|
+
@tag.pictures.first.name.should == 'still dm-accepts_nested_attributes'
|
60
|
+
@tag.save
|
61
|
+
|
62
|
+
Tag.all.size.should == 1
|
63
|
+
Tagging.all.size.should == 1
|
64
|
+
Photo.all.size.should == 1
|
65
|
+
|
66
|
+
Photo.first.name.should == 'still dm-accepts_nested_attributes'
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "every accessible has(n, :through) renamed association with :allow_destroy => false", :shared => true do
|
72
|
+
|
73
|
+
it "should not allow to delete an existing picture via Tag#pictures_attributes" do
|
74
|
+
@tag.save
|
75
|
+
photo = Photo.create(:name => 'dm-accepts_nested_attributes')
|
76
|
+
tagging = Tagging.create(:tag => @tag, :photo => photo)
|
77
|
+
|
78
|
+
Tag.all.size.should == 1
|
79
|
+
Tagging.all.size.should == 1
|
80
|
+
Photo.all.size.should == 1
|
81
|
+
|
82
|
+
@tag.reload
|
83
|
+
@tag.pictures_attributes = { '1' => { :id => photo.id, :_delete => true } }
|
84
|
+
@tag.save
|
85
|
+
|
86
|
+
Tag.all.size.should == 1
|
87
|
+
Tagging.all.size.should == 1
|
88
|
+
Photo.all.size.should == 1
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
describe "every accessible has(n, :through) renamed association with :allow_destroy => true", :shared => true do
|
94
|
+
|
95
|
+
it "should allow to delete an existing picture via Tag#pictures_attributes" do
|
96
|
+
@tag.save
|
97
|
+
photo = Photo.create(:name => 'dm-accepts_nested_attributes')
|
98
|
+
tagging = Tagging.create(:tag => @tag, :photo => photo)
|
99
|
+
|
100
|
+
Tag.all.size.should == 1
|
101
|
+
Tagging.all.size.should == 1
|
102
|
+
Photo.all.size.should == 1
|
103
|
+
|
104
|
+
@tag.reload
|
105
|
+
@tag.pictures_attributes = { '1' => { :id => photo.id, :_delete => true } }
|
106
|
+
@tag.save
|
107
|
+
|
108
|
+
Tag.all.size.should == 1
|
109
|
+
Tagging.all.size.should == 0
|
110
|
+
Photo.all.size.should == 0
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
describe "every accessible has(n, :through) renamed association with a nested attributes reader", :shared => true do
|
116
|
+
|
117
|
+
it "should return the attributes written to Tag#pictures_attributes from the Tag#pictures_attributes reader" do
|
118
|
+
@tag.pictures_attributes.should be_nil
|
119
|
+
|
120
|
+
@tag.pictures_attributes = { 'new_1' => { :name => 'write specs' } }
|
121
|
+
|
122
|
+
@tag.pictures_attributes.should == { 'new_1' => { :name => 'write specs' } }
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
describe "Tag.has(n, :pictures, :through => :taggings) renamed" do
|
128
|
+
|
129
|
+
describe "accepts_nested_attributes_for(:pictures)" do
|
130
|
+
|
131
|
+
before(:each) do
|
132
|
+
DataMapper.auto_migrate!
|
133
|
+
Tag.accepts_nested_attributes_for :pictures
|
134
|
+
@tag = Tag.new :name => 'snusnu'
|
135
|
+
end
|
136
|
+
|
137
|
+
it_should_behave_like "every accessible has(n, :through) renamed association with no reject_if proc"
|
138
|
+
it_should_behave_like "every accessible has(n, :through) renamed association with :allow_destroy => false"
|
139
|
+
it_should_behave_like "every accessible has(n, :through) renamed association with a nested attributes reader"
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
describe "accepts_nested_attributes_for(:pictures, :allow_destroy => false)" do
|
144
|
+
|
145
|
+
before(:each) do
|
146
|
+
DataMapper.auto_migrate!
|
147
|
+
Tag.accepts_nested_attributes_for :pictures, :allow_destroy => false
|
148
|
+
@tag = Tag.new :name => 'snusnu'
|
149
|
+
end
|
150
|
+
|
151
|
+
it_should_behave_like "every accessible has(n, :through) renamed association with no reject_if proc"
|
152
|
+
it_should_behave_like "every accessible has(n, :through) renamed association with :allow_destroy => false"
|
153
|
+
|
154
|
+
end
|
155
|
+
|
156
|
+
describe "accepts_nested_attributes_for(:pictures, :allow_destroy = true)" do
|
157
|
+
|
158
|
+
before(:each) do
|
159
|
+
DataMapper.auto_migrate!
|
160
|
+
Tag.accepts_nested_attributes_for :pictures, :allow_destroy => true
|
161
|
+
@tag = Tag.new :name => 'snusnu'
|
162
|
+
end
|
163
|
+
|
164
|
+
it_should_behave_like "every accessible has(n, :through) renamed association with no reject_if proc"
|
165
|
+
it_should_behave_like "every accessible has(n, :through) renamed association with :allow_destroy => true"
|
166
|
+
|
167
|
+
end
|
168
|
+
|
169
|
+
describe "accepts_nested_attributes_for :pictures, " do
|
170
|
+
|
171
|
+
describe ":reject_if => :foo" do
|
172
|
+
|
173
|
+
before(:each) do
|
174
|
+
DataMapper.auto_migrate!
|
175
|
+
Tag.accepts_nested_attributes_for :pictures, :reject_if => :foo
|
176
|
+
@tag = Tag.new :name => 'snusnu'
|
177
|
+
end
|
178
|
+
|
179
|
+
it_should_behave_like "every accessible has(n, :through) renamed association with no reject_if proc"
|
180
|
+
it_should_behave_like "every accessible has(n, :through) renamed association with :allow_destroy => false"
|
181
|
+
|
182
|
+
end
|
183
|
+
|
184
|
+
describe ":reject_if => lambda { |attrs| true }" do
|
185
|
+
|
186
|
+
before(:each) do
|
187
|
+
DataMapper.auto_migrate!
|
188
|
+
Tag.accepts_nested_attributes_for :pictures, :reject_if => lambda { |attrs| true }
|
189
|
+
@tag = Tag.new :name => 'snusnu'
|
190
|
+
end
|
191
|
+
|
192
|
+
it_should_behave_like "every accessible has(n, :through) renamed association with a valid reject_if proc"
|
193
|
+
it_should_behave_like "every accessible has(n, :through) renamed association with :allow_destroy => false"
|
194
|
+
|
195
|
+
end
|
196
|
+
|
197
|
+
describe ":reject_if => lambda { |attrs| false }" do
|
198
|
+
|
199
|
+
before(:each) do
|
200
|
+
DataMapper.auto_migrate!
|
201
|
+
Tag.accepts_nested_attributes_for :pictures, :reject_if => lambda { |attrs| false }
|
202
|
+
@tag = Tag.new :name => 'snusnu'
|
203
|
+
end
|
204
|
+
|
205
|
+
it_should_behave_like "every accessible has(n, :through) renamed association with no reject_if proc"
|
206
|
+
it_should_behave_like "every accessible has(n, :through) renamed association with :allow_destroy => false"
|
207
|
+
|
208
|
+
end
|
209
|
+
|
210
|
+
end
|
211
|
+
|
212
|
+
end
|
213
|
+
|
214
|
+
end
|
@@ -110,6 +110,18 @@ describe DataMapper::NestedAttributes do
|
|
110
110
|
end
|
111
111
|
|
112
112
|
end
|
113
|
+
|
114
|
+
describe "every accessible has(n, :through) association with a nested attributes reader", :shared => true do
|
115
|
+
|
116
|
+
it "should return the attributes written to Person#projects_attributes from the Person#projects_attributes reader" do
|
117
|
+
@person.projects_attributes.should be_nil
|
118
|
+
|
119
|
+
@person.projects_attributes = { 'new_1' => { :name => 'write specs' } }
|
120
|
+
|
121
|
+
@person.projects_attributes.should == { 'new_1' => { :name => 'write specs' } }
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
113
125
|
|
114
126
|
describe "Person.has(n, :projects, :through => :project_memberships)" do
|
115
127
|
|
@@ -123,6 +135,7 @@ describe DataMapper::NestedAttributes do
|
|
123
135
|
|
124
136
|
it_should_behave_like "every accessible has(n, :through) association with no reject_if proc"
|
125
137
|
it_should_behave_like "every accessible has(n, :through) association with :allow_destroy => false"
|
138
|
+
it_should_behave_like "every accessible has(n, :through) association with a nested attributes reader"
|
126
139
|
|
127
140
|
end
|
128
141
|
|
@@ -197,4 +210,5 @@ describe DataMapper::NestedAttributes do
|
|
197
210
|
|
198
211
|
end
|
199
212
|
|
200
|
-
end
|
213
|
+
end
|
214
|
+
|
data/spec/spec_helper.rb
CHANGED
@@ -13,8 +13,8 @@ require 'dm-validations'
|
|
13
13
|
require Pathname(__FILE__).dirname.parent.expand_path + 'lib/dm-accepts_nested_attributes'
|
14
14
|
|
15
15
|
ENV["SQLITE3_SPEC_URI"] ||= 'sqlite3::memory:'
|
16
|
-
ENV["MYSQL_SPEC_URI"] ||= 'mysql://localhost/
|
17
|
-
ENV["POSTGRES_SPEC_URI"] ||= 'postgres://postgres@localhost/
|
16
|
+
ENV["MYSQL_SPEC_URI"] ||= 'mysql://localhost/dm-accepts_nested_attributes_test'
|
17
|
+
ENV["POSTGRES_SPEC_URI"] ||= 'postgres://postgres@localhost/dm-accepts_nested_attributes_test'
|
18
18
|
|
19
19
|
|
20
20
|
def setup_adapter(name, default_uri = nil)
|
@@ -30,13 +30,6 @@ def setup_adapter(name, default_uri = nil)
|
|
30
30
|
false
|
31
31
|
end
|
32
32
|
end
|
33
|
-
|
34
|
-
ENV['ADAPTER'] ||= 'sqlite3'
|
35
|
-
|
36
|
-
|
37
|
-
setup_adapter(:default)
|
38
|
-
Dir[Pathname(__FILE__).dirname.to_s + "/fixtures/**/*.rb"].each { |rb| require(rb) }
|
39
|
-
|
40
33
|
|
41
34
|
# -----------------------------------------------
|
42
35
|
# support for nice html output in rspec tmbundle
|
@@ -50,9 +43,14 @@ if USE_TEXTMATE_RSPEC_BUNDLE
|
|
50
43
|
|
51
44
|
# use the tmbundle logger
|
52
45
|
RSpecTmBundleHelpers::TextmateRspecLogger.new(STDOUT, :off)
|
46
|
+
|
53
47
|
|
54
48
|
class Object
|
55
49
|
include RSpecTmBundleHelpers
|
56
50
|
end
|
57
51
|
|
58
|
-
end
|
52
|
+
end
|
53
|
+
|
54
|
+
ENV['ADAPTER'] ||= 'sqlite3'
|
55
|
+
setup_adapter(:default)
|
56
|
+
Dir[Pathname(__FILE__).dirname.to_s + "/fixtures/**/*.rb"].each { |rb| require(rb) }
|
@@ -181,6 +181,14 @@ describe "DataMapper::Model.accepts_nested_attributes_for" do
|
|
181
181
|
@model.autosave_associations[@association].should == { :allow_destroy => false }
|
182
182
|
end
|
183
183
|
|
184
|
+
it "should create a \#{association_name}_attributes instance reader" do
|
185
|
+
p = @model.new
|
186
|
+
p.respond_to?("#{@association}_attributes").should be_false
|
187
|
+
@model.accepts_nested_attributes_for @association
|
188
|
+
p = @model.new
|
189
|
+
p.respond_to?("#{@association}_attributes").should be_true
|
190
|
+
end
|
191
|
+
|
184
192
|
it "should create a \#{association_name}_attributes instance writer" do
|
185
193
|
p = @model.new
|
186
194
|
p.respond_to?("#{@association}_attributes=").should be_false
|
@@ -209,6 +217,14 @@ describe "DataMapper::Model.accepts_nested_attributes_for" do
|
|
209
217
|
@model.autosave_associations[@association].should == { :allow_destroy => false }
|
210
218
|
end
|
211
219
|
|
220
|
+
it "should create a \#{association_name}_attributes instance reader" do
|
221
|
+
p = @model.new
|
222
|
+
p.respond_to?("#{@association}_attributes").should be_false
|
223
|
+
@model.accepts_nested_attributes_for @association, {}
|
224
|
+
p = @model.new
|
225
|
+
p.respond_to?("#{@association}_attributes").should be_true
|
226
|
+
end
|
227
|
+
|
212
228
|
it "should create a \#{association_name}_attributes instance writer" do
|
213
229
|
p = @model.new
|
214
230
|
p.respond_to?("#{@association}_attributes=").should be_false
|
@@ -231,6 +247,14 @@ describe "DataMapper::Model.accepts_nested_attributes_for" do
|
|
231
247
|
@model.autosave_associations[@association].should be_nil
|
232
248
|
end
|
233
249
|
|
250
|
+
it "should not create a \#{association_name}_attributes instance reader" do
|
251
|
+
p = @model.new
|
252
|
+
p.respond_to?("#{@association}_attributes").should be_false
|
253
|
+
lambda { @model.accepts_nested_attributes_for @association, { :foo => :bar } }.should raise_error
|
254
|
+
p = @model.new
|
255
|
+
p.respond_to?("#{@association}_attributes").should be_false
|
256
|
+
end
|
257
|
+
|
234
258
|
it "should not create a \#{association_name}_attributes instance writer" do
|
235
259
|
p = @model.new
|
236
260
|
p.respond_to?("#{@association}_attributes=").should be_false
|
@@ -277,9 +301,17 @@ describe "DataMapper::Model.accepts_nested_attributes_for" do
|
|
277
301
|
@model.reject_new_nested_attributes_proc_for(@association).should be_kind_of(Proc)
|
278
302
|
end
|
279
303
|
|
304
|
+
it "should create a \#{association_name}_attributes instance reader" do
|
305
|
+
p = @model.new
|
306
|
+
p.respond_to?("#{@association}_attributes").should be_false
|
307
|
+
@model.accepts_nested_attributes_for @association, :allow_destroy => true
|
308
|
+
p = @model.new
|
309
|
+
p.respond_to?("#{@association}_attributes=").should be_true
|
310
|
+
end
|
311
|
+
|
280
312
|
it "should create a \#{association_name}_attributes instance writer" do
|
281
313
|
p = @model.new
|
282
|
-
p.respond_to?("#{@association}_attributes
|
314
|
+
p.respond_to?("#{@association}_attributes").should be_false
|
283
315
|
@model.accepts_nested_attributes_for @association, :allow_destroy => true
|
284
316
|
p = @model.new
|
285
317
|
p.respond_to?("#{@association}_attributes=").should be_true
|
@@ -451,4 +483,4 @@ describe "DataMapper::Model.accepts_nested_attributes_for" do
|
|
451
483
|
|
452
484
|
end
|
453
485
|
|
454
|
-
end
|
486
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: snusnu-dm-accepts_nested_attributes
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- "Martin Gamsj\xC3\xA4ger"
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-04-
|
12
|
+
date: 2009-04-15 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -55,13 +55,17 @@ files:
|
|
55
55
|
- lib/dm-accepts_nested_attributes/nested_attributes.rb
|
56
56
|
- lib/dm-accepts_nested_attributes/version.rb
|
57
57
|
- spec/fixtures/person.rb
|
58
|
+
- spec/fixtures/photo.rb
|
58
59
|
- spec/fixtures/profile.rb
|
59
60
|
- spec/fixtures/project.rb
|
60
61
|
- spec/fixtures/project_membership.rb
|
62
|
+
- spec/fixtures/tag.rb
|
63
|
+
- spec/fixtures/tagging.rb
|
61
64
|
- spec/fixtures/task.rb
|
62
65
|
- spec/integration/belongs_to_spec.rb
|
63
66
|
- spec/integration/has_1_spec.rb
|
64
67
|
- spec/integration/has_n_spec.rb
|
68
|
+
- spec/integration/has_n_through_renamed_spec.rb
|
65
69
|
- spec/integration/has_n_through_spec.rb
|
66
70
|
- spec/shared/rspec_tmbundle_support.rb
|
67
71
|
- spec/spec.opts
|