Skip to content

Commit d7b86a1

Browse files
committed
README update, add jruby and rbx to ci
1 parent b752da6 commit d7b86a1

File tree

4 files changed

+282
-90
lines changed

4 files changed

+282
-90
lines changed

.travis.yml

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ rvm:
22
- 1.8.7
33
- 1.9.2
44
- 1.9.3
5-
- jruby
5+
- jruby-19mode
6+
- jruby-18mode
7+
- rbx-19mode
8+
- rbx-18mode
69
- ruby-head
710
- ree

README.md

+213-86
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Save Queue
22
==========
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.
55

66
Installation
77
------------
@@ -16,146 +16,232 @@ See [contributing guide](http://github.com/AlexParamonov/save_queue/blob/master/
1616
Usage
1717
-----
1818

19-
How to start:
19+
### Getting started
2020

2121
1. include SaveQueue:
2222

2323
require 'save_queue'
24+
2425
class Artice
2526
include SaveQueue
2627
end
2728

2829
2. call \#mark_as_changed method when object gets dirty:
2930

31+
require 'save_queue'
32+
3033
class Artice
34+
include SaveQueue
35+
3136
def change_attribute attr, value
37+
@attributes ||= {}
3238
@attributes[attr] = value
3339
mark_as_changed # call this and object will be marked for save
3440
end
3541
end
3642

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):
7144

7245
require 'save_queue'
46+
7347
class Tag
7448
include SaveQueue
49+
50+
@attributes ||= {}
51+
@attributes[attr] = value
52+
mark_as_changed # call this and object will be marked for save
7553
end
7654

55+
4. Add some functionality:
56+
7757
class Artice
78-
def tags= tag_objects
58+
def tags=(tag_objects)
7959
@tags = tag_objects
80-
saved_queue.add_all tag_objects
60+
save_queue.add_all tag_objects
8161
end
8262

83-
def add_tag tag
63+
def add_tag(tag)
8464
@tags ||= []
8565
@tags << tag
86-
saved_queue.add tag # or use <<, push methods
66+
save_queue.add tag # you may use also #<<, #push methods
8767
end
8868
end
8969

90-
6. Use it:
70+
6. Voila!
9171

9272
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+
9482
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
9689

9790
# that will save article and all tags in this article if article
9891
# and tags are valid, and if article.save and all tag.save returns true
9992
# You may also use #save! method, that will trigger save_queue.save! and
10093
# raise SaveQueue::FailedSaveError on fail
101-
article.save
94+
article.save.should be_true
10295

103-
You may call it explicitly:
96+
# You may call save on queue explicitly:
97+
#
98+
# article.save_queue.save
99+
# article.save
104100

105-
article.save_queue.save
106-
article.save
101+
7. Read README for more details :)
107102

108-
See test specs for more details.
109103

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:
111107

112-
7.1. You did not include SaveQueue::Plugins::Validation:
108+
require "save_queue"
109+
class Artice
110+
include SaveQueue
113111

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
121117

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:
122122

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
131130

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:
134133

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
136137

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
141141

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
147145

148-
article.save_queue.errors[:validation] # also set
149-
end
150146

151-
You may catch both errors by
147+
### Error handling
152148

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+
# ...
157202
end
158203

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
159245

160246
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?):
161247

@@ -167,6 +253,44 @@ if you want not to save an object if save_queue is invalid then add this check t
167253
or you may add it to your validation.
168254
Note, that #valid? and #validate return true/false and #validate! raises SaveQueue::FailedValidationError exception
169255

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
273+
274+
__Q: Where i can get more information?__
275+
276+
A: See test specs for more details.
277+
278+
__How?__
279+
280+
clone git project by
281+
282+
git clone git://github.com/AlexParamonov/save_queue.git
283+
284+
cd into it and run bundle
285+
286+
cd save_queue
287+
bundle
288+
289+
and run rake
290+
291+
rake
292+
293+
170294
Requirements
171295
------------
172296

@@ -180,7 +304,10 @@ tested with Ruby
180304
* 1.8.7
181305
* 1.9.2
182306
* 1.9.3
183-
* jruby
307+
* jruby-19mode
308+
* jruby-18mode
309+
* rbx-19mode
310+
* rbx-18mode
184311
* ruby-head
185312
* ree
186313

0 commit comments

Comments
 (0)