You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardexpand all lines: README.md
+213-86
Original file line number
Diff line number
Diff line change
@@ -1,7 +1,7 @@
1
1
Save Queue
2
2
==========
3
-
Save Queue allows to push objects to other object's queue for delayed save.
4
-
Queue save will triggered on object#save.
3
+
Save Queue allows to push objects to other object's queue for a delayed save.
4
+
Queue save will be triggered by object#save.
5
5
6
6
Installation
7
7
------------
@@ -16,146 +16,232 @@ See [contributing guide](http://github.com/AlexParamonov/save_queue/blob/master/
16
16
Usage
17
17
-----
18
18
19
-
How to start:
19
+
### Getting started
20
20
21
21
1. include SaveQueue:
22
22
23
23
require 'save_queue'
24
+
24
25
class Artice
25
26
include SaveQueue
26
27
end
27
28
28
29
2. call \#mark_as_changed method when object gets dirty:
29
30
31
+
require 'save_queue'
32
+
30
33
class Artice
34
+
include SaveQueue
35
+
31
36
def change_attribute attr, value
37
+
@attributes ||= {}
32
38
@attributes[attr] = value
33
39
mark_as_changed # call this and object will be marked for save
34
40
end
35
41
end
36
42
37
-
or implement #has_unsaved_changes? method by yourself:
38
-
If you have custom logic for marking objects dirty then you may want to override
39
-
\#has_unsaved_changes? method in you class like this:
40
-
41
-
def has_unsaved_changes?
42
-
dirty? # dirty is you custom method to determine has object unsaved_changes or not
43
-
end
44
-
45
-
method \#mark_as_saved becomes useless in this case and you should mark objects by your self.
46
-
47
-
48
-
3. point save method to your save logic or dont care if you use #save already:
49
-
50
-
class Artice
51
-
# @return [boolean]
52
-
def save
53
-
write_to_db
54
-
end
55
-
end
56
-
57
-
4. If you want to use validation, include SaveQueue::Plugins::Validation and implement #valid? method. You may got failed objects from #errors\[:validation] array
58
-
\#errors are empty if no errors occurs
59
-
60
-
require 'save_queue/plugins/validation'
61
-
class Artice
62
-
include SaveQueue::Plugins::Validation
63
-
64
-
# @return [boolean]
65
-
def valid?
66
-
true
67
-
end
68
-
end
69
-
70
-
5. add SaveQueue to some other classes:
43
+
3. add SaveQueue to some other classes (or implement #save and #has_unsaved_changes? in it):
71
44
72
45
require 'save_queue'
46
+
73
47
class Tag
74
48
include SaveQueue
49
+
50
+
@attributes ||= {}
51
+
@attributes[attr] = value
52
+
mark_as_changed # call this and object will be marked for save
75
53
end
76
54
55
+
4. Add some functionality:
56
+
77
57
class Artice
78
-
def tags=tag_objects
58
+
def tags=(tag_objects)
79
59
@tags = tag_objects
80
-
saved_queue.add_all tag_objects
60
+
save_queue.add_all tag_objects
81
61
end
82
62
83
-
def add_tagtag
63
+
def add_tag(tag)
84
64
@tags ||= []
85
65
@tags << tag
86
-
saved_queue.add tag # or use <<, push methods
66
+
save_queue.add tag # you may use also #<<, #push methods
87
67
end
88
68
end
89
69
90
-
6.Use it:
70
+
6.Voila!
91
71
92
72
article = Article.new
93
-
tag_objects = [Tag.new, Tag.new, Tag.new]
73
+
74
+
tag_objects = []
75
+
3.times do
76
+
tag = Tag.new
77
+
tag.change_attribute :title, "new tag"
78
+
tag.should_receive(:save).once
79
+
tag_objects << tag
80
+
end
81
+
94
82
article.tags = tag_objects
95
-
article.add_tag Tag.new
83
+
84
+
tag = Tag.new
85
+
tag.change_attribute :title, "single tag"
86
+
tag.should_receive(:save).once
87
+
88
+
article.add_tag tag
96
89
97
90
# that will save article and all tags in this article if article
98
91
# and tags are valid, and if article.save and all tag.save returns true
99
92
# You may also use #save! method, that will trigger save_queue.save! and
100
93
# raise SaveQueue::FailedSaveError on fail
101
-
article.save
94
+
article.save.should be_true
102
95
103
-
You may call it explicitly:
96
+
# You may call save on queue explicitly:
97
+
#
98
+
# article.save_queue.save
99
+
# article.save
104
100
105
-
article.save_queue.save
106
-
article.save
101
+
7. Read README for more details :)
107
102
108
-
See test specs for more details.
109
103
110
-
7. Handle errors
104
+
### Tracing changes
105
+
By default SaveQueue provide changes tracing functional.
106
+
In order to use it, call #mark_as_changed method in your mutator methods like this:
111
107
112
-
7.1. You did not include SaveQueue::Plugins::Validation:
108
+
require "save_queue"
109
+
class Artice
110
+
include SaveQueue
113
111
114
-
unless article.save # article.save_queue.errors.any? or !article.save_queue.errors.empty?
115
-
# @option [Array<Object>] :processed
116
-
# @option [Array<Object>] :saved
117
-
# @option [Object] :failed
118
-
# @option [Array<Object>] :pending
119
-
article.save_queue.errors[:save]
120
-
end
112
+
def change_attribute attr, value
113
+
@attributes[attr] = value
114
+
mark_as_changed # call this and object will be marked for save
115
+
end
116
+
end
121
117
118
+
If you want to mark object as saved, you may use #mark_as_saved method. SaveQueue will automatically call #mark_as_saved
119
+
after saving an object.
120
+
This marks are used when SaveQueue calls #save. Object will be saved only, if it #has_unsaved_changes? returns true.
121
+
There are some docs from spec tests:
122
122
123
-
begin
124
-
article.save!
125
-
rescue SaveQueue::FailedSaveError => error
126
-
# @option [Array<Object>] :processed
127
-
# @option [Array<Object>] :saved
128
-
# @option [Object] :failed
129
-
# @option [Array<Object>] :pending
130
-
error.context
123
+
#has_unsaved_changes?
124
+
should return true for changed object
125
+
should return false for unchanged object
126
+
should return false for new object
127
+
should return true if save_queue was changed by #add
128
+
should return true if save_queue was changed by #<<
129
+
should return true if save_queue was changed by #push
131
130
132
-
article.save_queue.errors[:save] # also set
133
-
end
131
+
If you have custom logic for marking objects dirty then you may want to override
132
+
\#has_unsaved_changes? method, methods #mark_as_saved and #mark_as_changed in you class like this:
134
133
135
-
7.2. You've included SaveQueue::Plugins::Validation:
134
+
def has_unsaved_changes?
135
+
dirty? # dirty is your custom method to determine has object unsaved_changes or not
136
+
end
136
137
137
-
# Note: queue was not saved. You dont need to do a cleanup
138
-
unless article.save then
139
-
failed_objects = article.errors[:validation]
140
-
end
138
+
def mark_as_saved
139
+
# your custom methods
140
+
end
141
141
142
-
begin
143
-
article.save!
144
-
rescue SaveQueue::FailedValidationError => error
145
-
# [Array<Object>]
146
-
error.failed_objects
142
+
def mark_as_changed
143
+
# your custom methods
144
+
end
147
145
148
-
article.save_queue.errors[:validation] # also set
149
-
end
150
146
151
-
You may catch both errors by
147
+
### Error handling
152
148
153
-
begin
154
-
article.save!
155
-
rescue SaveQueue::Error
156
-
# do something
149
+
SaveQueue assumes, that #save method returns true/false and #save! raise an Exception if save failed:
150
+
151
+
unless article.save
152
+
# You may use article.save_queue.errors.any? or article.save_queue.errors.empty? also
153
+
154
+
# returns a [Hash] that contains information about saving proccess:
155
+
# @option [Array<Object>] :processed
156
+
# @option [Array<Object>] :saved
157
+
# @option [Object] :failed
158
+
# @option [Array<Object>] :pending
159
+
article.save_queue.errors[:save]
160
+
end
161
+
162
+
163
+
begin
164
+
article.save!
165
+
rescue SaveQueue::FailedSaveError => error
166
+
167
+
# returns a [Hash] that contains information about saving proccess:
168
+
# @option [Array<Object>] :processed
169
+
# @option [Array<Object>] :saved
170
+
# @option [Object] :failed
171
+
# @option [Array<Object>] :pending
172
+
error.context
173
+
174
+
article.save_queue.errors[:save] # also set
175
+
end
176
+
177
+
178
+
179
+
Plugins
180
+
-------
181
+
I am trying to extract any "extra" functionality into separate plugins, that you may want to include.
182
+
183
+
### Validation plugin
184
+
185
+
If you want to use validation, include SaveQueue::Plugins::Validation and implement #valid? method.
186
+
You may got failed objects from save_queue.errors\[:validation] array.
187
+
\save_queue.errors are empty if no errors occurs
188
+
189
+
require 'save_queue'
190
+
require 'save_queue/plugins/validation'
191
+
192
+
class Artice
193
+
include SaveQueue
194
+
include SaveQueue::Plugins::Validation
195
+
196
+
# @return [boolean]
197
+
def valid?
198
+
true
199
+
end
200
+
201
+
# ...
157
202
end
158
203
204
+
There are specs for them:
205
+
206
+
ValidQueue
207
+
invalid objects
208
+
save
209
+
should not be saved
210
+
should set errors
211
+
save!
212
+
should raise SaveQueue::FailedValidationError exception
213
+
should set errors
214
+
valid objects
215
+
save
216
+
should be saved
217
+
should not set errors
218
+
save!
219
+
should not raise an exception
220
+
should not set errors
221
+
222
+
Also you got more error hangling options:
223
+
224
+
# Note: queue was not saved. You dont need to do a cleanup
225
+
unless article.save then
226
+
failed_objects = article.errors[:validation]
227
+
end
228
+
229
+
begin
230
+
article.save!
231
+
rescue SaveQueue::FailedValidationError => error
232
+
# [Array<Object>]
233
+
error.failed_objects
234
+
235
+
article.save_queue.errors[:validation] # also set
236
+
end
237
+
238
+
You may catch both save and validation errors by
239
+
240
+
begin
241
+
article.save!
242
+
rescue SaveQueue::Error
243
+
# do something
244
+
end
159
245
160
246
if you want not to save an object if save_queue is invalid then add this check to your save method (or any other method that you use, ex: valid?):
161
247
@@ -167,6 +253,44 @@ if you want not to save an object if save_queue is invalid then add this check t
167
253
or you may add it to your validation.
168
254
Note, that #valid? and #validate return true/false and #validate! raises SaveQueue::FailedValidationError exception
169
255
256
+
257
+
258
+
FAQ
259
+
---
260
+
261
+
__Q: I use #write method to store object, how can i use SaveQueue?__
262
+
263
+
A: You may implement save method like this:
264
+
265
+
class Artice
266
+
# @return [boolean]
267
+
def save
268
+
write
269
+
end
270
+
end
271
+
272
+
Note that SaveQueue assumes, that #save method returns true/false and #save! raise an Exception if save failed
0 commit comments