save_queue 0.1.0 → 0.2.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/README.md +18 -10
- data/lib/save_queue/object.rb +11 -4
- data/lib/save_queue/plugins/validation/object.rb +15 -5
- data/lib/save_queue/plugins/validation/queue.rb +34 -0
- data/lib/save_queue/plugins/validation.rb +28 -0
- data/lib/save_queue/queue.rb +0 -6
- data/lib/save_queue/version.rb +1 -1
- data/lib/save_queue.rb +0 -2
- data/spec/save_queue_usage_spec.rb +27 -45
- data/spec/spec_helper.rb +2 -0
- data/spec/support/mock_helpers.rb +17 -0
- data/spec/validation_spec.rb +126 -0
- metadata +11 -7
data/README.md
CHANGED
@@ -11,11 +11,11 @@ Usage
|
|
11
11
|
|
12
12
|
How to start:
|
13
13
|
|
14
|
-
1. include
|
14
|
+
1. include SaveQueue:
|
15
15
|
|
16
|
-
require '
|
16
|
+
require 'save_queue'
|
17
17
|
class Artice
|
18
|
-
include
|
18
|
+
include SaveQueue
|
19
19
|
end
|
20
20
|
|
21
21
|
2. call \#mark_as_saved method when object gets dirty:
|
@@ -36,20 +36,22 @@ How to start:
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
-
4.
|
39
|
+
4. If you want to use validation, include SaveQueue::Plugins::Validation and implement #valid? method. You may got failed objects by save_queue.objects_with_errors
|
40
40
|
|
41
41
|
class Artice
|
42
|
+
include SaveQueue::Plugins::Validation
|
43
|
+
|
42
44
|
# @return [boolean]
|
43
45
|
def valid?
|
44
46
|
true
|
45
47
|
end
|
46
48
|
end
|
47
49
|
|
48
|
-
5. add
|
50
|
+
5. add SaveQueue to some other classes:
|
49
51
|
|
50
|
-
require '
|
52
|
+
require 'save_queue'
|
51
53
|
class Tag
|
52
|
-
include
|
54
|
+
include SaveQueue
|
53
55
|
end
|
54
56
|
|
55
57
|
class Artice
|
@@ -78,6 +80,8 @@ How to start:
|
|
78
80
|
|
79
81
|
7. Handle errors
|
80
82
|
|
83
|
+
7.1. You did not include SaveQueue::Plugins::Validation:
|
84
|
+
|
81
85
|
begin
|
82
86
|
article.save
|
83
87
|
rescue SaveQueue::FailedSaveError => save_error
|
@@ -89,6 +93,13 @@ How to start:
|
|
89
93
|
save_error.context
|
90
94
|
end
|
91
95
|
|
96
|
+
7.2. You've included SaveQueue::Plugins::Validation:
|
97
|
+
|
98
|
+
# Note nothing was actually saved. You dont need to do a cleanup
|
99
|
+
unless article.save then
|
100
|
+
failed_objects = article.saved_query.objects_with_errors
|
101
|
+
end
|
102
|
+
|
92
103
|
|
93
104
|
|
94
105
|
If you have custom logic for marking objects dirty then you may want to override
|
@@ -103,9 +114,6 @@ method \#mark_as_saved becomes useless in this case and you should mark objects
|
|
103
114
|
|
104
115
|
Note: Today Save Queue use only #save method to perform save actions on an objects, but later this should be changed to custom option.
|
105
116
|
|
106
|
-
Note: Save Queue forced you to use valid? method, this should be changes in future and extracted to a module
|
107
|
-
|
108
|
-
|
109
117
|
Requirements
|
110
118
|
------------
|
111
119
|
none, rspec2 for testing
|
data/lib/save_queue/object.rb
CHANGED
@@ -2,13 +2,20 @@ require "save_queue/queue"
|
|
2
2
|
|
3
3
|
module SaveQueue
|
4
4
|
module Object
|
5
|
+
#class_inheritable_accessor :queue_class
|
6
|
+
def self.included base
|
7
|
+
base.class_eval do
|
8
|
+
class<<self
|
9
|
+
attr_accessor :queue_class
|
10
|
+
end
|
11
|
+
|
12
|
+
self.queue_class = Queue
|
13
|
+
end
|
14
|
+
end
|
5
15
|
|
6
16
|
module RunAlwaysFirst
|
7
17
|
# @return [Boolean]
|
8
18
|
def save(*args)
|
9
|
-
# are objects in queue valid?
|
10
|
-
return false unless valid?
|
11
|
-
return false unless save_queue.valid?
|
12
19
|
#return false if defined?(super) and false == super
|
13
20
|
|
14
21
|
super_saved = true
|
@@ -23,7 +30,7 @@ module SaveQueue
|
|
23
30
|
|
24
31
|
def initialize(*args)
|
25
32
|
super if defined?(super)
|
26
|
-
queue =
|
33
|
+
queue = self.class.queue_class.new
|
27
34
|
instance_variable_set "@_save_queue", queue
|
28
35
|
|
29
36
|
# this will make RunAlwaysFirst methods triggered first in inheritance tree
|
@@ -1,13 +1,23 @@
|
|
1
1
|
module SaveQueue
|
2
2
|
module Plugins
|
3
3
|
module Validation
|
4
|
+
# Should be included AFTER SaveQueue
|
4
5
|
module Object
|
6
|
+
module RunAlwaysFirst
|
7
|
+
# @return [Boolean]
|
8
|
+
def save(*args)
|
9
|
+
# are objects in queue valid?
|
10
|
+
return false unless valid?
|
11
|
+
return false unless save_queue.valid?
|
5
12
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
13
|
+
super
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(*args)
|
18
|
+
super
|
19
|
+
# this will make RunAlwaysFirst methods triggered first in inheritance tree
|
20
|
+
extend RunAlwaysFirst
|
11
21
|
end
|
12
22
|
end
|
13
23
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require "save_queue/queue"
|
2
|
+
module SaveQueue
|
3
|
+
module Plugins
|
4
|
+
module Validation
|
5
|
+
class Queue < ::SaveQueue::Queue
|
6
|
+
attr_reader :objects_with_errors
|
7
|
+
|
8
|
+
def initialize(*args)
|
9
|
+
@objects_with_errors = []
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
13
|
+
def valid?
|
14
|
+
@objects_with_errors = []
|
15
|
+
@queue.each do |object|
|
16
|
+
@objects_with_errors << object unless object.valid?
|
17
|
+
end
|
18
|
+
|
19
|
+
@objects_with_errors.empty?
|
20
|
+
end
|
21
|
+
|
22
|
+
def validate!
|
23
|
+
raise FailedValidationError, @objects_with_errors unless valid?
|
24
|
+
|
25
|
+
true
|
26
|
+
end
|
27
|
+
|
28
|
+
def errors
|
29
|
+
@objects_with_errors.map(&:errors).reduce(:+)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require "save_queue/queue"
|
2
|
+
|
3
|
+
require "save_queue/plugins/validation/object"
|
4
|
+
require "save_queue/plugins/validation/queue"
|
5
|
+
|
6
|
+
|
7
|
+
module SaveQueue
|
8
|
+
module Plugins
|
9
|
+
module Validation
|
10
|
+
def self.included base
|
11
|
+
# must be included after SaveQueue::Object
|
12
|
+
base.send :include, Validation::Object
|
13
|
+
base.queue_class = Validation::Queue
|
14
|
+
end
|
15
|
+
|
16
|
+
class FailedValidationError < RuntimeError
|
17
|
+
attr_reader :failed_objects
|
18
|
+
def initialize(failed_objects)
|
19
|
+
@failed_objects = Array(failed_objects)
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_s # Some default way to display errors
|
23
|
+
"#{super}: " + @failed_objects.map{|object| "\"#{object.to_s}\": " + object.errors.full_messages.join(', ')}.join("\n")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/save_queue/queue.rb
CHANGED
data/lib/save_queue/version.rb
CHANGED
data/lib/save_queue.rb
CHANGED
@@ -1,9 +1,4 @@
|
|
1
|
-
require "
|
2
|
-
module Tests
|
3
|
-
class Object
|
4
|
-
include SaveQueue
|
5
|
-
end
|
6
|
-
end
|
1
|
+
require "spec_helper"
|
7
2
|
|
8
3
|
# TODO split by Object and Queue
|
9
4
|
describe "SaveQueue usage" do
|
@@ -28,7 +23,10 @@ describe "SaveQueue usage" do
|
|
28
23
|
end
|
29
24
|
|
30
25
|
it "should return false for new object" do
|
31
|
-
|
26
|
+
klass = Class.new
|
27
|
+
klass.send :include, SaveQueue
|
28
|
+
|
29
|
+
klass.new.should_not have_unsaved_changes
|
32
30
|
end
|
33
31
|
end
|
34
32
|
|
@@ -58,7 +56,7 @@ describe "SaveQueue usage" do
|
|
58
56
|
end
|
59
57
|
end
|
60
58
|
|
61
|
-
describe "add_all" do
|
59
|
+
describe "#add_all" do
|
62
60
|
it "should delegate to #add" do
|
63
61
|
@base.save_queue.should_receive(:add).exactly(3).times
|
64
62
|
@base.save_queue.add_all [1,2,3]
|
@@ -151,38 +149,6 @@ describe "SaveQueue usage" do
|
|
151
149
|
@base.save.should be_true
|
152
150
|
end
|
153
151
|
|
154
|
-
context "invalid caller" do
|
155
|
-
it "should not save queue" do
|
156
|
-
@base.save_queue.add @related_object
|
157
|
-
|
158
|
-
@base.stub(:valid?).and_return(false)
|
159
|
-
|
160
|
-
@related_object.should_not_receive(:save)
|
161
|
-
@base.save.should be_false
|
162
|
-
|
163
|
-
#@base.stub(:valid?).and_return(true)
|
164
|
-
#@related_object.should_receive(:save).once.and_return(true)
|
165
|
-
#@base.save.should be_true
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
|
-
describe "invalid object in queue" do
|
170
|
-
it "should not save queue and caller" do
|
171
|
-
invalid = new_mock_object :invalid
|
172
|
-
invalid.stub(:valid?).and_return(false)
|
173
|
-
|
174
|
-
valid = new_mock_object :valid
|
175
|
-
valid.stub(:valid?).and_return(true)
|
176
|
-
|
177
|
-
@base.save_queue.add invalid
|
178
|
-
@base.save_queue.add valid
|
179
|
-
|
180
|
-
invalid.should_not_receive(:save)
|
181
|
-
valid.should_not_receive(:save)
|
182
|
-
@base.save.should be_false
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
152
|
describe "multiple callers" do
|
187
153
|
before(:each) do
|
188
154
|
@base2 = new_object
|
@@ -269,11 +235,27 @@ describe "SaveQueue usage" do
|
|
269
235
|
end
|
270
236
|
end
|
271
237
|
|
238
|
+
describe "queue changes" do
|
239
|
+
it "should be able to change queue class before initialization" do
|
240
|
+
klass = Class.new
|
241
|
+
klass.send :include, SaveQueue
|
242
|
+
object = klass.new
|
243
|
+
object.save_queue.should be_a SaveQueue::Queue
|
244
|
+
|
245
|
+
other = Class.new(SaveQueue::Queue)
|
246
|
+
klass.queue_class = other
|
247
|
+
klass.new.save_queue.should be_kind_of other
|
248
|
+
|
249
|
+
object.class.queue_class = other
|
250
|
+
object.save_queue.should_not be_kind_of other
|
251
|
+
object.save_queue.should be_a SaveQueue::Queue
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
272
255
|
private
|
273
256
|
def new_mock_object name
|
274
257
|
bad_object = mock name
|
275
258
|
bad_object.stub_chain(:class, :include?).with(SaveQueue::Object).and_return(true)
|
276
|
-
bad_object.stub(:valid?).and_return(true)
|
277
259
|
bad_object.stub(:save).and_return(true)
|
278
260
|
bad_object.stub(:has_unsaved_changes?).and_return(true)
|
279
261
|
|
@@ -281,12 +263,12 @@ describe "SaveQueue usage" do
|
|
281
263
|
end
|
282
264
|
|
283
265
|
def new_object
|
284
|
-
|
285
|
-
|
266
|
+
klass = Class.new
|
267
|
+
klass.send :include, SaveQueue
|
268
|
+
|
269
|
+
object = klass.new
|
286
270
|
object.mark_as_changed
|
287
271
|
|
288
272
|
object
|
289
273
|
end
|
290
|
-
|
291
|
-
|
292
274
|
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#def new_mock_object name
|
2
|
+
# bad_object = mock name
|
3
|
+
# bad_object.stub_chain(:class, :include?).with(SaveQueue::Object).and_return(true)
|
4
|
+
# bad_object.stub(:valid?).and_return(true)
|
5
|
+
# bad_object.stub(:save).and_return(true)
|
6
|
+
# bad_object.stub(:has_unsaved_changes?).and_return(true)
|
7
|
+
#
|
8
|
+
# bad_object
|
9
|
+
#end
|
10
|
+
#
|
11
|
+
#def new_object
|
12
|
+
# object = Tests::Object.new
|
13
|
+
# object.stub(:valid?).and_return(true)
|
14
|
+
# object.mark_as_changed
|
15
|
+
#
|
16
|
+
# object
|
17
|
+
#end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "save_queue/plugins/validation"
|
3
|
+
|
4
|
+
describe SaveQueue::Plugins::Validation do
|
5
|
+
before(:each) do
|
6
|
+
@invalid = new_object
|
7
|
+
@invalid.stub(:valid?).and_return(false)
|
8
|
+
@valid = new_object
|
9
|
+
@valid.stub(:valid?).and_return(true)
|
10
|
+
end
|
11
|
+
|
12
|
+
describe SaveQueue::Plugins::Validation::Object do
|
13
|
+
before(:each) do
|
14
|
+
@base = new_object
|
15
|
+
end
|
16
|
+
|
17
|
+
context "valid object and caller" do
|
18
|
+
before(:each) do
|
19
|
+
@base.save_queue.add @valid
|
20
|
+
@base.stub(:valid?).and_return(true)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should save caller" do
|
24
|
+
@base.save.should be_true
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should save queue" do
|
28
|
+
@valid.should_receive(:save)
|
29
|
+
|
30
|
+
@base.save
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "invalid caller" do
|
35
|
+
it "should not save queue" do
|
36
|
+
@base.save_queue.add @valid
|
37
|
+
|
38
|
+
@base.stub(:valid?).and_return(false)
|
39
|
+
|
40
|
+
@valid.should_not_receive(:save)
|
41
|
+
@base.save.should be_false
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context "invalid object in queue" do
|
46
|
+
before(:each) do
|
47
|
+
@base.save_queue.add @valid
|
48
|
+
@base.save_queue.add @invalid
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should not save caller" do
|
52
|
+
@base.save.should be_false
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should not save queue" do
|
56
|
+
@invalid.should_not_receive(:save)
|
57
|
+
@valid.should_not_receive(:save)
|
58
|
+
|
59
|
+
@base.save
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe SaveQueue::Plugins::Validation::Queue do
|
65
|
+
before(:each) do
|
66
|
+
@save_queue = SaveQueue::Plugins::Validation::Queue.new
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "#valid?" do
|
70
|
+
it "should set objects_with_errors" do
|
71
|
+
@save_queue.add @invalid
|
72
|
+
@save_queue.add @valid
|
73
|
+
|
74
|
+
@save_queue.valid?.should be_false
|
75
|
+
|
76
|
+
@save_queue.objects_with_errors.should include @invalid
|
77
|
+
@save_queue.objects_with_errors.should_not include @valid
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "#validate!" do
|
82
|
+
it "should raise FailedValidationError if failed to save objects" do
|
83
|
+
@save_queue.add @invalid
|
84
|
+
@save_queue.add @valid
|
85
|
+
|
86
|
+
expect{ @save_queue.validate! }.to raise_error SaveQueue::Plugins::Validation::FailedValidationError
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should return true if objects were valid" do
|
90
|
+
@save_queue.add @valid
|
91
|
+
|
92
|
+
expect{ @save_queue.validate! }.to_not raise_error SaveQueue::Plugins::Validation::FailedValidationError
|
93
|
+
|
94
|
+
@save_queue.validate!.should be_true
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe "#integration" do
|
100
|
+
before(:each) do
|
101
|
+
@klass = Class.new
|
102
|
+
@klass.send :include, SaveQueue
|
103
|
+
@klass.send :include, SaveQueue::Plugins::Validation
|
104
|
+
end
|
105
|
+
it "should set query_class to SaveQueue::Plugins::Validation::Queue" do
|
106
|
+
@klass.queue_class.should == SaveQueue::Plugins::Validation::Queue
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should mix SaveQueue::Plugins::Validation::Object" do
|
110
|
+
@klass.should include SaveQueue::Plugins::Validation::Object
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
private
|
115
|
+
def new_object
|
116
|
+
klass = Class.new
|
117
|
+
klass.send :include, SaveQueue
|
118
|
+
klass.send :include, SaveQueue::Plugins::Validation
|
119
|
+
|
120
|
+
object = klass.new
|
121
|
+
object.stub(:valid?).and_return(true)
|
122
|
+
object.mark_as_changed
|
123
|
+
|
124
|
+
object
|
125
|
+
end
|
126
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: save_queue
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-11-
|
12
|
+
date: 2011-11-16 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement: &
|
16
|
+
requirement: &5065560 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '2.6'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *5065560
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rake
|
27
|
-
requirement: &
|
27
|
+
requirement: &5059980 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,7 +32,7 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *5059980
|
36
36
|
description: Save Queue allows to push related objects to an object's queue for delayed
|
37
37
|
save, that will triggered on object#save. In this case object wil store all related
|
38
38
|
information on its save.
|
@@ -52,12 +52,16 @@ files:
|
|
52
52
|
- Rakefile
|
53
53
|
- lib/save_queue.rb
|
54
54
|
- lib/save_queue/object.rb
|
55
|
+
- lib/save_queue/plugins/validation.rb
|
55
56
|
- lib/save_queue/plugins/validation/object.rb
|
56
57
|
- lib/save_queue/plugins/validation/queue.rb
|
57
58
|
- lib/save_queue/queue.rb
|
58
59
|
- lib/save_queue/version.rb
|
59
60
|
- save_queue.gemspec
|
60
61
|
- spec/save_queue_usage_spec.rb
|
62
|
+
- spec/spec_helper.rb
|
63
|
+
- spec/support/mock_helpers.rb
|
64
|
+
- spec/validation_spec.rb
|
61
65
|
homepage: http://github.com/AlexParamonov/save_queue
|
62
66
|
licenses: []
|
63
67
|
post_install_message:
|
@@ -78,7 +82,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
78
82
|
version: '0'
|
79
83
|
requirements: []
|
80
84
|
rubyforge_project: save_queue
|
81
|
-
rubygems_version: 1.8.
|
85
|
+
rubygems_version: 1.8.11
|
82
86
|
signing_key:
|
83
87
|
specification_version: 3
|
84
88
|
summary: Push related objects to a queue for delayed save
|