light-service 0.0.9 → 0.0.10
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 +78 -4
- data/lib/light-service/action.rb +1 -1
- data/lib/light-service/context.rb +9 -0
- data/lib/light-service/organizer.rb +21 -8
- data/lib/light-service/version.rb +1 -1
- data/{light-service.png → resources/light-service.png} +0 -0
- data/resources/organizer_and_actions.png +0 -0
- data/spec/acceptance/add_numbers_spec.rb +1 -1
- data/spec/action_base_spec.rb +28 -0
- data/spec/organizer_spec.rb +5 -4
- data/spec/sample/tax/calculates_tax.rb +1 -1
- metadata +4 -3
data/README.md
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
-

|
1
|
+

|
2
2
|
|
3
3
|
[](http://travis-ci.org/adomokos/light-service)
|
4
4
|
|
5
|
+
[](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
|
+

|
66
|
+
|
61
67
|
```ruby
|
62
68
|
class CalculatesTax
|
63
|
-
|
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 '
|
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
|
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).
|
data/lib/light-service/action.rb
CHANGED
@@ -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
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
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
|
-
|
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
|
File without changes
|
Binary file
|
data/spec/action_base_spec.rb
CHANGED
@@ -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
|
|
data/spec/organizer_spec.rb
CHANGED
@@ -4,7 +4,7 @@ describe LightService::Organizer do
|
|
4
4
|
class AnAction; end
|
5
5
|
|
6
6
|
class AnOrganizer
|
7
|
-
|
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.
|
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
|
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(
|
43
|
+
AnOrganizer.some_method_with(user)
|
43
44
|
end
|
44
45
|
end
|
45
46
|
|
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.
|
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-
|
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
|