light-service 0.0.10 → 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- ![Light Service](https://raw.github.com/adomokos/light-service/master/resources/light-service.png)
1
+ ![LightService](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
 
@@ -7,7 +7,7 @@
7
7
  What do you think of this code?
8
8
 
9
9
  ```ruby
10
- class TaxController < ApplicationContoller
10
+ class TaxController < ApplicationController
11
11
  def update
12
12
  @order = Order.find(params[:id])
13
13
  tax_ranges = TaxRange.for_region(order.region)
@@ -36,7 +36,7 @@ end
36
36
  ```
37
37
 
38
38
  This controller violates [SRP](http://en.wikipedia.org/wiki/Single_responsibility_principle) all over.
39
- Also, imagine what it takes to test this beast.
39
+ Also, imagine what would it take to test this beast.
40
40
  You could move the tax_percentage finders and calculations into the tax model,
41
41
  but then you'll make your model logic heavy.
42
42
 
@@ -62,7 +62,7 @@ and executes them one-by-one. Then you need to create the actions which will onl
62
62
 
63
63
  This is how the organizer and actions interact with eachother:
64
64
 
65
- ![Light Service](https://raw.github.com/adomokos/light-service/master/resources/organizer_and_actions.png)
65
+ ![LightService](https://raw.github.com/adomokos/light-service/master/resources/organizer_and_actions.png)
66
66
 
67
67
  ```ruby
68
68
  class CalculatesTax
@@ -150,7 +150,7 @@ class TaxController < ApplicationContoller
150
150
  end
151
151
  ```
152
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.
153
+ simple and elegant Rails code where I told the story of how LightService was extracted from the projects I had worked on.
154
154
 
155
155
  ## Requirements
156
156
 
@@ -175,63 +175,7 @@ Or install it yourself as:
175
175
  Based on the refactoring example above, just create an organizer object that calls the
176
176
  actions in order and write code for the actions. That's it.
177
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
- ```
178
+ For further examples, please visit the project's [Wiki](https://github.com/adomokos/light-service/wiki).
235
179
 
236
180
  ## Contributing
237
181
 
@@ -243,4 +187,4 @@ end
243
187
 
244
188
  ## License
245
189
 
246
- Light Service is released under the [MIT License](http://www.opensource.org/licenses/MIT).
190
+ LightService is released under the [MIT License](http://www.opensource.org/licenses/MIT).
@@ -8,13 +8,24 @@ module LightService
8
8
  module Macros
9
9
  def executed
10
10
  define_singleton_method "execute" do |context|
11
- return context if context.failure? || context.skip_all?
11
+ action_context = create_action_context(context)
12
+ return action_context if action_context.failure? || action_context.skip_all?
12
13
 
13
- yield(context)
14
+ yield(action_context)
14
15
 
15
- context
16
+ action_context
16
17
  end
17
18
  end
19
+
20
+ private
21
+
22
+ def create_action_context(context)
23
+ if context.respond_to? :failure?
24
+ return context
25
+ end
26
+
27
+ LightService::Context.make(context)
28
+ end
18
29
  end
19
30
 
20
31
  end
@@ -4,36 +4,27 @@ module LightService
4
4
  FAILURE = 1
5
5
  end
6
6
 
7
- class Context
7
+ class Context < Hash
8
8
  attr_accessor :outcome, :message
9
9
 
10
- def initialize(outcome=::LightService::Outcomes::SUCCESS, message='', context={})
11
- @outcome, @message, @context = outcome, message, context
10
+ def initialize(context={}, outcome=::LightService::Outcomes::SUCCESS, message='')
11
+ @outcome, @message = outcome, message
12
+ context.to_hash.each {|k,v| self[k] = v}
12
13
  end
13
14
 
14
15
  def self.make(context={})
15
- Context.new(::LightService::Outcomes::SUCCESS, '', context)
16
+ Context.new(context, ::LightService::Outcomes::SUCCESS, '')
16
17
  end
17
18
 
18
19
  def add_to_context(values)
19
- @context.merge! values
20
- end
21
-
22
- def [](index)
23
- @context[index]
24
- end
25
-
26
- def []=(index, value)
27
- @context[index] = value
28
- end
29
-
30
- def fetch(index)
31
- @context.fetch(index)
20
+ self.merge! values
32
21
  end
33
22
 
34
23
  # It's really there for testing and debugging
24
+ # Deprecated: Please use `to_hash` instead
35
25
  def context_hash
36
- @context.dup
26
+ warn 'DEPRECATED: Please use `to_hash` instead'
27
+ self.dup
37
28
  end
38
29
 
39
30
  def success?
@@ -62,6 +53,5 @@ module LightService
62
53
  @message = message
63
54
  @skip_all = true
64
55
  end
65
-
66
56
  end
67
57
  end
@@ -8,16 +8,10 @@ module LightService
8
8
  def with(data)
9
9
  new.with(data)
10
10
  end
11
-
12
- def reduce(actions)
13
- new.reduce(actions)
14
- end
15
11
  end
16
12
 
17
13
  def with(data = {})
18
- @context = data.kind_of?(::LightService::Context) ?
19
- data :
20
- LightService::Context.make(data)
14
+ @context = LightService::Context.make(data)
21
15
  self
22
16
  end
23
17
 
@@ -1,3 +1,3 @@
1
1
  module LightService
2
- VERSION = "0.0.10"
2
+ VERSION = "0.0.11"
3
3
  end
@@ -17,4 +17,5 @@ Gem::Specification.new do |gem|
17
17
 
18
18
  gem.add_development_dependency("rspec", "~> 2.0")
19
19
  gem.add_development_dependency("simplecov", "~> 0.7.1")
20
+ gem.add_development_dependency("pry", "0.9.12.2")
20
21
  end
@@ -26,7 +26,7 @@ module LightService
26
26
 
27
27
  DummyAction.execute(context)
28
28
 
29
- context.context_hash.keys.should be_empty
29
+ context.to_hash.keys.should be_empty
30
30
  end
31
31
  end
32
32
 
@@ -34,7 +34,7 @@ module LightService
34
34
  it "executes the block" do
35
35
  DummyAction.execute(context)
36
36
 
37
- context.context_hash.keys.should eq [:test_key]
37
+ context.to_hash.keys.should eq [:test_key]
38
38
  end
39
39
  end
40
40
 
@@ -44,7 +44,7 @@ module LightService
44
44
 
45
45
  DummyAction.execute(context)
46
46
 
47
- context.context_hash.keys.should be_empty
47
+ context.to_hash.keys.should be_empty
48
48
  end
49
49
 
50
50
  it "does not execute skipped actions" do
@@ -54,14 +54,23 @@ module LightService
54
54
 
55
55
  SkippedAction.execute(context)
56
56
 
57
- context.context_hash.should eq ({:test_key => "test_value"})
57
+ context.to_hash.should eq ({:test_key => "test_value"})
58
58
  end
59
59
  end
60
60
 
61
61
  it "returns the context" do
62
62
  result = DummyAction.execute(context)
63
63
 
64
- result.context_hash.should eq ({:test_key => "test_value"})
64
+ result.to_hash.should eq ({:test_key => "test_value"})
65
+ end
66
+
67
+ context "can take hash as an argument" do
68
+ it "creates LightService::Context implicitly" do
69
+ result = DummyAction.execute(some_key: "some value")
70
+
71
+ expect(result).to be_success
72
+ expect(result.keys).to eq([:some_key, :test_key])
73
+ end
65
74
  end
66
75
  end
67
76
  end
data/spec/context_spec.rb CHANGED
@@ -2,11 +2,13 @@ require "spec_helper"
2
2
 
3
3
  module LightService
4
4
  describe Context do
5
- subject { Context.new(Outcomes::SUCCESS, "some_message", {:test => 1}) }
5
+ subject { Context.new({:test => 1}, Outcomes::SUCCESS, "some_message") }
6
6
 
7
7
  it "initializes the object with default arguments" do
8
- service_result = Context.new
8
+ service_result = Context.new({test: 1})
9
9
  service_result.should be_success
10
+ service_result.message.should eq ""
11
+ service_result[:test].should eq 1
10
12
  end
11
13
 
12
14
  it "initializes the object with the context" do
@@ -16,11 +18,40 @@ module LightService
16
18
  service_result[:test].should eq 1
17
19
  end
18
20
 
19
- it "initializes the object with make" do
20
- service_result = Context.make({:test => 1})
21
- service_result.should be_success
22
- service_result.message.should eq ""
23
- service_result[:test].should eq 1
21
+ describe ".make" do
22
+ it "initializes the object with make" do
23
+ service_result = Context.make({:test => 1})
24
+ service_result.should be_success
25
+ service_result.message.should eq ""
26
+ service_result[:test].should eq 1
27
+ end
28
+
29
+ context "when passing valid parameters" do
30
+ subject { Context.make(params).to_hash }
31
+
32
+ let(:params) { {test: 1} }
33
+ it { should eq({test: 1}) }
34
+
35
+ let(:params) { Context.make(test: 1) }
36
+ it { should eq({test: 1}) }
37
+ end
38
+
39
+ context "when passing invalid parameters" do
40
+ subject { lambda {Context.make(invalid_params)} }
41
+
42
+ let(:invalid_params) { nil }
43
+ it { should raise_error(NoMethodError) }
44
+
45
+ let(:invalid_params) { [] }
46
+ it { should raise_error(NoMethodError) }
47
+ end
48
+ end
49
+
50
+ describe "#to_hash" do
51
+ it "converts context into a hash" do
52
+ Context.make(test: 1).to_hash.should == {test: 1}
53
+ Context.make({}).to_hash.should == {}
54
+ end
24
55
  end
25
56
 
26
57
  context "when created" do
@@ -45,14 +76,14 @@ module LightService
45
76
  end
46
77
 
47
78
  it "lets setting a group of context values" do
48
- subject.context_hash.should include(:test => 1)
49
- subject.context_hash.keys.length.should == 1
79
+ subject.to_hash.should include(:test => 1)
80
+ subject.to_hash.keys.length.should == 1
50
81
 
51
82
  subject.add_to_context(:test => 1, :two => 2)
52
83
 
53
- subject.context_hash.keys.length.should == 2
54
- subject.context_hash.should include(:test => 1)
55
- subject.context_hash.should include(:two => 2)
84
+ subject.to_hash.keys.length.should == 2
85
+ subject.to_hash.should include(:test => 1)
86
+ subject.to_hash.should include(:two => 2)
56
87
  end
57
88
  end
58
89
 
@@ -31,17 +31,4 @@ describe LightService::Organizer do
31
31
  AnOrganizer.some_method(user)
32
32
  end
33
33
  end
34
-
35
- context "when #with is called with Context" do
36
- it "does not create a context" do
37
- LightService::Context.stub(:new).with(user: user).and_return(context)
38
- LightService::Context.should_not_receive(:make)
39
-
40
- AnAction.should_receive(:execute) \
41
- .with(context) \
42
- .and_return context
43
- AnOrganizer.some_method_with(user)
44
- end
45
- end
46
-
47
34
  end
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.10
4
+ version: 0.0.11
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-06-20 00:00:00.000000000 Z
12
+ date: 2013-10-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -43,6 +43,22 @@ dependencies:
43
43
  - - ~>
44
44
  - !ruby/object:Gem::Version
45
45
  version: 0.7.1
46
+ - !ruby/object:Gem::Dependency
47
+ name: pry
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - '='
52
+ - !ruby/object:Gem::Version
53
+ version: 0.9.12.2
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - '='
60
+ - !ruby/object:Gem::Version
61
+ version: 0.9.12.2
46
62
  description: A service skeleton with an emphasis on simplicity
47
63
  email:
48
64
  - adomokos@gmail.com
@@ -66,7 +82,7 @@ files:
66
82
  - resources/light-service.png
67
83
  - resources/organizer_and_actions.png
68
84
  - spec/acceptance/add_numbers_spec.rb
69
- - spec/action_base_spec.rb
85
+ - spec/action_spec.rb
70
86
  - spec/context_spec.rb
71
87
  - spec/organizer_spec.rb
72
88
  - spec/sample/calculates_order_tax_action_spec.rb
@@ -90,12 +106,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
90
106
  - - ! '>='
91
107
  - !ruby/object:Gem::Version
92
108
  version: '0'
109
+ segments:
110
+ - 0
111
+ hash: -863764600829619710
93
112
  required_rubygems_version: !ruby/object:Gem::Requirement
94
113
  none: false
95
114
  requirements:
96
115
  - - ! '>='
97
116
  - !ruby/object:Gem::Version
98
117
  version: '0'
118
+ segments:
119
+ - 0
120
+ hash: -863764600829619710
99
121
  requirements: []
100
122
  rubyforge_project:
101
123
  rubygems_version: 1.8.23
@@ -104,7 +126,7 @@ specification_version: 3
104
126
  summary: A service skeleton with an emphasis on simplicity
105
127
  test_files:
106
128
  - spec/acceptance/add_numbers_spec.rb
107
- - spec/action_base_spec.rb
129
+ - spec/action_spec.rb
108
130
  - spec/context_spec.rb
109
131
  - spec/organizer_spec.rb
110
132
  - spec/sample/calculates_order_tax_action_spec.rb