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 CHANGED
@@ -11,11 +11,11 @@ Usage
11
11
 
12
12
  How to start:
13
13
 
14
- 1. include SavedQueue:
14
+ 1. include SaveQueue:
15
15
 
16
- require 'saved_queue'
16
+ require 'save_queue'
17
17
  class Artice
18
- include SavedQueue
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. Save Queue forced you to use valid? method, this should be changes in future and extracted to a module:
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 SavedQueue to some other classes:
50
+ 5. add SaveQueue to some other classes:
49
51
 
50
- require 'saved_queue'
52
+ require 'save_queue'
51
53
  class Tag
52
- include SavedQueue
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
@@ -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 = Queue.new
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
- # @return [Boolean]
7
- def save(*args)
8
- # are objects in queue valid?
9
- return false unless valid?
10
- return false unless save_queue.valid?
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
@@ -30,12 +30,6 @@ module SaveQueue
30
30
 
31
31
  true
32
32
  end
33
-
34
- def valid?
35
- @queue.all? do |object|
36
- object.valid?
37
- end
38
- end
39
33
  end
40
34
 
41
35
  class FailedSaveError < RuntimeError
@@ -1,3 +1,3 @@
1
1
  module SaveQueue
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
data/lib/save_queue.rb CHANGED
@@ -5,6 +5,4 @@ module SaveQueue
5
5
  def self.included base
6
6
  base.send :include, SaveQueue::Object
7
7
  end
8
-
9
-
10
8
  end
@@ -1,9 +1,4 @@
1
- require "save_queue"
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
- Tests::Object.new.should_not have_unsaved_changes
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
- object = Tests::Object.new
285
- object.stub(:valid?).and_return(true)
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
@@ -0,0 +1,2 @@
1
+ require "save_queue"
2
+ Dir[File.dirname(File.expand_path(__FILE__)) + "/support/**/*.rb"].each {|f| require f}
@@ -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.1.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-15 00:00:00.000000000Z
12
+ date: 2011-11-16 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &23937520 !ruby/object:Gem::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: *23937520
24
+ version_requirements: *5065560
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rake
27
- requirement: &23936900 !ruby/object:Gem::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: *23936900
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.10
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