simple_service 1.0.2 → 1.2.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 34986961f7123b9e3d467a2886eac29975e5ca1c
4
- data.tar.gz: 69ef5d5fd27746e2f9cd3ef1fdebf8ca1052f9b7
3
+ metadata.gz: 62127eaaf7ab561f13e676804054b5f6c5badb6b
4
+ data.tar.gz: 3c707fa3145d309d2ffe402a9083136cb464d0ab
5
5
  SHA512:
6
- metadata.gz: de14c40b0a186d035b1a7c1a8b43a4e9d6ac7c00209bccde3f7200661f816baeba28c2b4d94875b95c98122bc95433b9d991367c226ae5ca92f6ef7f7d778d13
7
- data.tar.gz: 6946d0168b295ff890883a2c7fb966fc5b0214441581712fbc5f785dbb2c999387dc45db49d8e7cd9e12e3564c127012438551049e9069b2dadbd748b925f6ea
6
+ metadata.gz: 966251837c81145882975a90ceb9ad88a97e9bcd39d182216e1fc4b0e425f8167d835a87df0bb3c3d43ab83624633a050334b2f46fb7cf35273d97815dd4e7d9
7
+ data.tar.gz: 31a500a462b2b4d98b7a49a6470ad93fe977b512744d8861b2d3e1d03536295a002060ab5c4b46ec7b2b10e7b533595bf5f0591f07ac2aeb619540adbae5327a
data/.gitignore CHANGED
@@ -3,6 +3,7 @@
3
3
  .bundle
4
4
  .config
5
5
  .yardoc
6
+ .ruby-version
6
7
  Gemfile.lock
7
8
  InstalledFiles
8
9
  _yardoc
data/README.md CHANGED
@@ -14,17 +14,18 @@ objects can be reused in multiple organizers minimizing code duplication.
14
14
  When an organizer is instantiated a hash of arguments is passed in. This hash
15
15
  is referred to as the context. The context hash is carried along throughout
16
16
  the sequence of command executions and modified by each command. After a
17
- successful run, the entire context hash (or a specified subset) is returned.
17
+ successful run, the keys specified are returned. If keys are not specified, the
18
+ entire context hash is returned.
18
19
 
19
20
  First, setup an Organizer class. An Organizer needs the following things defined:
20
21
 
21
22
  * expects: keys that are required to be passed into initialize when an
22
23
  instance of organizer is created. If not defined the organizer will
23
24
  accept arbitrary arguments.
24
- * returns: keys that will be returned when the organizer has executed all of
25
+ * returns: keys that will be returned when the organizer has called all of
25
26
  its commands
26
- * commands: classes that define all the steps that the organizer will execute.
27
- The organizer will call #execute on each command in order and the context
27
+ * commands: classes that define all the steps that the organizer will call.
28
+ The organizer will execute #call on each command in order and the context
28
29
  hash is passed to each of these commands. Any keys within the context that
29
30
  are modified will be merged back into the organizer and passed along to the
30
31
  next command.
@@ -36,12 +37,12 @@ class ProcessSomethingComplex < SimpleService::Organizer
36
37
  # leave out to accept any arguments/keys
37
38
  expects :something, :another_thing
38
39
 
39
- # optional - specifies which keys get returned after #execute is called on
40
+ # optional - specifies which keys get returned after #call is executed on
40
41
  # an organizer instance
41
42
  returns :modified_thing
42
43
 
43
44
  # what steps comprise this service
44
- # #execute will be called on an instance of each class in sequence
45
+ # #call will be executed on an instance of each class in sequence
45
46
  commands DoSomethingImportant, DoAnotherStep
46
47
 
47
48
  end
@@ -66,7 +67,7 @@ class DoSomethingImportant < SimpleService::Command
66
67
  # getters and setters are available for each key specified
67
68
  # in expects and returns. If not using expects and returns
68
69
  # simply interact with the context hash directly
69
- def execute
70
+ def call
70
71
  # uses getters and setters to modify the context
71
72
  self.modified_something = self.something.to_i + 1
72
73
 
@@ -88,14 +89,14 @@ end
88
89
  ## Usage
89
90
 
90
91
  Using the service is straight forward - just instantiate it, passing in the
91
- intial context hash, and then call execute.
92
+ intial context hash, and then call.
92
93
 
93
94
  ```ruby
94
95
  starting_context = {
95
96
  something: '1',
96
97
  :another_thing: AnotherThing.new
97
98
  }
98
- modified_context = ProcessSomethingComplex.new(starting_context).execute
99
+ modified_context = ProcessSomethingComplex.new(starting_context).call
99
100
 
100
101
  modified_context[:modified_thing] # => 2
101
102
  ```
@@ -104,6 +105,12 @@ If you are using this with a Rails app, placing top level services in
104
105
  app/services/ and all commands in app/services/commands/ is recommended. If
105
106
  not using rails, a similar structure would also be recommended.
106
107
 
108
+ For further examination of usage, here are a few examples:
109
+
110
+ * [hello world example](example/hello_world.rb)
111
+ * [nested services example](example/nested_services.rb)
112
+ * [override #call on the organizer](example/override_organizer_call_method.rb)
113
+
107
114
  ## Inspiration and Rationale
108
115
 
109
116
  This gem is heavily inspired by two very nice gems:
@@ -113,7 +120,7 @@ This gem is heavily inspired by two very nice gems:
113
120
  Mutations is a great gem, but lacks the concept of a top level organizer.
114
121
  LightService brings in the notion of the organizer object, but doesn't create
115
122
  instances of its action objects (what are referred to as commands here). Using
116
- instances rather than class level execute definitions allows the use of private
123
+ instances rather than class level #call definitions allows the use of private
117
124
  methods within the command for more complex commands that still do a single thing.
118
125
 
119
126
  The other goal of this gem is to do as little as possible above and beyond
@@ -1,12 +1,11 @@
1
1
  require 'rubygems'
2
- require 'pry'
3
2
  require 'simple_service'
4
3
 
5
4
  class ConcatName < SimpleService::Command
6
5
  expects :first_name, :last_name
7
6
  returns :name
8
7
 
9
- def execute
8
+ def call
10
9
  self.name = "#{first_name} #{last_name}"
11
10
  end
12
11
  end
@@ -15,7 +14,7 @@ class CreateHelloString < SimpleService::Command
15
14
  expects :name
16
15
  returns :hello
17
16
 
18
- def execute
17
+ def call
19
18
  self.hello = "#{name}, say hello world!"
20
19
  end
21
20
  end
@@ -26,5 +25,5 @@ class SayHello < SimpleService::Organizer
26
25
  commands ConcatName, CreateHelloString
27
26
  end
28
27
 
29
- result = SayHello.new(first_name: 'Ruby', last_name: 'Gem').execute
28
+ result = SayHello.new(first_name: 'Ruby', last_name: 'Gem').call
30
29
  puts result[:hello]
@@ -0,0 +1,29 @@
1
+ require 'rubygems'
2
+ require 'simple_service'
3
+
4
+ class Increment < SimpleService::Command
5
+ expects :counter
6
+ returns :counter
7
+
8
+ def call
9
+ self.counter += 1
10
+ end
11
+ end
12
+
13
+ class IncrementCounter < SimpleService::Organizer
14
+ expects :counter
15
+ returns :counter
16
+ commands Increment, Increment, Increment
17
+ end
18
+
19
+ class ReallyIncrementThatCounter < SimpleService::Organizer
20
+ expects :counter
21
+ returns :counter
22
+ commands IncrementCounter, IncrementCounter, IncrementCounter
23
+ end
24
+
25
+ result = IncrementCounter.new(counter: 0).call
26
+ puts "IncrementCounter: #{result[:counter]}"
27
+
28
+ result = ReallyIncrementThatCounter.new(counter: 0).call
29
+ puts "ReallyIncrementThatCounter: #{result[:counter]}"
@@ -0,0 +1,29 @@
1
+ require 'rubygems'
2
+ require 'simple_service'
3
+
4
+ class Increment < SimpleService::Command
5
+ expects :counter
6
+ returns :counter
7
+
8
+ def execute
9
+ self.counter += 1
10
+ end
11
+ end
12
+
13
+ class IncrementCounter < SimpleService::Organizer
14
+ expects :counter
15
+ returns :counter
16
+ commands Increment, Increment, Increment
17
+ end
18
+
19
+ class ReallyIncrementThatCounter < SimpleService::Organizer
20
+ expects :counter
21
+ returns :counter
22
+ commands IncrementCounter, IncrementCounter, IncrementCounter
23
+ end
24
+
25
+ result = IncrementCounter.new(counter: 0).execute
26
+ puts "IncrementCounter: #{result[:counter]}"
27
+
28
+ result = ReallyIncrementThatCounter.new(counter: 0).execute
29
+ puts "ReallyIncrementThatCounter: #{result[:counter]}"
@@ -0,0 +1,39 @@
1
+ require 'rubygems'
2
+ require 'simple_service'
3
+
4
+ class ConcatAnotherName < SimpleService::Command
5
+ expects :first_name, :last_name
6
+ returns :name
7
+
8
+ def call
9
+ self.name = "#{first_name} #{last_name}"
10
+ end
11
+ end
12
+
13
+ class CreateAnotherHelloString < SimpleService::Command
14
+ expects :name
15
+ returns :hello
16
+
17
+ def call
18
+ self.hello ||= ''
19
+ self.hello += "#{name}, say hello world!"
20
+ end
21
+ end
22
+
23
+ class SayHelloMultipleTimes < SimpleService::Organizer
24
+ expects :first_name, :last_name, :num_times
25
+ returns :hello
26
+ commands ConcatAnotherName, CreateAnotherHelloString
27
+
28
+ # overriding the #call method on the organizer allows
29
+ # you to do things like loop and call the service commands
30
+ # multiple times
31
+ def call
32
+ num_times.times do
33
+ super
34
+ end
35
+ end
36
+ end
37
+
38
+ result = SayHelloMultipleTimes.new(first_name: 'Ruby', last_name: 'Gem', num_times: 3).call
39
+ puts result[:hello]
@@ -8,40 +8,20 @@ module SimpleService
8
8
 
9
9
  def initialize(context={})
10
10
  @context = context
11
- setup_execute_chain
11
+ setup_call_chain
12
12
  define_getters_and_setters
13
- end
14
-
15
- # execute is where the command's behavior is defined
16
- # execute should be overriden by whatever class inherits from
17
- # this class
18
- def execute
19
- error_msg = "#{self.class} - does not define an execute method"
20
- raise SimpleService::ExecuteNotDefinedError , error_msg
21
- end
22
-
23
- private
24
13
 
25
- def all_specified_context_keys
26
- (expects + returns)
14
+ unless skip_validation
15
+ ValidatesExpectedKeys.new(provided_keys: context.keys).call
16
+ end
27
17
  end
28
18
 
29
- def define_getters_and_setters
30
- all_specified_context_keys.each do |key|
31
- self.class.class_eval do
32
-
33
- # getter
34
- define_method key do
35
- self.context[key]
36
- end
37
-
38
- # setter
39
- define_method "#{key}=" do |val|
40
- self.context[key] = val
41
- end
42
-
43
- end
44
- end
19
+ # call is where the command's behavior is defined
20
+ # call should be overriden by whatever class inherits from
21
+ # this class
22
+ def call
23
+ error_msg = "#{self.class} - does not define a call method"
24
+ raise SimpleService::CallNotDefinedError , error_msg
45
25
  end
46
26
 
47
27
  end
@@ -0,0 +1,16 @@
1
+ module SimpleService
2
+ class ValidatesCommandsNotEmpty < Command
3
+
4
+ expects :provided_commands
5
+
6
+ skip_validation true
7
+
8
+ def call
9
+ if provided_commands.nil? || provided_commands.empty?
10
+ error_msg = 'This Organizer class does not contain any command definitions'
11
+ raise SimpleService::OrganizerCommandsNotDefinedError, error_msg
12
+ end
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,24 @@
1
+ module SimpleService
2
+ class ValidatesCommandsProperlyInherit < Command
3
+
4
+ expects :provided_commands
5
+
6
+ skip_validation true
7
+
8
+ def call
9
+ # valid commands inherit from Command and do not inherit from service
10
+ # reject all valid commands and anything left over is invalid
11
+ invalid_commands = provided_commands.to_a.reject do |command|
12
+ command.ancestors.include?(SimpleService::Command) ||
13
+ command.ancestors.include?(SimpleService::Organizer)
14
+ end
15
+
16
+ if invalid_commands.any?
17
+ error_msg = invalid_commands.join(', ') +
18
+ ' - must inherit from SimpleService::Command'
19
+ raise SimpleService::CommandParentClassInvalidError, error_msg
20
+ end
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,19 @@
1
+ module SimpleService
2
+ class ValidatesExpectedKeys < Command
3
+
4
+ expects :expected_keys, :provided_keys
5
+
6
+ skip_validation true
7
+
8
+ def call
9
+ arguments_not_included = expected_keys.to_a - provided_keys.to_a
10
+
11
+ if arguments_not_included.any?
12
+ error_msg = 'keys required by the organizer but not found in the context: ' +
13
+ arguments_not_included.join(', ')
14
+ raise ExpectedKeyError, error_msg
15
+ end
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,21 @@
1
+ module SimpleService
2
+ class EnsureOrganizerIsValid < Organizer
3
+
4
+ expects :expected_keys, :provided_keys, :provided_commands
5
+
6
+ skip_validation true # false so as to not cause an infinite loop
7
+
8
+ commands ValidatesExpectedKeys,
9
+ ValidatesCommandsNotEmpty,
10
+ ValidatesCommandsProperlyInherit
11
+
12
+ def call
13
+ super
14
+
15
+ # dont return the keys within this internal service
16
+ # so we dont pollute external service objects
17
+ context.select { |k,v| !expects.include?(k) }
18
+ end
19
+
20
+ end
21
+ end
@@ -3,6 +3,6 @@ module SimpleService
3
3
  class OrganizerCommandsNotDefinedError < StandardError; end;
4
4
  class CommandParentClassInvalidError < StandardError; end;
5
5
  class ExpectedKeyError < StandardError; end;
6
- class ExecuteNotDefinedError < StandardError; end;
6
+ class CallNotDefinedError < StandardError; end;
7
7
  class ReturnKeyError < StandardError; end;
8
8
  end
@@ -9,14 +9,8 @@ module SimpleService
9
9
  def initialize(context={})
10
10
  @context = context
11
11
 
12
- ArgumentValidator.new(
13
- context: context,
14
- expects: expects,
15
- returns: returns,
16
- commands: commands
17
- ).execute
18
-
19
- setup_execute_chain
12
+ setup_call_chain
13
+ define_getters_and_setters
20
14
  end
21
15
 
22
16
  def self.commands(*args)
@@ -27,12 +21,49 @@ module SimpleService
27
21
  self.class.instance_variable_get('@commands')
28
22
  end
29
23
 
30
- def execute
31
- commands.each do |command|
32
- @context.merge!(command.new(context).execute)
24
+ def call
25
+ with_validation do |_commands|
26
+ _commands.each do |command|
27
+ @context.merge!(command.new(context).call)
28
+ end
33
29
  end
34
30
  end
35
31
 
32
+ # allow execution of the service from the class level for those
33
+ # that prefer that style
34
+ def self.call(context)
35
+ self.new(context).call
36
+ end
37
+
38
+ private
39
+
40
+ def with_validation
41
+ add_validation_keys_to_context unless skip_validation
42
+
43
+ _commands = skip_validation ? commands : [EnsureOrganizerIsValid] + commands
44
+
45
+ yield(_commands)
46
+
47
+ remove_validation_keys_from_context unless skip_validation
48
+ end
49
+
50
+ def add_validation_keys_to_context
51
+ context.merge!(validation_hash)
52
+ end
53
+
54
+ def remove_validation_keys_from_context
55
+ validation_hash.keys.each do |key|
56
+ context.delete(key)
57
+ end
58
+ end
59
+
60
+ def validation_hash
61
+ @validation_hash ||= {
62
+ provided_keys: context.keys,
63
+ expected_keys: expects,
64
+ provided_commands: commands
65
+ }
66
+ end
36
67
  end
37
68
 
38
69
  end
@@ -9,22 +9,26 @@ module SimpleService
9
9
  def returns(*args)
10
10
  @returns = args
11
11
  end
12
+
13
+ def skip_validation(skip=true)
14
+ @skip_validation = skip
15
+ end
12
16
  end
13
17
 
14
18
  module InstanceMethods
15
19
 
16
- def setup_execute_chain
20
+ def setup_call_chain
17
21
  self.class.class_eval do
18
22
 
19
23
  # grab the method object and hold onto it here
20
- execute_method = instance_method(:execute)
24
+ call_method = instance_method(:call)
21
25
 
22
- # redefine the execute method, call the existing execute method object,
23
- # and then run return key checking... allows user to implement execute in
26
+ # redefine the call method, execute the existing call method object,
27
+ # and then run return key checking... allows user to implement call in
24
28
  # their individual command classes without having to call super or any
25
29
  # other method to return only specific context keys
26
- define_method :execute do
27
- execute_method.bind(self).call
30
+ define_method :call do
31
+ call_method.bind(self).call
28
32
  find_specified_return_keys
29
33
  end
30
34
  end
@@ -54,6 +58,33 @@ module SimpleService
54
58
  def returns
55
59
  self.class.instance_variable_get('@returns') || []
56
60
  end
61
+
62
+ def skip_validation
63
+ self.class.instance_variable_get('@skip_validation')
64
+ end
65
+
66
+ def all_specified_context_keys
67
+ (expects + returns).uniq
68
+ end
69
+
70
+ def define_getters_and_setters
71
+ all_specified_context_keys.each do |key|
72
+ self.class.class_eval do
73
+
74
+ # getter
75
+ define_method key do
76
+ self.context[key]
77
+ end
78
+
79
+ # setter
80
+ define_method "#{key}=" do |val|
81
+ self.context[key] = val
82
+ end
83
+
84
+ end
85
+ end
86
+ end
87
+
57
88
  end
58
89
 
59
90
  end
@@ -1,3 +1,3 @@
1
1
  module SimpleService
2
- VERSION = '1.0.2'
2
+ VERSION = '1.2.5'
3
3
  end
@@ -1,10 +1,12 @@
1
1
  require 'simple_service/service_base'
2
- require 'simple_service/argument_validator'
3
2
  require 'simple_service/command'
4
- require 'simple_service/exceptions'
5
3
  require 'simple_service/organizer'
4
+ require 'simple_service/exceptions'
5
+ require 'simple_service/commands/validates_commands_not_empty'
6
+ require 'simple_service/commands/validates_commands_properly_inherit'
7
+ require 'simple_service/commands/validates_expected_keys'
8
+ require 'simple_service/ensure_organizer_is_valid'
6
9
  require 'simple_service/version'
7
10
 
8
11
  module SimpleService
9
- # Your code goes here...
10
12
  end
@@ -3,41 +3,48 @@ require 'spec_helper'
3
3
  describe SimpleService::Command do
4
4
 
5
5
  class ValidCommand < SimpleService::Command
6
-
7
6
  expects :foo, :bar
8
7
  returns :bar, :baz
9
-
10
- def execute
8
+ def call
11
9
  context.merge!(
12
10
  bar: 'modified',
13
11
  baz: 'blah'
14
12
  )
15
13
  end
14
+ end
16
15
 
16
+ class InvalidReturnCommand < SimpleService::Command
17
+ expects :foo
18
+ returns :foo, :baz
19
+ def call; true; end
17
20
  end
18
21
 
19
- class NoExecuteDefinedCommand < SimpleService::Command
22
+
23
+ class CallNotDefinedCommand < SimpleService::Command
20
24
  end
21
25
 
22
- describe '#execute' do
26
+ describe '#call' do
23
27
 
24
28
  context 'when #returns is not empty' do
25
29
  it 'returns the correct keys from the context' do
26
30
  expect(
27
- ValidCommand.new(foo: 'blah', bar: 'meh').execute
31
+ ValidCommand.new(foo: 'blah', bar: 'meh').call
28
32
  ).to eql(bar: 'modified', baz: 'blah')
29
33
  end
30
34
  end
31
35
 
32
36
  context 'raises error' do
33
37
 
34
- it 'when command does not define an execute method' do
38
+ it 'when command does not define an call method' do
39
+ expect {
40
+ CallNotDefinedCommand.new.call
41
+ }.to raise_error(SimpleService::CallNotDefinedError)
42
+ end
43
+
44
+ it 'when command attempts to return a key that doesnt exist' do
35
45
  expect {
36
- NoExecuteDefinedCommand.new.execute
37
- }.to raise_error(
38
- SimpleService::ExecuteNotDefinedError,
39
- 'NoExecuteDefinedCommand - does not define an execute method'
40
- )
46
+ InvalidReturnCommand.new.call
47
+ }.to raise_error(SimpleService::ReturnKeyError)
41
48
  end
42
49
 
43
50
  end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleService::ValidatesCommandsNotEmpty do
4
+
5
+ class DummyCommand < SimpleService::Command
6
+ def call; true; end
7
+ end
8
+
9
+ context '#call' do
10
+
11
+ it 'raises error when commands are not defined' do
12
+ expect {
13
+ SimpleService::ValidatesCommandsNotEmpty.new(provided_commands: nil).call
14
+ }.to raise_error(
15
+ SimpleService::OrganizerCommandsNotDefinedError,
16
+ 'This Organizer class does not contain any command definitions'
17
+ )
18
+ end
19
+
20
+ it 'does not raise error when commands are defined' do
21
+ expect {
22
+ SimpleService::ValidatesCommandsNotEmpty.new(provided_commands: [DummyCommand]).call
23
+ }.to_not raise_error
24
+ end
25
+
26
+ end
27
+
28
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleService::ValidatesCommandsProperlyInherit do
4
+
5
+ class ValidDummyCommand < SimpleService::Command
6
+ def call; true; end
7
+ end
8
+
9
+ class InvalidDummyCommand
10
+ def call; true; end
11
+ end
12
+
13
+ context '#call' do
14
+ it 'raises error when commands do not inherit from SimpleService::Command' do
15
+ expect {
16
+ SimpleService::ValidatesCommandsProperlyInherit.new(
17
+ provided_commands: [InvalidDummyCommand]
18
+ ).call
19
+ }.to raise_error(
20
+ SimpleService::CommandParentClassInvalidError,
21
+ 'InvalidDummyCommand - must inherit from SimpleService::Command'
22
+ )
23
+ end
24
+
25
+ it 'does not raises error when commands inherit from SimpleService::Command' do
26
+ expect {
27
+ SimpleService::ValidatesCommandsProperlyInherit.new(
28
+ provided_commands: [ValidDummyCommand]
29
+ ).call
30
+ }.to_not raise_error
31
+ end
32
+ end
33
+
34
+ end
@@ -0,0 +1,60 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleService::ValidatesExpectedKeys do
4
+
5
+ let(:valid_keys) {{
6
+ expected_keys: [:foo],
7
+ provided_keys: [:foo],
8
+ some_other_key: 'blah'
9
+ }}
10
+
11
+ context '#call' do
12
+
13
+ let(:with_valid_keys) {
14
+ SimpleService::ValidatesExpectedKeys.new(valid_keys)
15
+ }
16
+
17
+ let(:with_missing_keys) {
18
+ _keys = valid_keys.merge(expected_keys: [:foo, :baz])
19
+ SimpleService::ValidatesExpectedKeys.new(_keys)
20
+ }
21
+
22
+ let(:does_not_expect_any_keys) {
23
+ _keys = valid_keys.merge(expected_keys: [])
24
+ SimpleService::ValidatesExpectedKeys.new(_keys)
25
+ }
26
+
27
+ context 'when all arguments are valid' do
28
+
29
+ it 'does not raise error' do
30
+ expect {
31
+ with_valid_keys.call
32
+ }.to_not raise_error
33
+ end
34
+
35
+ end
36
+
37
+ context 'when there are expected keys missing from provided keys' do
38
+
39
+ it 'raises an error' do
40
+ expect { with_missing_keys.call }.to raise_error(
41
+ SimpleService::ExpectedKeyError,
42
+ 'keys required by the organizer but not found in the context: baz'
43
+ )
44
+ end
45
+
46
+ end
47
+
48
+ context 'no expected keys are given' do
49
+
50
+ it 'does not raise error' do
51
+ expect {
52
+ does_not_expect_any_keys.call
53
+ }.to_not raise_error
54
+ end
55
+
56
+ end
57
+
58
+ end
59
+
60
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleService::EnsureOrganizerIsValid do
4
+
5
+ context '#call' do
6
+
7
+ class FooCommand < SimpleService::Command
8
+ def call; true; end
9
+ end
10
+
11
+ class BadInheritanceCommand
12
+ def call; true; end
13
+ end
14
+
15
+ end
16
+
17
+ end
@@ -7,7 +7,7 @@ describe SimpleService::Organizer do
7
7
  class TestCommandOne < SimpleService::Command
8
8
  expects :foo
9
9
  returns :foo, :bar
10
- def execute
10
+ def call
11
11
  context.merge!(bar: 'bar')
12
12
  end
13
13
  end
@@ -15,7 +15,7 @@ describe SimpleService::Organizer do
15
15
  class TestCommandTwo < SimpleService::Command
16
16
  expects :foo, :bar
17
17
  returns :foo, :bar, :baz
18
- def execute
18
+ def call
19
19
  context.merge!(baz: 'baz')
20
20
  end
21
21
  end
@@ -26,10 +26,10 @@ describe SimpleService::Organizer do
26
26
  commands TestCommandOne, TestCommandTwo
27
27
  end
28
28
 
29
- describe '#execute' do
29
+ describe '#call' do
30
30
  it 'returns the correct hash' do
31
31
  expect(
32
- TestOrganizer.new(foo: 'foo').execute
32
+ TestOrganizer.new(foo: 'foo').call
33
33
  ).to eql(foo: 'foo', bar: 'bar', baz: 'baz')
34
34
  end
35
35
 
@@ -41,14 +41,14 @@ describe SimpleService::Organizer do
41
41
 
42
42
  class TestCommandThree < SimpleService::Command
43
43
  expects :foo
44
- def execute
44
+ def call
45
45
  context.merge!(bar: 'bar')
46
46
  end
47
47
  end
48
48
 
49
49
  class TestCommandFour < SimpleService::Command
50
50
  expects :foo, :bar
51
- def execute
51
+ def call
52
52
  context.merge!(baz: 'baz')
53
53
  end
54
54
  end
@@ -58,10 +58,10 @@ describe SimpleService::Organizer do
58
58
  commands TestCommandThree, TestCommandFour
59
59
  end
60
60
 
61
- describe '#execute' do
61
+ describe '#call' do
62
62
  it 'returns the entire context' do
63
63
  expect(
64
- TestOrganizerTwo.new(foo: 'foo', extra: 'extra').execute
64
+ TestOrganizerTwo.new(foo: 'foo', extra: 'extra').call
65
65
  ).to eql(foo: 'foo', bar: 'bar', baz: 'baz', extra: 'extra')
66
66
  end
67
67
 
@@ -74,7 +74,7 @@ describe SimpleService::Organizer do
74
74
  class GetterSetterCommand < SimpleService::Command
75
75
  expects :foo, :bar
76
76
  returns :baz
77
- def execute
77
+ def call
78
78
  self.baz = self.foo
79
79
  end
80
80
  end
@@ -87,7 +87,7 @@ describe SimpleService::Organizer do
87
87
 
88
88
  it 'returns the correct hash' do
89
89
  expect(
90
- GetterSetterOrganizer.new(foo: 'baz', bar: 'bar').execute
90
+ GetterSetterOrganizer.new(foo: 'baz', bar: 'bar').call
91
91
  ).to eql({ baz: 'baz' })
92
92
  end
93
93
 
metadata CHANGED
@@ -1,83 +1,83 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple_service
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jarrod Spillers
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-05 00:00:00.000000000 Z
11
+ date: 2015-04-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.3'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.3'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: 10.4.2
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: 10.4.2
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ~>
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
47
  version: 3.2.0
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ~>
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: 3.2.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: pry
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ~>
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
61
  version: 0.10.1
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ~>
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: 0.10.1
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: codeclimate-test-reporter
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - '>='
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - '>='
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  description: A minimal service object composer with support for individual commands
@@ -88,25 +88,34 @@ executables: []
88
88
  extensions: []
89
89
  extra_rdoc_files: []
90
90
  files:
91
- - .gitignore
92
- - .rspec
93
- - .travis.yml
91
+ - ".gitignore"
92
+ - ".rspec"
93
+ - ".travis.yml"
94
94
  - Gemfile
95
95
  - LICENSE
96
96
  - LICENSE.txt
97
97
  - README.md
98
98
  - Rakefile
99
99
  - example/hello_world.rb
100
+ - example/nested_organizer.rb
101
+ - example/nested_services.rb
102
+ - example/override_organizer_call_method.rb
100
103
  - lib/simple_service.rb
101
- - lib/simple_service/argument_validator.rb
102
104
  - lib/simple_service/command.rb
105
+ - lib/simple_service/commands/validates_commands_not_empty.rb
106
+ - lib/simple_service/commands/validates_commands_properly_inherit.rb
107
+ - lib/simple_service/commands/validates_expected_keys.rb
108
+ - lib/simple_service/ensure_organizer_is_valid.rb
103
109
  - lib/simple_service/exceptions.rb
104
110
  - lib/simple_service/organizer.rb
105
111
  - lib/simple_service/service_base.rb
106
112
  - lib/simple_service/version.rb
107
113
  - simple_service.gemspec
108
- - spec/lib/argument_validator_spec.rb
109
114
  - spec/lib/command_spec.rb
115
+ - spec/lib/commands/validates_commands_not_empty_spec.rb
116
+ - spec/lib/commands/validates_commands_properly_inherit_spec.rb
117
+ - spec/lib/commands/validates_expected_keys_spec.rb
118
+ - spec/lib/ensure_organizer_is_valid_spec.rb
110
119
  - spec/lib/organizer_spec.rb
111
120
  - spec/simple_service_spec.rb
112
121
  - spec/spec_helper.rb
@@ -120,24 +129,27 @@ require_paths:
120
129
  - lib
121
130
  required_ruby_version: !ruby/object:Gem::Requirement
122
131
  requirements:
123
- - - '>='
132
+ - - ">="
124
133
  - !ruby/object:Gem::Version
125
134
  version: '0'
126
135
  required_rubygems_version: !ruby/object:Gem::Requirement
127
136
  requirements:
128
- - - '>='
137
+ - - ">="
129
138
  - !ruby/object:Gem::Version
130
139
  version: '0'
131
140
  requirements: []
132
141
  rubyforge_project:
133
- rubygems_version: 2.4.2
142
+ rubygems_version: 2.4.5
134
143
  signing_key:
135
144
  specification_version: 4
136
145
  summary: A minimal service object composer with support for individual commands and
137
146
  top level organizer objects
138
147
  test_files:
139
- - spec/lib/argument_validator_spec.rb
140
148
  - spec/lib/command_spec.rb
149
+ - spec/lib/commands/validates_commands_not_empty_spec.rb
150
+ - spec/lib/commands/validates_commands_properly_inherit_spec.rb
151
+ - spec/lib/commands/validates_expected_keys_spec.rb
152
+ - spec/lib/ensure_organizer_is_valid_spec.rb
141
153
  - spec/lib/organizer_spec.rb
142
154
  - spec/simple_service_spec.rb
143
155
  - spec/spec_helper.rb
@@ -1,57 +0,0 @@
1
- module SimpleService
2
- class ArgumentValidator
3
-
4
- attr_accessor :context, :expects, :commands
5
-
6
- def initialize(opts)
7
- @context = opts[:context]
8
- @expects = opts[:expects]
9
- @commands = opts[:commands]
10
- end
11
-
12
- def execute
13
- validate_expected_arguments
14
- validate_commands_not_empty
15
- validate_commands_properly_inherit
16
- true
17
- end
18
-
19
- private
20
-
21
- def validate_expected_arguments
22
- arguments_not_included = []
23
-
24
- expects.each do |expected_arg|
25
- arguments_not_included << expected_arg unless context.has_key?(expected_arg)
26
- end
27
-
28
- if arguments_not_included.any?
29
- error_msg = 'keys required by the organizer but not found in the context: ' +
30
- arguments_not_included.join(', ')
31
- raise ExpectedKeyError, error_msg
32
- end
33
- end
34
-
35
- def validate_commands_not_empty
36
- if commands.nil? || commands.empty?
37
- error_msg = 'This Organizer class does not contain any command definitions'
38
- raise SimpleService::OrganizerCommandsNotDefinedError, error_msg
39
- end
40
-
41
- end
42
-
43
- def validate_commands_properly_inherit
44
- invalid_command_inherit = commands.select do |command|
45
- # does the command class inherit from SimpleService::Command
46
- !(command.ancestors.include?(SimpleService::Command))
47
- end
48
-
49
- if invalid_command_inherit.any?
50
- error_msg = invalid_command_inherit.join(', ') +
51
- ' - must inherit from SimpleService::Command'
52
- raise SimpleService::CommandParentClassInvalidError, error_msg
53
- end
54
- end
55
-
56
- end
57
- end
@@ -1,70 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe SimpleService::ArgumentValidator do
4
-
5
- context 'execute' do
6
-
7
- class FooCommand < SimpleService::Command
8
- def execute; true; end
9
- end
10
-
11
- class BadInheritanceCommand
12
- def execute; true; end
13
- end
14
-
15
- let(:valid_args) {{
16
- context: { foo: 'bar'},
17
- expects: [:foo],
18
- returns: [:foo],
19
- commands: [FooCommand]
20
- }}
21
-
22
- context 'when all arguments are valid' do
23
-
24
- it 'does not raise error' do
25
- expect {
26
- SimpleService::ArgumentValidator.new(valid_args).execute
27
- }.to_not raise_error
28
- end
29
-
30
- it 'returns true' do
31
- expect(
32
- SimpleService::ArgumentValidator.new(valid_args).execute
33
- ).to eql true
34
- end
35
-
36
- end
37
-
38
- it 'raises error when context does not contain expected keys' do
39
- expect {
40
- args = valid_args.merge(expects: [:baz])
41
- SimpleService::ArgumentValidator.new(args).execute
42
- }.to raise_error(
43
- SimpleService::ExpectedKeyError,
44
- 'keys required by the organizer but not found in the context: baz'
45
- )
46
- end
47
-
48
- it 'raises error when commands are not defined' do
49
- expect {
50
- args = valid_args.merge(commands: nil)
51
- SimpleService::ArgumentValidator.new(args).execute
52
- }.to raise_error(
53
- SimpleService::OrganizerCommandsNotDefinedError,
54
- 'This Organizer class does not contain any command definitions'
55
- )
56
- end
57
-
58
- it 'raises error when commands do not inherit from SimpleService::Command' do
59
- expect {
60
- args = valid_args.merge(commands: [BadInheritanceCommand])
61
- SimpleService::ArgumentValidator.new(args).execute
62
- }.to raise_error(
63
- SimpleService::CommandParentClassInvalidError,
64
- 'BadInheritanceCommand - must inherit from SimpleService::Command'
65
- )
66
- end
67
-
68
- end
69
-
70
- end