light-service 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,7 +1,9 @@
1
- ![Light Service](https://raw.github.com/adomokos/light-service/master/light-service.png)
1
+ ![Light Service](https://raw.github.com/adomokos/light-service/master/resources/light-service.png)
2
2
 
3
3
  [![Build Status](https://secure.travis-ci.org/adomokos/light-service.png)](http://travis-ci.org/adomokos/light-service)
4
4
 
5
+ [![Code Climate](https://codeclimate.com/github/adomokos/light-service.png)](https://codeclimate.com/github/adomokos/light-service)
6
+
5
7
  What do you think of this code?
6
8
 
7
9
  ```ruby
@@ -58,9 +60,13 @@ This block of code should tell you the "story" of what's going on in this workfl
58
60
  With the help of LightService you can write code this way. First you need an organizer object that sets up the actions in order
59
61
  and executes them one-by-one. Then you need to create the actions which will only have one method and will do only one thing.
60
62
 
63
+ This is how the organizer and actions interact with eachother:
64
+
65
+ ![Light Service](https://raw.github.com/adomokos/light-service/master/resources/organizer_and_actions.png)
66
+
61
67
  ```ruby
62
68
  class CalculatesTax
63
- extend LightService::Organizer
69
+ include LightService::Organizer
64
70
 
65
71
  def self.for_order(order)
66
72
  with(order: order).reduce \
@@ -143,12 +149,18 @@ class TaxController < ApplicationContoller
143
149
  end
144
150
  end
145
151
  ```
152
+ I gave a [talk at RailsConf 2013](http://www.adomokos.com/2013/06/simple-and-elegant-rails-code-with.html) on
153
+ simple and elegant Rails code where I told the story of how Light Service was extracted from the projects I had worked on.
154
+
155
+ ## Requirements
156
+
157
+ This gem requires ruby 1.9.x
146
158
 
147
159
  ## Installation
148
160
 
149
161
  Add this line to your application's Gemfile:
150
162
 
151
- gem 'light_service'
163
+ gem 'light-service'
152
164
 
153
165
  And then execute:
154
166
 
@@ -156,13 +168,71 @@ And then execute:
156
168
 
157
169
  Or install it yourself as:
158
170
 
159
- $ gem install light_service
171
+ $ gem install light-service
160
172
 
161
173
  ## Usage
162
174
 
163
175
  Based on the refactoring example above, just create an organizer object that calls the
164
176
  actions in order and write code for the actions. That's it.
165
177
 
178
+ Here's how to use a `LightService::Action` as a `LightService::Organizer`:
179
+
180
+ ```ruby
181
+ require 'light-service'
182
+
183
+ module Yoyo
184
+ class PushesLead
185
+ include LightService::Action
186
+ include LightService::Organizer
187
+
188
+ executed do |context|
189
+ lead = context.fetch(:lead)
190
+ fail ArgumentError if lead.nil?
191
+
192
+ integration = context.fetch(:integration)
193
+ fail ArgumentError if integration.nil?
194
+
195
+ with(context).reduce([
196
+ PreparesLeadForImport,
197
+ RemoteClient::ImportsGuestCard
198
+ ])
199
+ end
200
+ end
201
+ end
202
+ ```
203
+
204
+ Calling `set_failure!` on the context will stop execution of the remaining actions, in some cases you may want the same behaviour but not due to failure, in that case use `skip_all!`. `skip_all!` optionally takes a message argument.
205
+
206
+ ```ruby
207
+ # organizer class registered to execute 2 actions
208
+ class AddComment
209
+ extend LightService::Organizer
210
+
211
+ def self.to_post(args = {})
212
+ with(args).reduce [
213
+ SaveCommentAction,
214
+ PublishCommentAction
215
+ ]
216
+ end
217
+ end
218
+
219
+ # action to save comment data, conditionally will bypass the remaining actions
220
+ class SaveCommentAction
221
+ include LightService::Action
222
+
223
+ executed do |context|
224
+ comment = context.fetch(:comment)
225
+ post = context.fetch(:post)
226
+ post.comments << comment
227
+
228
+ unless comment.commenter.can_auto_approve_own_comment
229
+ # calling skip_all! will bypass PublishCommentAction execution
230
+ context.skip_all!
231
+ end
232
+ end
233
+ end
234
+ ```
235
+
166
236
  ## Contributing
167
237
 
168
238
  1. Fork it
@@ -170,3 +240,7 @@ actions in order and write code for the actions. That's it.
170
240
  3. Commit your changes (`git commit -am 'Added some feature'`)
171
241
  4. Push to the branch (`git push origin my-new-feature`)
172
242
  5. Create new Pull Request
243
+
244
+ ## License
245
+
246
+ Light Service is released under the [MIT License](http://www.opensource.org/licenses/MIT).
@@ -8,7 +8,7 @@ module LightService
8
8
  module Macros
9
9
  def executed
10
10
  define_singleton_method "execute" do |context|
11
- return context if context.failure?
11
+ return context if context.failure? || context.skip_all?
12
12
 
13
13
  yield(context)
14
14
 
@@ -44,6 +44,10 @@ module LightService
44
44
  success? == false
45
45
  end
46
46
 
47
+ def skip_all?
48
+ @skip_all
49
+ end
50
+
47
51
  def set_success!(message)
48
52
  @message = message
49
53
  @outcome = ::LightService::Outcomes::SUCCESS
@@ -54,5 +58,10 @@ module LightService
54
58
  @outcome = ::LightService::Outcomes::FAILURE
55
59
  end
56
60
 
61
+ def skip_all!(message = nil)
62
+ @message = message
63
+ @skip_all = true
64
+ end
65
+
57
66
  end
58
67
  end
@@ -1,15 +1,28 @@
1
1
  module LightService
2
2
  module Organizer
3
- protected
4
- def with(data = {})
5
- @context = data.kind_of?(::LightService::Context) ?
6
- data :
7
- LightService::Context.make(data)
8
- self
3
+ def self.included(base_class)
4
+ base_class.extend ClassMethods
5
+ end
6
+
7
+ module ClassMethods
8
+ def with(data)
9
+ new.with(data)
9
10
  end
10
11
 
11
- def reduce(actions=[])
12
- actions.reduce(@context) { |context, action| action.execute(context) }
12
+ def reduce(actions)
13
+ new.reduce(actions)
13
14
  end
15
+ end
16
+
17
+ def with(data = {})
18
+ @context = data.kind_of?(::LightService::Context) ?
19
+ data :
20
+ LightService::Context.make(data)
21
+ self
22
+ end
23
+
24
+ def reduce(actions=[])
25
+ actions.reduce(@context) { |context, action| action.execute(context) }
26
+ end
14
27
  end
15
28
  end
@@ -1,3 +1,3 @@
1
1
  module LightService
2
- VERSION = "0.0.9"
2
+ VERSION = "0.0.10"
3
3
  end
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  class Organizer
4
- extend LightService::Organizer
4
+ include LightService::Organizer
5
5
 
6
6
  def self.add_number(number)
7
7
  with(number: number).reduce \
@@ -10,6 +10,14 @@ module LightService
10
10
  end
11
11
  end
12
12
 
13
+ class SkippedAction
14
+ include LightService::Action
15
+
16
+ executed do |context|
17
+ context[:test_key] = "set_by_skipped_action"
18
+ end
19
+ end
20
+
13
21
  let(:context) { ::LightService::Context.new }
14
22
 
15
23
  context "when the action context has failure" do
@@ -30,6 +38,26 @@ module LightService
30
38
  end
31
39
  end
32
40
 
41
+ context "when the action context skips all" do
42
+ it "returns immediately" do
43
+ context.skip_all!
44
+
45
+ DummyAction.execute(context)
46
+
47
+ context.context_hash.keys.should be_empty
48
+ end
49
+
50
+ it "does not execute skipped actions" do
51
+ DummyAction.execute(context)
52
+
53
+ context.skip_all!
54
+
55
+ SkippedAction.execute(context)
56
+
57
+ context.context_hash.should eq ({:test_key => "test_value"})
58
+ end
59
+ end
60
+
33
61
  it "returns the context" do
34
62
  result = DummyAction.execute(context)
35
63
 
@@ -4,7 +4,7 @@ describe LightService::Organizer do
4
4
  class AnAction; end
5
5
 
6
6
  class AnOrganizer
7
- extend LightService::Organizer
7
+ include LightService::Organizer
8
8
 
9
9
  def self.some_method(user)
10
10
  with(user: user).reduce [AnAction]
@@ -16,7 +16,7 @@ describe LightService::Organizer do
16
16
  end
17
17
  end
18
18
 
19
- let(:context) { ::LightService::Context.make(user: user) }
19
+ let!(:context) { ::LightService::Context.new(user: user) }
20
20
  let(:user) { double(:user) }
21
21
 
22
22
  context "when #with is called with hash" do
@@ -34,12 +34,13 @@ describe LightService::Organizer do
34
34
 
35
35
  context "when #with is called with Context" do
36
36
  it "does not create a context" do
37
- LightService::Context.stub(:new).and_return context
37
+ LightService::Context.stub(:new).with(user: user).and_return(context)
38
+ LightService::Context.should_not_receive(:make)
38
39
 
39
40
  AnAction.should_receive(:execute) \
40
41
  .with(context) \
41
42
  .and_return context
42
- AnOrganizer.some_method_with(context)
43
+ AnOrganizer.some_method_with(user)
43
44
  end
44
45
  end
45
46
 
@@ -1,5 +1,5 @@
1
1
  class CalculatesTax
2
- extend LightService::Organizer
2
+ include LightService::Organizer
3
3
 
4
4
  def self.for_order(order)
5
5
  with(order: order).reduce \
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: light-service
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.0.10
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-30 00:00:00.000000000 Z
12
+ date: 2013-06-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -63,7 +63,8 @@ files:
63
63
  - lib/light-service/organizer.rb
64
64
  - lib/light-service/version.rb
65
65
  - light-service.gemspec
66
- - light-service.png
66
+ - resources/light-service.png
67
+ - resources/organizer_and_actions.png
67
68
  - spec/acceptance/add_numbers_spec.rb
68
69
  - spec/action_base_spec.rb
69
70
  - spec/context_spec.rb