save_queue 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.travis.yml +3 -2
- data/HISTORY.md +13 -6
- data/README.md +184 -126
- data/lib/save_queue/exceptions.rb +2 -1
- data/lib/save_queue/object/queue_class_management.rb +21 -0
- data/lib/save_queue/object.rb +35 -47
- data/lib/save_queue/object_queue.rb +14 -26
- data/lib/save_queue/plugins/dirty/object.rb +31 -0
- data/lib/save_queue/plugins/dirty.rb +11 -0
- data/lib/save_queue/plugins/notification/object.rb +6 -24
- data/lib/save_queue/plugins/notification/queue.rb +2 -3
- data/lib/save_queue/plugins/notification.rb +2 -2
- data/lib/save_queue/plugins/validation/exceptions.rb +10 -2
- data/lib/save_queue/plugins/validation/queue.rb +1 -1
- data/lib/save_queue/plugins/validation.rb +1 -1
- data/lib/save_queue/uniq_queue.rb +10 -2
- data/lib/save_queue/version.rb +1 -1
- data/spec/dirty/dirty_spec.rb +74 -0
- data/spec/dirty/object_spec.rb +200 -0
- data/spec/notification/notification_spec.rb +3 -4
- data/spec/notification/object_spec.rb +0 -17
- data/spec/notification/queue_spec.rb +4 -4
- data/spec/object/queue_class_management_spec.rb +53 -0
- data/spec/object_queue_spec.rb +58 -68
- data/spec/object_spec.rb +124 -163
- data/spec/save_queue_spec.rb +0 -62
- data/spec/support/object_helpers.rb +31 -0
- data/spec/support/queue_helpers.rb +3 -1
- data/spec/uniq_queue_spec.rb +51 -21
- data/spec/validation/queue_spec.rb +83 -32
- metadata +14 -8
data/.travis.yml
CHANGED
data/HISTORY.md
CHANGED
@@ -1,14 +1,21 @@
|
|
1
|
+
0.4.x
|
2
|
+
=====
|
3
|
+
- Remove changes trakcing functional from SaveQueue::Object and move it to Dirty plugin.
|
4
|
+
+ Dirty plugin.
|
5
|
+
* Notification plugin dont mark object as saved by default.
|
6
|
+
* Refactor to 'tell dont ask' pattern.
|
7
|
+
|
1
8
|
0.3.x
|
2
9
|
=====
|
3
|
-
+ Notification plugin
|
4
|
-
+
|
5
|
-
+
|
6
|
-
+
|
10
|
+
+ Notification plugin.
|
11
|
+
+ Add save! method.
|
12
|
+
+ Refactor Validation plugin.
|
13
|
+
+ Bugfixing.
|
7
14
|
|
8
15
|
0.2.x
|
9
16
|
=====
|
10
|
-
Implemented main functionality, add Validation plugin
|
17
|
+
Implemented main functionality, add Validation plugin.
|
11
18
|
|
12
19
|
0.0.1
|
13
20
|
=====
|
14
|
-
Initial release. Add README, LICENSE, .gitignore, etc
|
21
|
+
Initial release. Add README, LICENSE, .gitignore, etc.
|
data/README.md
CHANGED
@@ -1,8 +1,18 @@
|
|
1
1
|
Save Queue
|
2
2
|
==========
|
3
|
-
|
4
|
-
|
3
|
+
[](http://travis-ci.org/AlexParamonov/save_queue)
|
4
|
+
[](http://gemnasium.com/AlexParamonov/save_queue)
|
5
5
|
|
6
|
+
Save Queue creates queue of objects inside holder object.
|
7
|
+
Queue will be saved and cleared after successfull holder object save.
|
8
|
+
|
9
|
+
|
10
|
+
**Holder object** is object that include SaveQueue.
|
11
|
+
**Object in queue** is any instance of any class, that include SaveQueue or respond to #save method.
|
12
|
+
|
13
|
+
|
14
|
+
There are plugins, that alter queue or holder object behavior, find them in 'save_queue/plugins' directory and read about
|
15
|
+
them in Plugins section of [readme](https://github.com/AlexParamonov/save_queue/blob/develop/README.md)
|
6
16
|
|
7
17
|
Contents
|
8
18
|
---------
|
@@ -10,9 +20,9 @@ Contents
|
|
10
20
|
1. Contributing
|
11
21
|
1. Usage
|
12
22
|
* Getting started
|
13
|
-
* Tracking changes
|
14
23
|
* Error handling
|
15
24
|
1. Plugins
|
25
|
+
* Dirty
|
16
26
|
* Validation
|
17
27
|
* Notification
|
18
28
|
1. Creating your own Queues / TODO
|
@@ -27,50 +37,42 @@ Installation
|
|
27
37
|
|
28
38
|
Contributing
|
29
39
|
-------------
|
30
|
-
|
40
|
+
**Please help to improve this project!**
|
31
41
|
|
32
|
-
|
42
|
+
|
43
|
+
See [contributing guide](http://github.com/AlexParamonov/save_queue/blob/master/CONTRIBUTING.md) for best practices
|
44
|
+
I am using [gitflow](https://github.com/nvie/gitflow). Develop branch is most featured and usually far above master.
|
33
45
|
|
34
46
|
Usage
|
35
47
|
-----
|
36
48
|
|
37
49
|
### Getting started
|
38
50
|
|
39
|
-
1.
|
40
|
-
|
41
|
-
require 'save_queue'
|
42
|
-
|
43
|
-
class Artice
|
44
|
-
include SaveQueue
|
45
|
-
end
|
46
|
-
|
47
|
-
2. call \#mark_as_changed method when object gets dirty:
|
51
|
+
1. Include SaveQueue:
|
48
52
|
|
49
53
|
require 'save_queue'
|
50
54
|
|
51
55
|
class Artice
|
52
56
|
include SaveQueue
|
53
57
|
|
54
|
-
def
|
55
|
-
|
56
|
-
@attributes[attr] = value
|
57
|
-
mark_as_changed # call this and object will be marked for save
|
58
|
+
def save
|
59
|
+
puts "article saved!"
|
58
60
|
end
|
59
61
|
end
|
60
62
|
|
61
|
-
|
63
|
+
1. Add SaveQueue to some other classes (or implement #save method in it):
|
62
64
|
|
63
65
|
require 'save_queue'
|
64
66
|
|
65
67
|
class Tag
|
66
68
|
include SaveQueue
|
67
69
|
|
68
|
-
|
69
|
-
|
70
|
-
|
70
|
+
def save
|
71
|
+
puts "tag saved!"
|
72
|
+
end
|
71
73
|
end
|
72
74
|
|
73
|
-
|
75
|
+
1. Add some functionality:
|
74
76
|
|
75
77
|
class Artice
|
76
78
|
def tags=(tag_objects)
|
@@ -81,83 +83,60 @@ Usage
|
|
81
83
|
def add_tag(tag)
|
82
84
|
@tags ||= []
|
83
85
|
@tags << tag
|
84
|
-
save_queue.add tag #
|
86
|
+
save_queue.add tag # methods #<<, #push can be also used to add object to queue
|
87
|
+
# You may also do
|
88
|
+
# tag.save_queue << self
|
89
|
+
# save_queue will not circle in this case
|
85
90
|
end
|
86
91
|
end
|
87
92
|
|
88
|
-
|
93
|
+
1. Voila!
|
89
94
|
|
90
95
|
article = Article.new
|
91
96
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
article.tags = tag_objects
|
97
|
+
# Create 3 tags and add them to the article
|
98
|
+
article.tags =
|
99
|
+
3.times.map do
|
100
|
+
tag = Tag.new
|
101
|
+
tag.should_receive(:save).once
|
102
|
+
|
103
|
+
tag
|
104
|
+
end
|
101
105
|
|
106
|
+
# Add single tag
|
102
107
|
tag = Tag.new
|
103
|
-
tag.change_attribute :title, "single tag"
|
104
108
|
tag.should_receive(:save).once
|
105
109
|
|
106
110
|
article.add_tag tag
|
107
111
|
|
108
|
-
# that will save article and all tags in this article if article
|
109
|
-
# and
|
110
|
-
# You may also use #save! method, that will
|
112
|
+
# that will save article and all tags in this article if article.save
|
113
|
+
# and all tag.save returns true.
|
114
|
+
# You may also use #save! method, that will delegate to article.save! and
|
111
115
|
# raise SaveQueue::FailedSaveError on fail
|
112
116
|
article.save.should be_true
|
113
117
|
|
118
|
+
# Output:
|
119
|
+
# article saved!
|
120
|
+
# tag saved!
|
121
|
+
# tag saved!
|
122
|
+
# tag saved!
|
123
|
+
# tag saved!
|
124
|
+
|
125
|
+
# empty the queue after successfull save
|
126
|
+
article.save_queue.should be_empty
|
127
|
+
|
128
|
+
article.save
|
129
|
+
# Output:
|
130
|
+
# article saved!
|
131
|
+
|
114
132
|
# You may call save on queue explicitly:
|
115
133
|
#
|
116
134
|
# article.save_queue.save
|
117
135
|
# article.save
|
118
136
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
### Tracking changes
|
123
|
-
By default SaveQueue provide changes tracking functional.
|
124
|
-
In order to use it, call #mark_as_changed method in your mutator methods like this:
|
125
|
-
|
126
|
-
require "save_queue"
|
127
|
-
class Artice
|
128
|
-
include SaveQueue
|
129
|
-
|
130
|
-
def change_attribute attr, value
|
131
|
-
@attributes[attr] = value
|
132
|
-
mark_as_changed # call this and object will be marked for save
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
If you want to mark object as saved, you may use #mark_as_saved method. SaveQueue will automatically call #mark_as_saved
|
137
|
-
after saving an object.
|
138
|
-
This marks are used when SaveQueue calls #save. Object will be saved only, if it #has_unsaved_changes? returns true.
|
139
|
-
There are some docs from spec tests:
|
140
|
-
|
141
|
-
#has_unsaved_changes?
|
142
|
-
should return true for changed object
|
143
|
-
should return false for unchanged object
|
144
|
-
should return false for new object
|
145
|
-
|
146
|
-
If you have custom logic for marking objects dirty then you may want to override
|
147
|
-
\#has_unsaved_changes? method, methods #mark_as_saved and #mark_as_changed in you class like this:
|
148
|
-
|
149
|
-
def has_unsaved_changes?
|
150
|
-
dirty? # dirty is your custom method to determine has object unsaved_changes or not
|
151
|
-
end
|
152
|
-
|
153
|
-
def mark_as_saved
|
154
|
-
# your custom methods
|
155
|
-
end
|
156
|
-
|
157
|
-
def mark_as_changed
|
158
|
-
# your custom methods
|
159
|
-
end
|
137
|
+
1. To save object _only_ if it was changed, include Dirty module described below.
|
160
138
|
|
139
|
+
1. Continue reading for more details.
|
161
140
|
|
162
141
|
### Error handling
|
163
142
|
|
@@ -167,7 +146,6 @@ SaveQueue assumes, that #save method returns true/false and #save! raise an Exce
|
|
167
146
|
# You may use article.save_queue.errors.any? or article.save_queue.errors.empty? also
|
168
147
|
|
169
148
|
# returns a [Hash] that contains information about saving proccess:
|
170
|
-
# @option [Array<Object>] :processed
|
171
149
|
# @option [Array<Object>] :saved
|
172
150
|
# @option [Object] :failed
|
173
151
|
# @option [Array<Object>] :pending
|
@@ -180,7 +158,6 @@ SaveQueue assumes, that #save method returns true/false and #save! raise an Exce
|
|
180
158
|
rescue SaveQueue::FailedSaveError => error
|
181
159
|
|
182
160
|
# returns a [Hash] that contains information about saving proccess:
|
183
|
-
# @option [Array<Object>] :processed
|
184
161
|
# @option [Array<Object>] :saved
|
185
162
|
# @option [Object] :failed
|
186
163
|
# @option [Array<Object>] :pending
|
@@ -189,16 +166,64 @@ SaveQueue assumes, that #save method returns true/false and #save! raise an Exce
|
|
189
166
|
article.save_queue.errors[:save] # also set
|
190
167
|
end
|
191
168
|
|
192
|
-
|
169
|
+
Queue is not cleared after fail. Possible to fix errors and rerun queue.save
|
193
170
|
|
194
171
|
Plugins
|
195
172
|
-------
|
196
|
-
|
173
|
+
Any extract any "extra" functionality goes into bundled plugins.
|
174
|
+
|
175
|
+
### Dirty
|
176
|
+
|
177
|
+
SaveQueue::Plugins::Dirty module provide changes tracking functional.
|
178
|
+
In order to use it include this module and call #mark_as_changed method in mutator methods like this:
|
179
|
+
|
180
|
+
require "save_queue"
|
181
|
+
require "save_queue/plugins/dirty"
|
182
|
+
|
183
|
+
class Artice
|
184
|
+
include SaveQueue
|
185
|
+
include SaveQueue::Plugins::Dirty
|
186
|
+
|
187
|
+
def initialize
|
188
|
+
@attributes = {}
|
189
|
+
end
|
190
|
+
|
191
|
+
def change_attribute attr, value
|
192
|
+
@attributes[attr] = value
|
193
|
+
mark_as_changed # call this and object will be marked for a save
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
To mark object as saved, call #mark_as_saved method. SaveQueue Dirty plugin will automatically call
|
198
|
+
\#mark_as_saved method after saving an object.
|
199
|
+
This marks are used when SaveQueue calls #save. Object will be saved only, if it #has_unsaved_changes? method returns true.
|
200
|
+
There are some docs from spec tests:
|
201
|
+
|
202
|
+
#has_unsaved_changes?
|
203
|
+
should return true for changed object
|
204
|
+
should return false for unchanged object
|
205
|
+
should return false for new object
|
206
|
+
|
207
|
+
If you have custom logic for marking objects dirty then you may want to overwrite
|
208
|
+
\#has_unsaved_changes? method, methods #mark_as_saved and #mark_as_changed in you class like this:
|
209
|
+
|
210
|
+
def has_unsaved_changes?
|
211
|
+
dirty? # dirty is your custom method to determine has object unsaved_changes or not
|
212
|
+
end
|
213
|
+
|
214
|
+
def mark_as_saved
|
215
|
+
# your custom methods
|
216
|
+
end
|
217
|
+
|
218
|
+
def mark_as_changed
|
219
|
+
# your custom methods
|
220
|
+
end
|
221
|
+
|
197
222
|
|
198
223
|
### Validation
|
199
224
|
|
200
|
-
|
201
|
-
|
225
|
+
To use validation include SaveQueue::Plugins::Validation and implement #valid? method.
|
226
|
+
Failed objects are stored in save_queue.errors\[:validation] array.
|
202
227
|
\save_queue.errors are empty if no errors occurs
|
203
228
|
|
204
229
|
require 'save_queue'
|
@@ -218,23 +243,58 @@ You may got failed objects from save_queue.errors\[:validation] array.
|
|
218
243
|
|
219
244
|
There are specs for them:
|
220
245
|
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
should
|
226
|
-
save!
|
227
|
-
should raise
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
should
|
232
|
-
|
233
|
-
|
234
|
-
should
|
235
|
-
|
236
|
-
|
237
|
-
|
246
|
+
SaveQueue::Plugins::Validation::Queue
|
247
|
+
is empty
|
248
|
+
should be valid
|
249
|
+
#save
|
250
|
+
should be true
|
251
|
+
#save!
|
252
|
+
should not raise Exception
|
253
|
+
contains valid objects
|
254
|
+
#save
|
255
|
+
should be true
|
256
|
+
should save all elements
|
257
|
+
#save!
|
258
|
+
should not raise Exception
|
259
|
+
should save all elements
|
260
|
+
#valid?
|
261
|
+
should be true
|
262
|
+
should not has any errors
|
263
|
+
#validate!
|
264
|
+
should not raise any exception
|
265
|
+
should not has any errors
|
266
|
+
contains invalid objects
|
267
|
+
behaves like queue with invalid objects
|
268
|
+
#save
|
269
|
+
should be false
|
270
|
+
should not save elements
|
271
|
+
#save!
|
272
|
+
should raise SaveQueue::FailedValidationError
|
273
|
+
should not save elements
|
274
|
+
#valid?
|
275
|
+
should be false
|
276
|
+
should set errors
|
277
|
+
#validate!
|
278
|
+
should raise SaveQueue::FailedValidationError exception
|
279
|
+
should set errors
|
280
|
+
contains mix of valid and invalid objects
|
281
|
+
#save should call #valid?
|
282
|
+
#save! should call #validate!
|
283
|
+
behaves like queue with invalid objects
|
284
|
+
#save
|
285
|
+
should be false
|
286
|
+
should not save elements
|
287
|
+
#save!
|
288
|
+
should raise SaveQueue::FailedValidationError
|
289
|
+
should not save elements
|
290
|
+
#valid?
|
291
|
+
should be false
|
292
|
+
should set errors
|
293
|
+
#validate!
|
294
|
+
should raise SaveQueue::FailedValidationError exception
|
295
|
+
should set errors
|
296
|
+
|
297
|
+
Plugin adds SaveQueue::FailedValidationError:
|
238
298
|
|
239
299
|
# Note: queue was not saved. You dont need to do a cleanup
|
240
300
|
unless article.save then
|
@@ -250,7 +310,7 @@ Also you got more error hangling options:
|
|
250
310
|
article.save_queue.errors[:validation] # also set
|
251
311
|
end
|
252
312
|
|
253
|
-
|
313
|
+
To catch both save and validation errors use SaveQueue::Error:
|
254
314
|
|
255
315
|
begin
|
256
316
|
article.save!
|
@@ -258,21 +318,24 @@ You may catch both save and validation errors by
|
|
258
318
|
# do something
|
259
319
|
end
|
260
320
|
|
261
|
-
|
321
|
+
To not save an object if save_queue is invalid, add this condition to #save method:
|
262
322
|
|
263
323
|
def save
|
264
324
|
return false unless save_queue.valid?
|
265
325
|
#..
|
266
326
|
end
|
267
327
|
|
268
|
-
or
|
269
|
-
Note, that #valid? and #validate return true/false and #validate! raises SaveQueue::FailedValidationError exception
|
328
|
+
or add it to validation (to object#valid? method for example).
|
329
|
+
Note, that queue#valid? and queue#validate return true/false and queue#validate! raises SaveQueue::FailedValidationError exception.
|
330
|
+
Queue is not creared if validation fails.
|
270
331
|
|
271
332
|
### Notification
|
272
333
|
|
273
|
-
|
274
|
-
|
275
|
-
|
334
|
+
To use notification include SaveQueue::Plugins::Notification.
|
335
|
+
Holder object will be notified by #queue_changed_event method.
|
336
|
+
Overwrite this method to implement your functionality, for ex logging.
|
337
|
+
|
338
|
+
require 'save_queue/plugins/notification'
|
276
339
|
|
277
340
|
class Artice
|
278
341
|
include SaveQueue
|
@@ -280,21 +343,17 @@ You may override this method in your object if you want to.
|
|
280
343
|
end
|
281
344
|
|
282
345
|
article = Article.new
|
283
|
-
article.
|
284
|
-
|
285
|
-
article.should have_unsaved changes
|
346
|
+
article.save_queue << tag # this will trigger callback #queue_changed_event on article
|
347
|
+
|
286
348
|
|
287
349
|
class Artice
|
288
350
|
def queue_changed_event(result, object)
|
289
|
-
super
|
290
351
|
puts "queue was changed!"
|
291
352
|
end
|
292
353
|
end
|
293
354
|
|
294
355
|
article = Article.new
|
295
|
-
article.
|
296
|
-
article.save_queue << tag # "queue was changed!"
|
297
|
-
article.should have_unsaved changes
|
356
|
+
article.save_queue.add tag # Outputs "queue was changed!"
|
298
357
|
|
299
358
|
|
300
359
|
Creating your own Queues
|
@@ -305,9 +364,8 @@ Creating your own Queues
|
|
305
364
|
FAQ
|
306
365
|
---
|
307
366
|
|
308
|
-
__Q: I use #write method to store object, how can i use SaveQueue?__
|
309
|
-
|
310
|
-
A: You may implement save method like this:
|
367
|
+
__Q: I use #write method to store object, how can i use SaveQueue?__
|
368
|
+
A: You may implement #save method like this:
|
311
369
|
|
312
370
|
class Artice
|
313
371
|
# @return [boolean]
|
@@ -316,14 +374,12 @@ A: You may implement save method like this:
|
|
316
374
|
end
|
317
375
|
end
|
318
376
|
|
319
|
-
Note that SaveQueue assumes, that #save method returns true/false and #save! raise an Exception if save failed
|
320
|
-
|
321
|
-
__Q: Where i can get more information?__
|
322
|
-
|
323
|
-
A: See test specs for more details.
|
377
|
+
Note that SaveQueue assumes, that #save method returns true/false and #save! raise an Exception if save failed.
|
324
378
|
|
325
|
-
__How?__
|
326
379
|
|
380
|
+
__Q: Where i can get more information?__
|
381
|
+
A: See test specs for more details.
|
382
|
+
__How?__
|
327
383
|
clone git project by
|
328
384
|
|
329
385
|
git clone git://github.com/AlexParamonov/save_queue.git
|
@@ -333,10 +389,11 @@ cd into it and run bundle
|
|
333
389
|
cd save_queue
|
334
390
|
bundle
|
335
391
|
|
336
|
-
and
|
392
|
+
and then rake
|
337
393
|
|
338
394
|
rake
|
339
395
|
|
396
|
+
docs will be printed to your console :)
|
340
397
|
|
341
398
|
Requirements
|
342
399
|
------------
|
@@ -352,6 +409,7 @@ tested with Ruby
|
|
352
409
|
* 1.9.2
|
353
410
|
* 1.9.3
|
354
411
|
* jruby-18mode
|
412
|
+
* jruby-19mode
|
355
413
|
* rbx-19mode
|
356
414
|
* rbx-18mode
|
357
415
|
* ruby-head
|
@@ -2,11 +2,12 @@ module SaveQueue
|
|
2
2
|
class Error < RuntimeError; end
|
3
3
|
class FailedSaveError < Error
|
4
4
|
attr_reader :context
|
5
|
+
|
5
6
|
def initialize(context_hash)
|
6
7
|
@context = context_hash
|
7
8
|
end
|
8
9
|
|
9
|
-
def to_s
|
10
|
+
def to_s
|
10
11
|
"#{super}: " + @context.to_s
|
11
12
|
end
|
12
13
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'hooks'
|
2
|
+
require 'save_queue/object_queue'
|
3
|
+
|
4
|
+
module SaveQueue
|
5
|
+
module Object
|
6
|
+
module QueueClassManagement
|
7
|
+
def queue_class
|
8
|
+
@queue_class ||= ObjectQueue
|
9
|
+
end
|
10
|
+
|
11
|
+
def queue_class=(klass)
|
12
|
+
raise "Your Queue implementation: #{klass} should include Hooks module!" unless klass.include? Hooks
|
13
|
+
@queue_class = klass
|
14
|
+
end
|
15
|
+
|
16
|
+
def inherited base
|
17
|
+
base.queue_class = self.queue_class
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/save_queue/object.rb
CHANGED
@@ -1,49 +1,40 @@
|
|
1
1
|
require 'save_queue/object_queue'
|
2
|
+
require 'save_queue/object/queue_class_management'
|
2
3
|
|
3
4
|
module SaveQueue
|
4
5
|
module Object
|
5
|
-
|
6
|
-
base.class_eval do
|
7
|
-
|
8
|
-
class<<self
|
9
|
-
attr_reader :queue_class
|
10
|
-
|
11
|
-
def queue_class=(klass)
|
12
|
-
raise "Your Queue implementation: #{klass} should include Hooks module!" unless klass.include? Hooks
|
13
|
-
@queue_class = klass
|
14
|
-
end
|
15
|
-
end
|
6
|
+
attr_reader :processed
|
16
7
|
|
17
|
-
|
18
|
-
|
19
|
-
end
|
20
|
-
|
21
|
-
self.queue_class ||= ObjectQueue
|
22
|
-
end
|
8
|
+
def self.included base
|
9
|
+
base.send :extend, QueueClassManagement
|
23
10
|
end
|
24
11
|
|
25
|
-
|
26
12
|
module RunAlwaysFirst
|
27
13
|
# can not reilly on save! here, because client may not define it at all
|
28
14
|
def save(*args)
|
29
|
-
|
30
|
-
|
15
|
+
no_recursion do
|
16
|
+
super_result =
|
17
|
+
_sq_around_original_save do
|
18
|
+
super if defined?(super)
|
19
|
+
end
|
31
20
|
|
32
|
-
|
21
|
+
return false if false == super_result
|
22
|
+
return false unless save_queue.save
|
33
23
|
|
34
|
-
|
35
|
-
if save_queue.save
|
36
|
-
true == super_result ? true : super_result # super_result may be not boolean, String for ex
|
37
|
-
else
|
38
|
-
false
|
24
|
+
super_result || true
|
39
25
|
end
|
40
26
|
end
|
41
27
|
|
42
|
-
#
|
28
|
+
# TODO squash with save method
|
29
|
+
# Expect save! to raise an Exception if failed to save an object
|
43
30
|
def save!
|
44
|
-
|
45
|
-
|
46
|
-
|
31
|
+
no_recursion do
|
32
|
+
_sq_around_original_save do
|
33
|
+
super if defined?(super)
|
34
|
+
end
|
35
|
+
|
36
|
+
save_queue.save!
|
37
|
+
end
|
47
38
|
end
|
48
39
|
end
|
49
40
|
|
@@ -55,29 +46,26 @@ module SaveQueue
|
|
55
46
|
extend RunAlwaysFirst
|
56
47
|
end
|
57
48
|
|
58
|
-
def
|
59
|
-
|
60
|
-
end
|
61
|
-
|
62
|
-
# @returns [Boolean] true if object has been modified
|
63
|
-
def has_unsaved_changes?
|
64
|
-
status = instance_variable_get("@_changed_mark")
|
65
|
-
status.nil? ? false : status
|
49
|
+
def save_queue
|
50
|
+
@_save_queue
|
66
51
|
end
|
67
52
|
|
68
|
-
|
69
|
-
|
53
|
+
private
|
54
|
+
def create_queue
|
55
|
+
# queue_class located in QueueClassManagement
|
56
|
+
@_save_queue = self.class.queue_class.new
|
70
57
|
end
|
71
58
|
|
72
|
-
def
|
73
|
-
|
59
|
+
def _sq_around_original_save
|
60
|
+
yield
|
74
61
|
end
|
75
62
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
63
|
+
def no_recursion
|
64
|
+
return true if @_no_recursion_saving_flag
|
65
|
+
@_no_recursion_saving_flag = true
|
66
|
+
yield
|
67
|
+
ensure
|
68
|
+
@_no_recursion_saving_flag = false
|
81
69
|
end
|
82
70
|
end
|
83
71
|
end
|