snusnu-dm-accepts_nested_attributes 0.0.1
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 +23 -0
- data/History.txt +1 -0
- data/LICENSE +20 -0
- data/Manifest.txt +29 -0
- data/README.textile +250 -0
- data/Rakefile +32 -0
- data/TODO +3 -0
- data/lib/dm-accepts_nested_attributes.rb +18 -0
- data/lib/dm-accepts_nested_attributes/associations.rb +55 -0
- data/lib/dm-accepts_nested_attributes/nested_attributes.rb +300 -0
- data/lib/dm-accepts_nested_attributes/version.rb +7 -0
- data/spec/fixtures/person.rb +8 -0
- data/spec/fixtures/profile.rb +7 -0
- data/spec/fixtures/project.rb +8 -0
- data/spec/fixtures/project_membership.rb +8 -0
- data/spec/fixtures/task.rb +7 -0
- data/spec/integration/belongs_to_spec.rb +204 -0
- data/spec/integration/has_1_spec.rb +193 -0
- data/spec/integration/has_n_spec.rb +181 -0
- data/spec/integration/has_n_through_spec.rb +200 -0
- data/spec/shared/rspec_tmbundle_support.rb +35 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +58 -0
- data/spec/unit/accepts_nested_attributes_for_spec.rb +454 -0
- data/spec/unit/resource_spec.rb +174 -0
- data/tasks/gemspec.rb +10 -0
- data/tasks/hoe.rb +46 -0
- data/tasks/install.rb +15 -0
- data/tasks/spec.rb +25 -0
- metadata +103 -0
@@ -0,0 +1,454 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
|
3
|
+
|
4
|
+
describe "DataMapper::Model.accepts_nested_attributes_for" do
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
|
8
|
+
# don't use the originally defined fixtures but provide new ones,
|
9
|
+
# this time without already calling accepts_nested_attributes_for on them.
|
10
|
+
# this helps speccing the exact behavior of this very method call
|
11
|
+
|
12
|
+
Object.send(:remove_const, 'Branch') if Object.const_defined?('Branch')
|
13
|
+
Object.send(:remove_const, 'Shop') if Object.const_defined?('Shop')
|
14
|
+
Object.send(:remove_const, 'Item') if Object.const_defined?('Item')
|
15
|
+
Object.send(:remove_const, 'Booking') if Object.const_defined?('Booking')
|
16
|
+
|
17
|
+
class Branch
|
18
|
+
include DataMapper::Resource
|
19
|
+
property :id, Serial
|
20
|
+
has 1, :shop
|
21
|
+
has n, :items
|
22
|
+
has n, :bookings, :through => :items
|
23
|
+
end
|
24
|
+
|
25
|
+
class Shop
|
26
|
+
include DataMapper::Resource
|
27
|
+
property :id, Serial
|
28
|
+
property :branch_id, Integer
|
29
|
+
belongs_to :branch
|
30
|
+
end
|
31
|
+
|
32
|
+
class Item
|
33
|
+
include DataMapper::Resource
|
34
|
+
property :id, Serial
|
35
|
+
property :branch_id, Integer
|
36
|
+
belongs_to :branch
|
37
|
+
has n, :bookings
|
38
|
+
end
|
39
|
+
|
40
|
+
class Booking
|
41
|
+
include DataMapper::Resource
|
42
|
+
property :id, Serial
|
43
|
+
property :item_id, Integer
|
44
|
+
belongs_to :item
|
45
|
+
end
|
46
|
+
|
47
|
+
DataMapper.auto_migrate!
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
describe "when called with" do
|
53
|
+
|
54
|
+
describe "no association_name" do
|
55
|
+
|
56
|
+
describe "and no options" do
|
57
|
+
|
58
|
+
it "should raise" do
|
59
|
+
lambda { Branch.accepts_nested_attributes_for }.should raise_error(ArgumentError)
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "and empty options" do
|
65
|
+
|
66
|
+
it "should raise" do
|
67
|
+
lambda { Branch.accepts_nested_attributes_for({}) }.should raise_error(ArgumentError)
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "and invalid options" do
|
73
|
+
|
74
|
+
it "should raise" do
|
75
|
+
lambda { Branch.accepts_nested_attributes_for({ :foo => :bar}) }.should raise_error(ArgumentError)
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "and valid options" do
|
81
|
+
|
82
|
+
it "should raise" do
|
83
|
+
lambda { Branch.accepts_nested_attributes_for({ :allow_destroy => true}) }.should raise_error(ArgumentError)
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "nil as association_name" do
|
91
|
+
|
92
|
+
describe "and no options" do
|
93
|
+
|
94
|
+
it "should raise" do
|
95
|
+
lambda { Branch.accepts_nested_attributes_for(nil) }.should raise_error(ArgumentError)
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
describe "and empty options" do
|
101
|
+
|
102
|
+
it "should raise" do
|
103
|
+
lambda { Branch.accepts_nested_attributes_for(nil, {}) }.should raise_error(ArgumentError)
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
describe "and invalid options" do
|
109
|
+
|
110
|
+
it "should raise" do
|
111
|
+
lambda { Branch.accepts_nested_attributes_for(nil, { :foo => :bar }) }.should raise_error(ArgumentError)
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
describe "and valid options" do
|
117
|
+
|
118
|
+
it "should raise" do
|
119
|
+
lambda { Branch.accepts_nested_attributes_for(nil, { :allow_destroy => true }) }.should raise_error(ArgumentError)
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
describe "an invalid association_name" do
|
127
|
+
|
128
|
+
describe "and no options" do
|
129
|
+
|
130
|
+
it "should raise" do
|
131
|
+
lambda { Branch.accepts_nested_attributes_for(:foo) }.should raise_error(ArgumentError)
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
describe "and empty options" do
|
137
|
+
|
138
|
+
it "should raise" do
|
139
|
+
lambda { Branch.accepts_nested_attributes_for(:foo, {}) }.should raise_error(ArgumentError)
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
|
144
|
+
describe "and invalid options" do
|
145
|
+
|
146
|
+
it "should raise" do
|
147
|
+
lambda { Branch.accepts_nested_attributes_for(:foo, { :foo => :bar }) }.should raise_error(ArgumentError)
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
151
|
+
|
152
|
+
describe "and valid options" do
|
153
|
+
|
154
|
+
it "should raise" do
|
155
|
+
lambda { Branch.accepts_nested_attributes_for(:foo, { :allow_destroy => true }) }.should raise_error(ArgumentError)
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
161
|
+
|
162
|
+
|
163
|
+
describe "a valid association_name", :shared => true do
|
164
|
+
|
165
|
+
|
166
|
+
describe "and no options" do
|
167
|
+
|
168
|
+
it "should not raise" do
|
169
|
+
lambda { @model.accepts_nested_attributes_for @association }.should_not raise_error
|
170
|
+
end
|
171
|
+
|
172
|
+
it "should store the accessible association in .autosave_associations" do
|
173
|
+
@model.autosave_associations[@association].should be_nil
|
174
|
+
@model.accepts_nested_attributes_for @association
|
175
|
+
@model.autosave_associations[@association].should_not be_nil
|
176
|
+
end
|
177
|
+
|
178
|
+
it "should store the default options under the association_name in .autosave_associations" do
|
179
|
+
@model.autosave_associations[@association].should be_nil
|
180
|
+
@model.accepts_nested_attributes_for @association
|
181
|
+
@model.autosave_associations[@association].should == { :allow_destroy => false }
|
182
|
+
end
|
183
|
+
|
184
|
+
it "should create a \#{association_name}_attributes instance writer" 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
|
+
|
192
|
+
end
|
193
|
+
|
194
|
+
describe "and empty options" do
|
195
|
+
|
196
|
+
it "should not raise" do
|
197
|
+
lambda { @model.accepts_nested_attributes_for @association, {} }.should_not raise_error
|
198
|
+
end
|
199
|
+
|
200
|
+
it "should store the accessible association in .autosave_associations" do
|
201
|
+
@model.autosave_associations[@association].should be_nil
|
202
|
+
@model.accepts_nested_attributes_for @association, {}
|
203
|
+
@model.autosave_associations[@association].should_not be_nil
|
204
|
+
end
|
205
|
+
|
206
|
+
it "should store the default options under the association_name in .autosave_associations" do
|
207
|
+
@model.autosave_associations[@association].should be_nil
|
208
|
+
@model.accepts_nested_attributes_for @association, {}
|
209
|
+
@model.autosave_associations[@association].should == { :allow_destroy => false }
|
210
|
+
end
|
211
|
+
|
212
|
+
it "should create a \#{association_name}_attributes instance writer" do
|
213
|
+
p = @model.new
|
214
|
+
p.respond_to?("#{@association}_attributes=").should be_false
|
215
|
+
@model.accepts_nested_attributes_for @association, {}
|
216
|
+
p = @model.new
|
217
|
+
p.respond_to?("#{@association}_attributes=").should be_true
|
218
|
+
end
|
219
|
+
|
220
|
+
end
|
221
|
+
|
222
|
+
describe "and invalid options" do
|
223
|
+
|
224
|
+
it "should raise" do
|
225
|
+
lambda { @model.accepts_nested_attributes_for @association, { :foo => :bar } }.should raise_error
|
226
|
+
end
|
227
|
+
|
228
|
+
it "should not store the accessible association in .autosave_associations" do
|
229
|
+
@model.autosave_associations[@association].should be_nil
|
230
|
+
lambda { @model.accepts_nested_attributes_for @association, { :foo => :bar } }.should raise_error
|
231
|
+
@model.autosave_associations[@association].should be_nil
|
232
|
+
end
|
233
|
+
|
234
|
+
it "should not create a \#{association_name}_attributes instance writer" do
|
235
|
+
p = @model.new
|
236
|
+
p.respond_to?("#{@association}_attributes=").should be_false
|
237
|
+
lambda { @model.accepts_nested_attributes_for @association, { :foo => :bar } }.should raise_error
|
238
|
+
p = @model.new
|
239
|
+
p.respond_to?("#{@association}_attributes=").should be_false
|
240
|
+
end
|
241
|
+
|
242
|
+
end
|
243
|
+
|
244
|
+
describe "and valid options" do
|
245
|
+
|
246
|
+
it "should not raise" do
|
247
|
+
lambda { @model.accepts_nested_attributes_for @association, :allow_destroy => true }.should_not raise_error
|
248
|
+
end
|
249
|
+
|
250
|
+
it "should store the accessible association in .autosave_associations" do
|
251
|
+
@model.autosave_associations[@association].should be_nil
|
252
|
+
@model.accepts_nested_attributes_for @association, :allow_destroy => true
|
253
|
+
@model.autosave_associations[@association].should_not be_nil
|
254
|
+
end
|
255
|
+
|
256
|
+
it "should accept :allow_destroy as the only option (and thus overwrite the default option)" do
|
257
|
+
@model.autosave_associations[@association].should be_nil
|
258
|
+
@model.accepts_nested_attributes_for @association, :allow_destroy => true
|
259
|
+
@model.autosave_associations[@association].should == { :allow_destroy => true }
|
260
|
+
end
|
261
|
+
|
262
|
+
it "should accept :reject_if as the only option (and add :allow_destroy => false)" do
|
263
|
+
@model.autosave_associations[@association].should be_nil
|
264
|
+
@model.accepts_nested_attributes_for @association, :reject_if => lambda { |attributes| nil }
|
265
|
+
@model.autosave_associations[@association].should_not be_nil
|
266
|
+
@model.autosave_associations[@association][:allow_destroy].should be_false
|
267
|
+
@model.autosave_associations[@association][:reject_if].should be_kind_of(Proc)
|
268
|
+
@model.reject_new_nested_attributes_proc_for(@association).should be_kind_of(Proc)
|
269
|
+
end
|
270
|
+
|
271
|
+
it "should accept both :allow_destroy and :reject_if as options" do
|
272
|
+
@model.autosave_associations[@association].should be_nil
|
273
|
+
@model.accepts_nested_attributes_for @association, :allow_destroy => true, :reject_if => lambda { |attributes| nil }
|
274
|
+
@model.autosave_associations[@association].should_not be_nil
|
275
|
+
@model.autosave_associations[@association][:allow_destroy].should be_true
|
276
|
+
@model.autosave_associations[@association][:reject_if].should be_kind_of(Proc)
|
277
|
+
@model.reject_new_nested_attributes_proc_for(@association).should be_kind_of(Proc)
|
278
|
+
end
|
279
|
+
|
280
|
+
it "should create a \#{association_name}_attributes instance writer" do
|
281
|
+
p = @model.new
|
282
|
+
p.respond_to?("#{@association}_attributes=").should be_false
|
283
|
+
@model.accepts_nested_attributes_for @association, :allow_destroy => true
|
284
|
+
p = @model.new
|
285
|
+
p.respond_to?("#{@association}_attributes=").should be_true
|
286
|
+
end
|
287
|
+
|
288
|
+
end
|
289
|
+
|
290
|
+
end
|
291
|
+
|
292
|
+
describe "a valid association_name pointing to a single resource", :shared => true do
|
293
|
+
|
294
|
+
describe "and no options" do
|
295
|
+
|
296
|
+
it "should create a get_\#{association_name} instance reader" do
|
297
|
+
p = @model.new
|
298
|
+
p.respond_to?("get_#{@association}").should be_false
|
299
|
+
@model.accepts_nested_attributes_for @association
|
300
|
+
p = @model.new
|
301
|
+
p.respond_to?("get_#{@association}").should be_true
|
302
|
+
p.send("get_#{@association}").should_not be_nil
|
303
|
+
end
|
304
|
+
|
305
|
+
end
|
306
|
+
|
307
|
+
describe "and empty options" do
|
308
|
+
|
309
|
+
it "should create a get_\#{association_name} instance reader" do
|
310
|
+
p = @model.new
|
311
|
+
p.respond_to?("get_#{@association}").should be_false
|
312
|
+
@model.accepts_nested_attributes_for @association, {}
|
313
|
+
p = @model.new
|
314
|
+
p.respond_to?("get_#{@association}").should be_true
|
315
|
+
p.send("get_#{@association}").should_not be_nil
|
316
|
+
end
|
317
|
+
|
318
|
+
end
|
319
|
+
|
320
|
+
describe "and invalid options" do
|
321
|
+
|
322
|
+
it "should not create a get_\#{association_name} instance reader" do
|
323
|
+
p = @model.new
|
324
|
+
p.respond_to?("get_#{@association}").should be_false
|
325
|
+
lambda { @model.accepts_nested_attributes_for @association, { :foo => :bar } }.should raise_error
|
326
|
+
p = @model.new
|
327
|
+
p.respond_to?("get_#{@association}").should be_false
|
328
|
+
end
|
329
|
+
|
330
|
+
end
|
331
|
+
|
332
|
+
describe "and valid options" do
|
333
|
+
|
334
|
+
it "should create a get_\#{association_name} instance reader" do
|
335
|
+
p = @model.new
|
336
|
+
p.respond_to?("get_#{@association}").should be_false
|
337
|
+
@model.accepts_nested_attributes_for @association, :allow_destroy => true
|
338
|
+
p = @model.new
|
339
|
+
p.respond_to?("get_#{@association}").should be_true
|
340
|
+
p.send("get_#{@association}").should_not be_nil
|
341
|
+
end
|
342
|
+
|
343
|
+
end
|
344
|
+
|
345
|
+
end
|
346
|
+
|
347
|
+
describe "a valid association_name pointing to multiple resources", :shared => true do
|
348
|
+
|
349
|
+
describe "and no options" do
|
350
|
+
|
351
|
+
it "should not create a get_\#{association_name} instance reader" do
|
352
|
+
p = @model.new
|
353
|
+
p.respond_to?("get_#{@association}").should be_false
|
354
|
+
lambda { @model.accepts_nested_attributes_for @association }.should_not raise_error
|
355
|
+
p = @model.new
|
356
|
+
p.respond_to?("get_#{@association}").should be_false
|
357
|
+
end
|
358
|
+
|
359
|
+
end
|
360
|
+
|
361
|
+
describe "and empty options" do
|
362
|
+
|
363
|
+
it "should not create a get_\#{association_name} instance reader" do
|
364
|
+
p = @model.new
|
365
|
+
p.respond_to?("get_#{@association}").should be_false
|
366
|
+
lambda { @model.accepts_nested_attributes_for @association, {} }.should_not raise_error
|
367
|
+
p = @model.new
|
368
|
+
p.respond_to?("get_#{@association}").should be_false
|
369
|
+
end
|
370
|
+
|
371
|
+
end
|
372
|
+
|
373
|
+
describe "and invalid options" do
|
374
|
+
|
375
|
+
it "should not create a get_\#{association_name} instance reader" do
|
376
|
+
p = @model.new
|
377
|
+
p.respond_to?("get_#{@association}").should be_false
|
378
|
+
lambda { @model.accepts_nested_attributes_for @association, { :foo => :bar } }.should raise_error
|
379
|
+
p = @model.new
|
380
|
+
p.respond_to?("get_#{@association}").should be_false
|
381
|
+
end
|
382
|
+
|
383
|
+
end
|
384
|
+
|
385
|
+
describe "and valid options" do
|
386
|
+
|
387
|
+
it "should not create a get_\#{association_name} instance reader" do
|
388
|
+
p = @model.new
|
389
|
+
p.respond_to?("get_#{@association}").should be_false
|
390
|
+
lambda { @model.accepts_nested_attributes_for @association, { :allow_destroy => :true } }.should_not raise_error
|
391
|
+
p = @model.new
|
392
|
+
p.respond_to?("get_#{@association}").should be_false
|
393
|
+
end
|
394
|
+
|
395
|
+
end
|
396
|
+
|
397
|
+
end
|
398
|
+
|
399
|
+
# ----------------------------------------------------------------------------------------
|
400
|
+
# ----------------------------------------------------------------------------------------
|
401
|
+
# ----------------------------------------------------------------------------------------
|
402
|
+
|
403
|
+
|
404
|
+
describe "a valid belongs_to association_name" do
|
405
|
+
|
406
|
+
before(:each) do
|
407
|
+
@model = Item
|
408
|
+
@association = :branch
|
409
|
+
end
|
410
|
+
|
411
|
+
it_should_behave_like "a valid association_name"
|
412
|
+
it_should_behave_like "a valid association_name pointing to a single resource"
|
413
|
+
|
414
|
+
end
|
415
|
+
|
416
|
+
describe "a valid has(1) association_name" do
|
417
|
+
|
418
|
+
before(:each) do
|
419
|
+
@model = Branch
|
420
|
+
@association = :shop
|
421
|
+
end
|
422
|
+
|
423
|
+
it_should_behave_like "a valid association_name"
|
424
|
+
it_should_behave_like "a valid association_name pointing to a single resource"
|
425
|
+
|
426
|
+
end
|
427
|
+
|
428
|
+
describe "a valid has(n) association_name" do
|
429
|
+
|
430
|
+
before(:each) do
|
431
|
+
@model = Branch
|
432
|
+
@association = :items
|
433
|
+
end
|
434
|
+
|
435
|
+
it_should_behave_like "a valid association_name"
|
436
|
+
it_should_behave_like "a valid association_name pointing to multiple resources"
|
437
|
+
|
438
|
+
end
|
439
|
+
|
440
|
+
describe "a valid has(n, :through) association_name" do
|
441
|
+
|
442
|
+
before(:each) do
|
443
|
+
@model = Branch
|
444
|
+
@association = :bookings
|
445
|
+
end
|
446
|
+
|
447
|
+
it_should_behave_like "a valid association_name"
|
448
|
+
it_should_behave_like "a valid association_name pointing to multiple resources"
|
449
|
+
|
450
|
+
end
|
451
|
+
|
452
|
+
end
|
453
|
+
|
454
|
+
end
|