save_queue 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Build Status](https://secure.travis-ci.org/AlexParamonov/save_queue.png)](http://travis-ci.org/AlexParamonov/save_queue)
|
4
|
+
[![Gemnasium Build Status](https://gemnasium.com/AlexParamonov/save_queue.png)](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
|