object_attorney 0.0.2 → 0.0.9
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 +1 -0
- data/lib/object_attorney.rb +44 -228
- data/lib/object_attorney/nested_objects.rb +138 -0
- data/lib/object_attorney/nested_uniqueness_validator.rb +33 -0
- data/lib/object_attorney/orm.rb +60 -0
- data/lib/object_attorney/orm_handlers/smooth_operator.rb +51 -0
- data/lib/object_attorney/version.rb +1 -1
- metadata +6 -2
data/.gitignore
CHANGED
data/lib/object_attorney.rb
CHANGED
@@ -1,12 +1,9 @@
|
|
1
1
|
require "object_attorney/version"
|
2
|
+
require "object_attorney/nested_objects"
|
3
|
+
require "object_attorney/orm"
|
2
4
|
|
3
5
|
module ObjectAttorney
|
4
6
|
|
5
|
-
################# EXAMPLES ##################
|
6
|
-
# represents :user
|
7
|
-
# accepts_nested_objects :addess, :posts
|
8
|
-
#############################################
|
9
|
-
|
10
7
|
def initialize(attributes = {}, object = nil, options = {})
|
11
8
|
if !attributes.kind_of?(Hash) && object.blank?
|
12
9
|
object = attributes
|
@@ -20,50 +17,12 @@ module ObjectAttorney
|
|
20
17
|
object = nil
|
21
18
|
end
|
22
19
|
|
23
|
-
@
|
24
|
-
@trusted_data = options[:trusted_data] if options.present? && options.kind_of?(Hash)
|
20
|
+
@represented_object = object if object.present?
|
25
21
|
|
26
22
|
assign_attributes attributes
|
27
23
|
mark_for_destruction_if_necessary(self, attributes)
|
28
24
|
end
|
29
25
|
|
30
|
-
def nested_objects
|
31
|
-
unless nested_objects_updated
|
32
|
-
@nested_objects = self.class.instance_variable_get("@nested_objects").map { |nested_object_sym| self.send(nested_object_sym) }.flatten
|
33
|
-
nested_objects_updated = true
|
34
|
-
end
|
35
|
-
|
36
|
-
@nested_objects
|
37
|
-
end
|
38
|
-
|
39
|
-
def new_record?
|
40
|
-
@object.try_or_return(:new_record?, true)
|
41
|
-
end
|
42
|
-
|
43
|
-
def persisted?
|
44
|
-
@object.try_or_return(:persisted?, false)
|
45
|
-
end
|
46
|
-
|
47
|
-
def mark_for_destruction
|
48
|
-
@marked_for_destruction = true
|
49
|
-
end
|
50
|
-
|
51
|
-
def marked_for_destruction?
|
52
|
-
@marked_for_destruction
|
53
|
-
end
|
54
|
-
|
55
|
-
def save
|
56
|
-
save_process
|
57
|
-
end
|
58
|
-
|
59
|
-
def save!
|
60
|
-
save_process true
|
61
|
-
end
|
62
|
-
|
63
|
-
def destroy
|
64
|
-
@object.try_or_return(:destroy, true) && nested_objects.all?(&:destroy)
|
65
|
-
end
|
66
|
-
|
67
26
|
def assign_attributes(attributes = {})
|
68
27
|
return if attributes.blank?
|
69
28
|
|
@@ -72,234 +31,91 @@ module ObjectAttorney
|
|
72
31
|
end
|
73
32
|
end
|
74
33
|
|
75
|
-
def mark_for_destruction_if_necessary(object, attributes)
|
76
|
-
return nil unless attributes.kind_of?(Hash)
|
77
|
-
|
78
|
-
_destroy = attributes["_destroy"] || attributes[:_destroy]
|
79
|
-
|
80
|
-
object.mark_for_destruction if ["true", "1"].include?(_destroy)
|
81
|
-
end
|
82
|
-
|
83
34
|
def read_attribute_for_serialization(attribute)
|
84
35
|
respond_to?(attribute) ? send(attribute) : nil
|
85
36
|
end
|
86
37
|
|
87
38
|
protected #--------------------------------------------------protected
|
88
39
|
|
89
|
-
def self.included(base)
|
90
|
-
base.extend(ClassMethods)
|
91
|
-
|
92
|
-
base.class_eval do
|
93
|
-
include ActiveModel::Validations
|
94
|
-
include ActiveModel::Conversion
|
95
|
-
|
96
|
-
attr_accessor :nested_objects_updated, :trusted_data
|
97
|
-
validate :validate_own_object, :validate_nested_objects
|
98
|
-
|
99
|
-
def valid?
|
100
|
-
override_valid? ? true : super
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
base.instance_variable_set("@nested_objects", [])
|
105
|
-
base.instance_variable_set("@white_list", [])
|
106
|
-
base.instance_variable_set("@black_list", [])
|
107
|
-
end
|
108
|
-
|
109
40
|
def allowed_attribute(attribute)
|
110
41
|
attribute = attribute.to_s
|
111
42
|
|
112
|
-
return false if !respond_to?("#{attribute}=") || black_list.include?(attribute)
|
113
|
-
return true if self.class.
|
114
|
-
|
115
|
-
self.class.instance_variable_get("@white_list").include?(attribute)
|
116
|
-
end
|
117
|
-
|
118
|
-
def black_list
|
119
|
-
[*self.class.instance_variable_get("@black_list"), "trusted_data", "nested_objects_updated", "_destroy"]
|
120
|
-
end
|
121
|
-
|
122
|
-
def save_process(raise_exception = false)
|
123
|
-
before_save
|
124
|
-
save_result = raise_exception ? _save! : _save
|
125
|
-
after_save if save_result
|
126
|
-
save_result
|
127
|
-
end
|
128
|
-
|
129
|
-
def before_save; end
|
130
|
-
def after_save; end
|
131
|
-
|
132
|
-
def _save
|
133
|
-
begin
|
134
|
-
ActiveRecord::Base.transaction { _save! }
|
135
|
-
rescue
|
136
|
-
valid?
|
137
|
-
false
|
138
|
-
end
|
139
|
-
end
|
43
|
+
return false if !respond_to?("#{attribute}=") || self.class.black_list.include?(attribute)
|
44
|
+
return true if self.class.white_list.empty?
|
140
45
|
|
141
|
-
|
142
|
-
result = (save_or_raise_rollback! ? save_or_destroy_nested_objects : false)
|
143
|
-
valid?
|
144
|
-
result
|
46
|
+
self.class.white_list.include?(attribute)
|
145
47
|
end
|
146
48
|
|
147
|
-
def
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
raise ActiveRecord::Rollback
|
152
|
-
end
|
49
|
+
def validate_represented_object
|
50
|
+
valid = override_validations? ? true : try_or_return(@represented_object, :valid?, true)
|
51
|
+
import_represented_object_errors unless valid
|
52
|
+
valid
|
153
53
|
end
|
154
54
|
|
155
|
-
def
|
156
|
-
@
|
55
|
+
def import_represented_object_errors
|
56
|
+
@represented_object.errors.each { |key, value| self.errors.add(key, value) }
|
157
57
|
end
|
158
58
|
|
159
|
-
|
160
|
-
result = nested_objects.map do |nested_object|
|
161
|
-
nested_object.marked_for_destruction? ? nested_object.destroy : nested_object.save!
|
162
|
-
end.all?
|
163
|
-
|
164
|
-
self.errors.add(:base, "Some errors where found while saving the nested objects.") unless result
|
59
|
+
private #################### PRIVATE METHODS DOWN BELOW ######################
|
165
60
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
def validate_own_object
|
170
|
-
valid = override_valid? ? true : @object.try_or_return(:valid?, true)
|
171
|
-
import_own_object_errors unless valid
|
172
|
-
valid
|
173
|
-
end
|
174
|
-
|
175
|
-
def validate_nested_objects
|
176
|
-
#nested_objects.all?(&:valid?) #will not validate all nested_objects
|
177
|
-
return true if nested_objects.reject(&:marked_for_destruction?).map(&:valid?).all?
|
178
|
-
import_nested_objects_errors
|
179
|
-
false
|
180
|
-
end
|
61
|
+
def self.included(base)
|
62
|
+
base.extend(ClassMethods)
|
181
63
|
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
64
|
+
base.class_eval do
|
65
|
+
include ActiveModel::Validations
|
66
|
+
include ActiveModel::Conversion
|
67
|
+
include ObjectAttorney::NestedObjects
|
68
|
+
include ObjectAttorney::ORM
|
187
69
|
|
188
|
-
|
189
|
-
@object.errors.each { |key, value| self.errors.add(key, value) }
|
190
|
-
end
|
70
|
+
validate :validate_represented_object
|
191
71
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
[*self.send(nested_object_sym)].each do |nested_object|
|
196
|
-
nested_object.errors.full_messages.each { |message| self.errors.add(nested_object_sym, message) }
|
72
|
+
def valid?
|
73
|
+
override_validations? ? true : super
|
197
74
|
end
|
198
|
-
|
199
75
|
end
|
200
76
|
end
|
201
77
|
|
202
|
-
|
203
|
-
# object ||= self
|
204
|
-
# object.errors.empty? ? hash : hash.merge({ errors: object.errors })
|
205
|
-
# end
|
206
|
-
|
207
|
-
private #------------------------------ private
|
208
|
-
|
209
|
-
def attributes_without_destroy(attributes)
|
210
|
-
return nil unless attributes.kind_of?(Hash)
|
211
|
-
|
212
|
-
_attributes = attributes.dup
|
213
|
-
_attributes.delete("_destroy")
|
214
|
-
_attributes.delete(:_destroy)
|
215
|
-
|
216
|
-
_attributes
|
217
|
-
end
|
218
|
-
|
219
|
-
def override_valid?
|
78
|
+
def override_validations?
|
220
79
|
marked_for_destruction?
|
221
80
|
end
|
222
81
|
|
223
|
-
def
|
224
|
-
|
225
|
-
|
226
|
-
if nested_instance_variable.nil?
|
227
|
-
nested_instance_variable = get_existing_and_new_nested_objects(nested_object_name)
|
228
|
-
self.instance_variable_set("@#{nested_object_name}", nested_instance_variable)
|
229
|
-
end
|
230
|
-
|
231
|
-
nested_instance_variable
|
82
|
+
def try_or_return(object, method, default_value)
|
83
|
+
returning_value = object.try(method)
|
84
|
+
returning_value.nil? ? default_value : returning_value
|
232
85
|
end
|
233
86
|
|
234
|
-
|
235
|
-
existing_and_new_nested_objects = []
|
236
|
-
|
237
|
-
update_existing_nested_objects(existing_and_new_nested_objects, nested_object_name)
|
238
|
-
build_new_nested_objects(existing_and_new_nested_objects, nested_object_name)
|
239
|
-
|
240
|
-
existing_and_new_nested_objects
|
241
|
-
end
|
242
|
-
|
243
|
-
def update_existing_nested_objects(existing_and_new_nested_objects, nested_object_name)
|
244
|
-
(send("existing_#{nested_object_name}") || []).each do |existing_nested_object|
|
245
|
-
attributes = get_attributes_for_existing(nested_object_name, existing_nested_object)
|
87
|
+
module ClassMethods
|
246
88
|
|
247
|
-
|
248
|
-
|
89
|
+
def represents(represented_object, represented_object_class = nil)
|
90
|
+
represented_object_class ||= represented_object.to_s.camelize
|
249
91
|
|
250
|
-
|
92
|
+
define_method(represented_object) do
|
93
|
+
@represented_object ||= represented_object_class.constantize.new
|
94
|
+
end
|
251
95
|
end
|
252
|
-
end
|
253
|
-
|
254
|
-
def build_new_nested_objects(existing_and_new_nested_objects, nested_object_name)
|
255
|
-
(send("#{nested_object_name}_attributes") || {}).values.each do |attributes|
|
256
|
-
next if attributes["id"].present?
|
257
96
|
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
existing_and_new_nested_objects << new_nested_object
|
97
|
+
def delegate_properties(*properties, options)
|
98
|
+
properties.each { |property| delegate_propertiy(property, options) }
|
262
99
|
end
|
263
|
-
end
|
264
100
|
|
265
|
-
|
266
|
-
|
267
|
-
attr_accessor :own_object_class
|
268
|
-
|
269
|
-
def represents(own_object)
|
270
|
-
define_method(own_object) do
|
271
|
-
own_object_class = self.class.instance_variable_get(:@own_object_class)
|
272
|
-
own_object_class ||= own_object.to_s.camelize
|
273
|
-
@object ||= own_object_class.constantize.new
|
274
|
-
end
|
101
|
+
def delegate_propertiy(property, options)
|
102
|
+
delegate property, "#{property}=", options
|
275
103
|
end
|
276
104
|
|
277
|
-
def
|
278
|
-
|
279
|
-
self.send(:attr_accessor, *nested_objects_list.map { |attribute| "#{attribute}_attributes".to_sym })
|
280
|
-
define_nested_objects_getter_methods nested_objects_list
|
105
|
+
def attr_white_list=(*white_list)
|
106
|
+
@white_list = white_list.map(&:to_s)
|
281
107
|
end
|
282
108
|
|
283
|
-
def
|
284
|
-
|
109
|
+
def white_list
|
110
|
+
@white_list ||= []
|
285
111
|
end
|
286
112
|
|
287
113
|
def attr_black_list(*black_list)
|
288
|
-
|
289
|
-
end
|
290
|
-
|
291
|
-
def reflect_on_association(association)
|
292
|
-
nil
|
114
|
+
@black_list = black_list.map(&:to_s)
|
293
115
|
end
|
294
116
|
|
295
|
-
|
296
|
-
|
297
|
-
def define_nested_objects_getter_methods(nested_objects_list)
|
298
|
-
nested_objects_list.each do |nested_object_name|
|
299
|
-
define_method(nested_object_name) do
|
300
|
-
nested_getter(nested_object_name)
|
301
|
-
end
|
302
|
-
end
|
117
|
+
def black_list
|
118
|
+
@black_list ||= ["_destroy"]
|
303
119
|
end
|
304
120
|
|
305
121
|
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
module ObjectAttorney
|
2
|
+
module NestedObjects
|
3
|
+
|
4
|
+
def nested_objects
|
5
|
+
self.class.instance_variable_get("@nested_objects").map { |nested_object_sym| self.send(nested_object_sym) }.flatten
|
6
|
+
end
|
7
|
+
|
8
|
+
def mark_for_destruction
|
9
|
+
@marked_for_destruction = true
|
10
|
+
end
|
11
|
+
|
12
|
+
def marked_for_destruction?
|
13
|
+
@marked_for_destruction
|
14
|
+
end
|
15
|
+
|
16
|
+
def mark_for_destruction_if_necessary(object, attributes)
|
17
|
+
return nil unless attributes.kind_of?(Hash)
|
18
|
+
|
19
|
+
_destroy = attributes["_destroy"] || attributes[:_destroy]
|
20
|
+
|
21
|
+
object.mark_for_destruction if ["true", "1"].include?(_destroy)
|
22
|
+
end
|
23
|
+
|
24
|
+
protected #################### PROTECTED METHODS DOWN BELOW ######################
|
25
|
+
|
26
|
+
def validate_nested_objects
|
27
|
+
#nested_objects.all?(&:valid?) #will not validate all nested_objects
|
28
|
+
return true if nested_objects.reject(&:marked_for_destruction?).map(&:valid?).all?
|
29
|
+
import_nested_objects_errors
|
30
|
+
false
|
31
|
+
end
|
32
|
+
|
33
|
+
def import_nested_objects_errors
|
34
|
+
self.class.instance_variable_get("@nested_objects").map do |nested_object_sym|
|
35
|
+
|
36
|
+
[*self.send(nested_object_sym)].each do |nested_object|
|
37
|
+
nested_object.errors.full_messages.each { |message| self.errors.add(nested_object_sym, message) }
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def get_attributes_for_existing(nested_object_name, existing_nested_object)
|
44
|
+
attributes = send("#{nested_object_name}_attributes")
|
45
|
+
return {} if attributes.blank?
|
46
|
+
attributes.present? ? (attributes.values.select { |x| x[:id].to_i == existing_nested_object.id }.first || {}) : {}
|
47
|
+
end
|
48
|
+
|
49
|
+
private #################### PRIVATE METHODS DOWN BELOW ######################
|
50
|
+
|
51
|
+
def self.included(base)
|
52
|
+
base.extend(ClassMethods)
|
53
|
+
|
54
|
+
base.class_eval do
|
55
|
+
validate :validate_nested_objects
|
56
|
+
end
|
57
|
+
|
58
|
+
base.instance_variable_set("@nested_objects", [])
|
59
|
+
end
|
60
|
+
|
61
|
+
def attributes_without_destroy(attributes)
|
62
|
+
return nil unless attributes.kind_of?(Hash)
|
63
|
+
|
64
|
+
_attributes = attributes.dup
|
65
|
+
_attributes.delete("_destroy")
|
66
|
+
_attributes.delete(:_destroy)
|
67
|
+
|
68
|
+
_attributes
|
69
|
+
end
|
70
|
+
|
71
|
+
def nested_getter(nested_object_name)
|
72
|
+
nested_instance_variable = self.instance_variable_get("@#{nested_object_name}")
|
73
|
+
|
74
|
+
if nested_instance_variable.nil?
|
75
|
+
nested_instance_variable = get_existing_and_new_nested_objects(nested_object_name)
|
76
|
+
self.instance_variable_set("@#{nested_object_name}", nested_instance_variable)
|
77
|
+
end
|
78
|
+
|
79
|
+
nested_instance_variable
|
80
|
+
end
|
81
|
+
|
82
|
+
def get_existing_and_new_nested_objects(nested_object_name)
|
83
|
+
existing_and_new_nested_objects = []
|
84
|
+
|
85
|
+
update_existing_nested_objects(existing_and_new_nested_objects, nested_object_name)
|
86
|
+
build_new_nested_objects(existing_and_new_nested_objects, nested_object_name)
|
87
|
+
|
88
|
+
existing_and_new_nested_objects
|
89
|
+
end
|
90
|
+
|
91
|
+
def update_existing_nested_objects(existing_and_new_nested_objects, nested_object_name)
|
92
|
+
(send("existing_#{nested_object_name}") || []).each do |existing_nested_object|
|
93
|
+
attributes = get_attributes_for_existing(nested_object_name, existing_nested_object)
|
94
|
+
|
95
|
+
mark_for_destruction_if_necessary(existing_nested_object, attributes)
|
96
|
+
existing_nested_object.assign_attributes(attributes_without_destroy(attributes))
|
97
|
+
|
98
|
+
existing_and_new_nested_objects << existing_nested_object
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def build_new_nested_objects(existing_and_new_nested_objects, nested_object_name)
|
103
|
+
(send("#{nested_object_name}_attributes") || {}).values.each do |attributes|
|
104
|
+
next if attributes["id"].present?
|
105
|
+
|
106
|
+
new_nested_object = send("build_#{nested_object_name.to_s.singularize}", attributes_without_destroy(attributes))
|
107
|
+
mark_for_destruction_if_necessary(new_nested_object, attributes)
|
108
|
+
|
109
|
+
existing_and_new_nested_objects << new_nested_object
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
module ClassMethods
|
114
|
+
|
115
|
+
def accepts_nested_objects(*nested_objects_list)
|
116
|
+
self.instance_variable_set("@nested_objects", nested_objects_list)
|
117
|
+
self.send(:attr_accessor, *nested_objects_list.map { |attribute| "#{attribute}_attributes".to_sym })
|
118
|
+
define_nested_objects_getter_methods nested_objects_list
|
119
|
+
end
|
120
|
+
|
121
|
+
def reflect_on_association(association)
|
122
|
+
nil
|
123
|
+
end
|
124
|
+
|
125
|
+
private #################### PRIVATE METHODS DOWN BELOW ######################
|
126
|
+
|
127
|
+
def define_nested_objects_getter_methods(nested_objects_list)
|
128
|
+
nested_objects_list.each do |nested_object_name|
|
129
|
+
define_method(nested_object_name) do
|
130
|
+
nested_getter(nested_object_name)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module ActiveModel
|
2
|
+
|
3
|
+
module Validations
|
4
|
+
|
5
|
+
class NestedUniquenessValidator < EachValidator
|
6
|
+
def validate_each(record, attr_name, value)
|
7
|
+
uniq_value, existing_objects, first_element = options[:uniq_value], [], nil
|
8
|
+
|
9
|
+
record.send(attr_name).each do |object|
|
10
|
+
next if object.marked_for_destruction?
|
11
|
+
|
12
|
+
first_element = object if first_element.nil?
|
13
|
+
|
14
|
+
if existing_objects.include?(object.send(uniq_value))
|
15
|
+
object.errors.add(uniq_value, :taken)
|
16
|
+
record.errors.add(attr_name, :taken)
|
17
|
+
else
|
18
|
+
existing_objects << object.send(uniq_value)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
module HelperMethods
|
26
|
+
|
27
|
+
def validates_nested_uniqueness(*attr_names)
|
28
|
+
validates_with NestedUniquenessValidator, _merge_attributes(attr_names)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require "object_attorney/orm_handlers/smooth_operator"
|
2
|
+
|
3
|
+
module ObjectAttorney
|
4
|
+
module ORM
|
5
|
+
|
6
|
+
def new_record?
|
7
|
+
try_or_return(@represented_object, :new_record?, true)
|
8
|
+
end
|
9
|
+
|
10
|
+
def persisted?
|
11
|
+
try_or_return(@represented_object, :persisted?, false)
|
12
|
+
end
|
13
|
+
|
14
|
+
def save
|
15
|
+
save!(:save)
|
16
|
+
end
|
17
|
+
|
18
|
+
def save!(save_method = :save!)
|
19
|
+
before_save
|
20
|
+
save_result = valid? ? save_after_validations(save_method) : false
|
21
|
+
after_save if valid? && save_result
|
22
|
+
save_result
|
23
|
+
end
|
24
|
+
|
25
|
+
def destroy
|
26
|
+
return true if @represented_object.blank?
|
27
|
+
evoke_method_on_object(@represented_object, :destroy)
|
28
|
+
end
|
29
|
+
|
30
|
+
def call_save_or_destroy(object, save_method)
|
31
|
+
if object == self
|
32
|
+
@represented_object.present? ? evoke_method_on_object(@represented_object, save_method) : true
|
33
|
+
else
|
34
|
+
save_method = :destroy if check_if_marked_for_destruction?(object)
|
35
|
+
evoke_method_on_object(object, save_method)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
protected #################### PROTECTED METHODS DOWN BELOW ######################
|
40
|
+
|
41
|
+
def before_save; end
|
42
|
+
def after_save; end
|
43
|
+
|
44
|
+
def save_after_validations(save_method)
|
45
|
+
return true if @represented_object.blank?
|
46
|
+
evoke_method_on_object(@represented_object, save_method)
|
47
|
+
end
|
48
|
+
|
49
|
+
private #################### PRIVATE METHODS DOWN BELOW ######################
|
50
|
+
|
51
|
+
def check_if_marked_for_destruction?(object)
|
52
|
+
object.respond_to?(:marked_for_destruction?) ? object.marked_for_destruction? : false
|
53
|
+
end
|
54
|
+
|
55
|
+
def evoke_method_on_object(object, method)
|
56
|
+
object.send(method)
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module ObjectAttorney
|
2
|
+
module OrmHandlers
|
3
|
+
|
4
|
+
module SmoothOperator
|
5
|
+
|
6
|
+
def save(options = {})
|
7
|
+
save!(options, :save)
|
8
|
+
end
|
9
|
+
|
10
|
+
def save!(options = {}, save_method = :save!)
|
11
|
+
before_save
|
12
|
+
save_result = valid? ? save_after_validations(save_method, options) : false
|
13
|
+
after_save if valid? && save_result
|
14
|
+
save_result
|
15
|
+
end
|
16
|
+
|
17
|
+
def destroy(options = {})
|
18
|
+
return true if @represented_object.blank?
|
19
|
+
evoke_method_on_object(@represented_object, :destroy, options)
|
20
|
+
end
|
21
|
+
|
22
|
+
def rollback(options = {})
|
23
|
+
@represented_object.rollback(options)
|
24
|
+
end
|
25
|
+
|
26
|
+
def call_save_or_destroy(object, save_method, options = {})
|
27
|
+
if object == self
|
28
|
+
@represented_object.present? ? evoke_method_on_object(@represented_object, save_method, options) : true
|
29
|
+
else
|
30
|
+
save_method = :destroy if check_if_marked_for_destruction?(object)
|
31
|
+
evoke_method_on_object(object, save_method, options)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
protected #################### PROTECTED METHODS DOWN BELOW ######################
|
36
|
+
|
37
|
+
def save_after_validations(save_method, options = {})
|
38
|
+
return true if @represented_object.blank?
|
39
|
+
evoke_method_on_object(@represented_object, save_method, options)
|
40
|
+
end
|
41
|
+
|
42
|
+
private #################### PRIVATE METHODS DOWN BELOW ######################
|
43
|
+
|
44
|
+
def evoke_method_on_object(object, method, options = {})
|
45
|
+
object.send(method, options)
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: object_attorney
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.9
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-08-
|
12
|
+
date: 2013-08-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -56,6 +56,10 @@ files:
|
|
56
56
|
- README.md
|
57
57
|
- Rakefile
|
58
58
|
- lib/object_attorney.rb
|
59
|
+
- lib/object_attorney/nested_objects.rb
|
60
|
+
- lib/object_attorney/nested_uniqueness_validator.rb
|
61
|
+
- lib/object_attorney/orm.rb
|
62
|
+
- lib/object_attorney/orm_handlers/smooth_operator.rb
|
59
63
|
- lib/object_attorney/version.rb
|
60
64
|
- object_attorney.gemspec
|
61
65
|
homepage: https://github.com/goncalvesjoao/object_attorney
|