snusnu-dm-accepts_nested_attributes 0.0.2 → 0.0.3
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 +2 -5
- data/lib/dm-accepts_nested_attributes.rb +3 -2
- data/lib/dm-accepts_nested_attributes/{associations.rb → association_proxies.rb} +0 -0
- data/lib/dm-accepts_nested_attributes/association_validation.rb +91 -0
- data/lib/dm-accepts_nested_attributes/nested_attributes.rb +171 -220
- data/lib/dm-accepts_nested_attributes/version.rb +1 -1
- data/spec/fixtures/person.rb +1 -1
- data/spec/fixtures/profile.rb +1 -1
- data/spec/fixtures/project.rb +1 -1
- data/spec/fixtures/task.rb +1 -1
- data/spec/integration/belongs_to_spec.rb +33 -35
- data/spec/integration/has_1_spec.rb +38 -40
- data/spec/integration/has_n_spec.rb +41 -6
- data/spec/integration/has_n_through_spec.rb +35 -6
- data/spec/spec_helper.rb +32 -6
- data/spec/unit/accepts_nested_attributes_for_spec.rb +19 -14
- data/spec/unit/resource_spec.rb +1 -1
- data/tasks/gemspec.rb +0 -3
- metadata +4 -7
- data/spec/fixtures/photo.rb +0 -9
- data/spec/fixtures/tag.rb +0 -12
- data/spec/fixtures/tagging.rb +0 -10
- data/spec/integration/has_n_through_renamed_spec.rb +0 -214
data/Manifest.txt
CHANGED
@@ -6,21 +6,18 @@ README.textile
|
|
6
6
|
Rakefile
|
7
7
|
TODO
|
8
8
|
lib/dm-accepts_nested_attributes.rb
|
9
|
-
lib/dm-accepts_nested_attributes/
|
9
|
+
lib/dm-accepts_nested_attributes/association_proxies.rb
|
10
|
+
lib/dm-accepts_nested_attributes/association_validation.rb
|
10
11
|
lib/dm-accepts_nested_attributes/nested_attributes.rb
|
11
12
|
lib/dm-accepts_nested_attributes/version.rb
|
12
13
|
spec/fixtures/person.rb
|
13
|
-
spec/fixtures/photo.rb
|
14
14
|
spec/fixtures/profile.rb
|
15
15
|
spec/fixtures/project.rb
|
16
16
|
spec/fixtures/project_membership.rb
|
17
|
-
spec/fixtures/tag.rb
|
18
|
-
spec/fixtures/tagging.rb
|
19
17
|
spec/fixtures/task.rb
|
20
18
|
spec/integration/belongs_to_spec.rb
|
21
19
|
spec/integration/has_1_spec.rb
|
22
20
|
spec/integration/has_n_spec.rb
|
23
|
-
spec/integration/has_n_through_renamed_spec.rb
|
24
21
|
spec/integration/has_n_through_spec.rb
|
25
22
|
spec/shared/rspec_tmbundle_support.rb
|
26
23
|
spec/spec.opts
|
@@ -12,7 +12,8 @@ require 'dm-validations'
|
|
12
12
|
# Require plugin-files
|
13
13
|
require Pathname(__FILE__).dirname.expand_path / 'dm-accepts_nested_attributes' / 'nested_attributes'
|
14
14
|
# monkeypatches for dm-core/associations/(many_to_one.rb and one_to_many.rb)
|
15
|
-
require Pathname(__FILE__).dirname.expand_path / 'dm-accepts_nested_attributes' / '
|
15
|
+
require Pathname(__FILE__).dirname.expand_path / 'dm-accepts_nested_attributes' / 'association_proxies'
|
16
16
|
|
17
17
|
# Include the plugin in Model
|
18
|
-
DataMapper::
|
18
|
+
DataMapper::Model.append_extensions DataMapper::NestedAttributes::ClassMethods
|
19
|
+
DataMapper::Resource.append_inclusions DataMapper::NestedAttributes::CommonInstanceMethods
|
File without changes
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module NestedAttributes
|
3
|
+
|
4
|
+
module AssociationValidation
|
5
|
+
|
6
|
+
# NOTE:
|
7
|
+
# overwriting Resource#save like this breaks the before(:save) hook stack
|
8
|
+
# this hopefully is no problem, since the current implementation doesn't rely on
|
9
|
+
# a before(:save) hook, but rather overwrites this hook with a no-op, and adds
|
10
|
+
# the desired behavior via overwriting Resource#save directly. I'd really appreciate
|
11
|
+
# any ideas for doing this differently, though. Anyways, I'm not really sure if this
|
12
|
+
# is the right approach. I don't even know if it works with custom validations,
|
13
|
+
# or maybe breaks other things. It's also really not well specced at all atm.
|
14
|
+
# Use at your own risk :-)
|
15
|
+
|
16
|
+
def save(context = :default)
|
17
|
+
|
18
|
+
# -----------------------------------------------------------------
|
19
|
+
# ORIGINAL CODE from Resource#save
|
20
|
+
# -----------------------------------------------------------------
|
21
|
+
#
|
22
|
+
# associations_saved = false
|
23
|
+
# child_associations.each { |a| associations_saved |= a.save }
|
24
|
+
#
|
25
|
+
# saved = new_record? ? create : update
|
26
|
+
#
|
27
|
+
# if saved
|
28
|
+
# original_values.clear
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# parent_associations.each { |a| associations_saved |= a.save }
|
32
|
+
#
|
33
|
+
# # We should return true if the model (or any of its associations)
|
34
|
+
# # were saved.
|
35
|
+
# (saved | associations_saved) == true
|
36
|
+
#
|
37
|
+
# -----------------------------------------------------------------
|
38
|
+
|
39
|
+
return super if context.nil? # preserve save! behavior
|
40
|
+
|
41
|
+
associations_saved = false
|
42
|
+
|
43
|
+
child_associations.each do |a|
|
44
|
+
|
45
|
+
if a.respond_to?(:valid?)
|
46
|
+
a.errors.each { |e| self.errors.add(:general, e) } unless a.valid?(context)
|
47
|
+
else
|
48
|
+
self.errors.add(:general, "child association is missing")
|
49
|
+
end
|
50
|
+
|
51
|
+
associations_saved |= a.save
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
saved = self.valid? && (new_record? ? create : update)
|
56
|
+
|
57
|
+
if saved
|
58
|
+
original_values.clear
|
59
|
+
end
|
60
|
+
|
61
|
+
parent_associations.each do |a|
|
62
|
+
|
63
|
+
if a.respond_to?(:each)
|
64
|
+
a.each do |r|
|
65
|
+
r.errors.each { |e| self.errors.add(:general, e) } unless r.valid?(context)
|
66
|
+
end
|
67
|
+
else
|
68
|
+
a.errors.each { |e| self.errors.add(:general, e) } unless a.valid?(context)
|
69
|
+
end
|
70
|
+
|
71
|
+
associations_saved |= a.save
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
(saved | associations_saved) == true
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
# everything works the same if this method isn't overwritten with a no-op
|
80
|
+
# however, i suspect that this is the case because the registered before(:save) hook
|
81
|
+
# somehow gets lost when overwriting Resource#save here in this module.
|
82
|
+
# I'll leave it in for now, to make the purpose clear
|
83
|
+
|
84
|
+
def check_validations(context = :default)
|
85
|
+
true # no-op, validations are checked inside #save
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
@@ -1,14 +1,13 @@
|
|
1
1
|
module DataMapper
|
2
2
|
module NestedAttributes
|
3
3
|
|
4
|
-
def self.included(base)
|
5
|
-
base.extend(ClassMethods)
|
6
|
-
base.class_inheritable_accessor :autosave_associations
|
7
|
-
base.autosave_associations = {}
|
8
|
-
end
|
9
|
-
|
10
4
|
module ClassMethods
|
11
5
|
|
6
|
+
def self.extended(base)
|
7
|
+
base.class_inheritable_accessor :autosave_associations
|
8
|
+
base.autosave_associations = {}
|
9
|
+
end
|
10
|
+
|
12
11
|
# Defines an attributes reader and writer for the specified association(s).
|
13
12
|
# If you are using <tt>attr_protected</tt> or <tt>attr_accessible</tt>,
|
14
13
|
# then you will need to add the attribute writer to the allowed list.
|
@@ -57,17 +56,37 @@ module DataMapper
|
|
57
56
|
|
58
57
|
association_for_name(association_name)
|
59
58
|
|
59
|
+
|
60
|
+
# should be safe to go on
|
61
|
+
|
62
|
+
include InstanceMethods
|
63
|
+
|
64
|
+
if ::DataMapper.const_defined?('Validate')
|
65
|
+
|
66
|
+
require Pathname(__FILE__).dirname.expand_path + 'association_validation'
|
67
|
+
|
68
|
+
include AssociationValidation
|
69
|
+
|
70
|
+
end
|
71
|
+
|
60
72
|
autosave_associations[association_name] = options
|
61
73
|
|
62
74
|
type = nr_of_possible_child_instances(association_name) > 1 ? :collection : :one_to_one
|
63
75
|
|
64
76
|
class_eval %{
|
65
77
|
|
78
|
+
def save(context = :default)
|
79
|
+
saved = false # preserve Resource#save api contract
|
80
|
+
transaction { |t| t.rollback unless saved = super }
|
81
|
+
saved
|
82
|
+
end
|
83
|
+
|
66
84
|
def #{association_name}_attributes
|
67
85
|
@#{association_name}_attributes
|
68
86
|
end
|
69
87
|
|
70
88
|
def #{association_name}_attributes=(attributes)
|
89
|
+
attributes = sanitize_nested_attributes(attributes)
|
71
90
|
@#{association_name}_attributes = attributes
|
72
91
|
assign_nested_attributes_for_#{type}_association(:#{association_name}, attributes, #{options[:allow_destroy]})
|
73
92
|
end
|
@@ -151,249 +170,181 @@ module DataMapper
|
|
151
170
|
end
|
152
171
|
|
153
172
|
|
154
|
-
|
155
|
-
|
173
|
+
module InstanceMethods
|
156
174
|
|
157
|
-
|
158
|
-
|
159
|
-
#
|
160
|
-
#
|
161
|
-
#
|
162
|
-
#
|
163
|
-
#
|
164
|
-
#
|
165
|
-
#
|
166
|
-
#
|
167
|
-
|
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
|
175
|
+
# This method can be used to remove ambiguities from the passed attributes.
|
176
|
+
# Consider a situation with a belongs_to association where both a valid value
|
177
|
+
# for the foreign_key attribute *and* nested_attributes for a new record are
|
178
|
+
# present (i.e. item_type_id and item_type_attributes are present).
|
179
|
+
# Also see http://is.gd/sz2d on the rails-core ml for a discussion on this.
|
180
|
+
# The basic idea is, that there should be a well defined behavior for what
|
181
|
+
# exactly happens when such a situation occurs. I'm currently in favor for
|
182
|
+
# using the foreign_key if it is present, but this probably needs more thinking.
|
183
|
+
# For now, this method basically is a no-op, but at least it provides a hook where
|
184
|
+
# everyone can perform it's own sanitization (just overwrite this method)
|
185
|
+
def sanitize_nested_attributes(attrs)
|
186
|
+
attrs
|
240
187
|
end
|
241
|
-
|
242
|
-
end
|
243
188
|
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
# Reloads the attributes of the object as usual and removes a mark for destruction.
|
250
|
-
def reload
|
251
|
-
@marked_for_destruction = false
|
252
|
-
super
|
253
|
-
end
|
254
|
-
|
255
|
-
def marked_for_destruction?
|
256
|
-
@marked_for_destruction
|
257
|
-
end
|
258
|
-
|
259
|
-
def mark_for_destruction
|
260
|
-
@marked_for_destruction = true
|
261
|
-
end
|
189
|
+
# returns nil if no resource has been associated yet
|
190
|
+
def associated_instance_get(association_name, repository = :default)
|
191
|
+
send(self.class.association_for_name(association_name, repository).name)
|
192
|
+
end
|
262
193
|
|
263
194
|
|
264
|
-
|
195
|
+
private
|
265
196
|
|
266
|
-
|
267
|
-
|
268
|
-
|
197
|
+
# Attribute hash keys that should not be assigned as normal attributes.
|
198
|
+
# These hash keys are nested attributes implementation details.
|
199
|
+
UNASSIGNABLE_KEYS = [ :id, :_delete ]
|
269
200
|
|
270
201
|
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
202
|
+
# Assigns the given attributes to the association.
|
203
|
+
#
|
204
|
+
# If the given attributes include an <tt>:id</tt> that matches the existing
|
205
|
+
# record’s id, then the existing record will be modified. Otherwise a new
|
206
|
+
# record will be built.
|
207
|
+
#
|
208
|
+
# If the given attributes include a matching <tt>:id</tt> attribute _and_ a
|
209
|
+
# <tt>:_delete</tt> key set to a truthy value, then the existing record
|
210
|
+
# will be marked for destruction.
|
211
|
+
def assign_nested_attributes_for_one_to_one_association(association_name, attributes, allow_destroy)
|
212
|
+
if attributes[:id].blank?
|
213
|
+
unless reject_new_record?(association_name, attributes)
|
214
|
+
model = self.class.associated_model_for_name(association_name)
|
215
|
+
send("#{association_name}=", model.new(attributes.except(*UNASSIGNABLE_KEYS)))
|
216
|
+
end
|
217
|
+
else (existing_record = associated_instance_get(association_name)) && existing_record.id.to_s == attributes[:id].to_s
|
218
|
+
assign_to_or_mark_for_destruction(association_name, existing_record, attributes, allow_destroy)
|
285
219
|
end
|
286
|
-
else (existing_record = associated_instance_get(association_name)) && existing_record.id.to_s == attributes[:id].to_s
|
287
|
-
assign_to_or_mark_for_destruction(association_name, existing_record, attributes, allow_destroy)
|
288
220
|
end
|
289
|
-
end
|
290
221
|
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
222
|
+
# Assigns the given attributes to the collection association.
|
223
|
+
#
|
224
|
+
# Hashes with an <tt>:id</tt> value matching an existing associated record
|
225
|
+
# will update that record. Hashes without an <tt>:id</tt> value will build
|
226
|
+
# a new record for the association. Hashes with a matching <tt>:id</tt>
|
227
|
+
# value and a <tt>:_delete</tt> key set to a truthy value will mark the
|
228
|
+
# matched record for destruction.
|
229
|
+
#
|
230
|
+
# For example:
|
231
|
+
#
|
232
|
+
# assign_nested_attributes_for_collection_association(:people, {
|
233
|
+
# '1' => { :id => '1', :name => 'Peter' },
|
234
|
+
# '2' => { :name => 'John' },
|
235
|
+
# '3' => { :id => '2', :_delete => true }
|
236
|
+
# })
|
237
|
+
#
|
238
|
+
# Will update the name of the Person with ID 1, build a new associated
|
239
|
+
# person with the name `John', and mark the associatied Person with ID 2
|
240
|
+
# for destruction.
|
241
|
+
#
|
242
|
+
# Also accepts an Array of attribute hashes:
|
243
|
+
#
|
244
|
+
# assign_nested_attributes_for_collection_association(:people, [
|
245
|
+
# { :id => '1', :name => 'Peter' },
|
246
|
+
# { :name => 'John' },
|
247
|
+
# { :id => '2', :_delete => true }
|
248
|
+
# ])
|
249
|
+
def assign_nested_attributes_for_collection_association(association_name, attributes_collection, allow_destroy)
|
319
250
|
|
320
|
-
|
321
|
-
|
251
|
+
assert_kind_of 'association_name', association_name, Symbol
|
252
|
+
assert_kind_of 'attributes_collection', attributes_collection, Hash, Array
|
322
253
|
|
323
|
-
|
324
|
-
|
325
|
-
|
254
|
+
if attributes_collection.is_a? Hash
|
255
|
+
attributes_collection = attributes_collection.sort_by { |index, _| index.to_i }.map { |_, attributes| attributes }
|
256
|
+
end
|
326
257
|
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
258
|
+
attributes_collection.each do |attributes|
|
259
|
+
if attributes[:id].blank?
|
260
|
+
unless reject_new_record?(association_name, attributes)
|
261
|
+
case self.class.association_type(association_name)
|
262
|
+
when :one_to_many
|
263
|
+
build_new_has_n_association(association_name, attributes)
|
264
|
+
when :many_to_many
|
265
|
+
build_new_has_n_through_association(association_name, attributes)
|
266
|
+
end
|
335
267
|
end
|
268
|
+
elsif existing_record = send(association_name).detect { |record| record.id.to_s == attributes[:id].to_s }
|
269
|
+
assign_to_or_mark_for_destruction(association_name, existing_record, attributes, allow_destroy)
|
336
270
|
end
|
337
|
-
elsif existing_record = send(association_name).detect { |record| record.id.to_s == attributes[:id].to_s }
|
338
|
-
assign_to_or_mark_for_destruction(association_name, existing_record, attributes, allow_destroy)
|
339
271
|
end
|
340
|
-
end
|
341
272
|
|
342
|
-
|
273
|
+
end
|
343
274
|
|
344
|
-
|
345
|
-
|
346
|
-
|
275
|
+
def build_new_has_n_association(association_name, attributes)
|
276
|
+
send(association_name).build(attributes.except(*UNASSIGNABLE_KEYS))
|
277
|
+
end
|
347
278
|
|
348
|
-
|
349
|
-
|
350
|
-
|
279
|
+
def build_new_has_n_through_association(association_name, attributes)
|
280
|
+
# fetch the association to have the information ready
|
281
|
+
association = self.class.association_for_name(association_name)
|
351
282
|
|
352
|
-
|
283
|
+
# do what's done in dm-core/specs/integration/association_through_spec.rb
|
353
284
|
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
285
|
+
# explicitly build the join entry and assign it to the join association
|
286
|
+
join_entry = self.class.associated_model_for_name(association.name).new
|
287
|
+
self.send(association.name) << join_entry
|
288
|
+
self.save
|
289
|
+
# explicitly build the child entry and assign the join entry to its join association
|
290
|
+
child_entry = self.class.associated_model_for_name(association_name).new(attributes)
|
291
|
+
child_entry.send(association.name) << join_entry
|
292
|
+
child_entry.save
|
293
|
+
end
|
363
294
|
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
295
|
+
# Updates a record with the +attributes+ or marks it for destruction if
|
296
|
+
# +allow_destroy+ is +true+ and has_delete_flag? returns +true+.
|
297
|
+
def assign_to_or_mark_for_destruction(association_name, record, attributes, allow_destroy)
|
298
|
+
if has_delete_flag?(attributes) && allow_destroy
|
299
|
+
if self.class.association_type(association_name) == :many_to_many
|
300
|
+
# destroy the join record
|
301
|
+
record.send(self.class.association_for_name(association_name).name).destroy!
|
302
|
+
# destroy the child record
|
303
|
+
record.destroy
|
304
|
+
else
|
305
|
+
record.mark_for_destruction
|
306
|
+
end
|
373
307
|
else
|
374
|
-
record.
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
if self.class.association_type(association_name) == :many_to_many
|
379
|
-
record.save
|
308
|
+
record.attributes = attributes.except(*UNASSIGNABLE_KEYS)
|
309
|
+
if self.class.association_type(association_name) == :many_to_many
|
310
|
+
record.save
|
311
|
+
end
|
380
312
|
end
|
381
313
|
end
|
382
|
-
end
|
383
314
|
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
315
|
+
# Determines if a hash contains a truthy _delete key.
|
316
|
+
def has_delete_flag?(hash)
|
317
|
+
# TODO find out if this activerecord code needs to be ported
|
318
|
+
# ConnectionAdapters::Column.value_to_boolean hash['_delete']
|
319
|
+
hash[:_delete]
|
320
|
+
end
|
321
|
+
|
322
|
+
# Determines if a new record should be build by checking for
|
323
|
+
# has_delete_flag? or if a <tt>:reject_if</tt> proc exists for this
|
324
|
+
# association and evaluates to +true+.
|
325
|
+
def reject_new_record?(association_name, attributes)
|
326
|
+
guard = self.class.reject_new_nested_attributes_proc_for(association_name)
|
327
|
+
has_delete_flag?(attributes) || (guard.respond_to?(:call) && guard.call(attributes))
|
328
|
+
end
|
329
|
+
|
389
330
|
end
|
390
331
|
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
332
|
+
module CommonInstanceMethods
|
333
|
+
|
334
|
+
# Reloads the attributes of the object as usual and removes a mark for destruction.
|
335
|
+
def reload
|
336
|
+
@marked_for_destruction = false
|
337
|
+
super
|
338
|
+
end
|
339
|
+
|
340
|
+
def marked_for_destruction?
|
341
|
+
@marked_for_destruction
|
342
|
+
end
|
343
|
+
|
344
|
+
def mark_for_destruction
|
345
|
+
@marked_for_destruction = true
|
346
|
+
end
|
347
|
+
|
397
348
|
end
|
398
349
|
|
399
350
|
end
|