simple_service 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: af47217423dfde7e55b44539cb67335bf973e827
4
+ data.tar.gz: 6f6955116fc1de25feb69748943bbd693f032fe1
5
+ SHA512:
6
+ metadata.gz: a29bd75670cad144a923b95738dc20966cd2af9c5c777ee64603f7b498d16ac948e4ed0f1003cd2e15a4dc4d0d9e34c9f03a2782fdb2fb02876d973efb80a4a4
7
+ data.tar.gz: 078d232dc698930fec97d656566edce4d29007e144849f03d14c263e0f0a220eb487525bd3e37f9d0822c2daa2dbe4965b46136f60dc6ccdbb044564a0c1ceae
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --format progress
3
+ --order rand
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - jruby-19mode
5
+ - rbx
6
+ - 2.0.0
7
+ - 2.1.0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in simple_service.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Jarrod Spillers
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Jrod
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,139 @@
1
+ # SimpleService
2
+
3
+ [![Code Climate](https://codeclimate.com/github/jspillers/simple_service/badges/gpa.svg)](https://codeclimate.com/github/jspillers/simple_service)
4
+ [![Test Coverage](https://codeclimate.com/github/jspillers/simple_service/badges/coverage.svg)](https://codeclimate.com/github/jspillers/simple_service)
5
+ [![Build Status](https://travis-ci.org/jspillers/simple_service.svg?branch=master)](https://travis-ci.org/jspillers/simple_service)
6
+
7
+ SimpleService gives you a way to organize service objects such that they adhere
8
+ to the single responsibility principle. Instead of writing large service objects
9
+ that perform multiple tasks, SimpleService allows you to breakdown tasks into a
10
+ set a sequentially performed Command objects. When properly designed, these command
11
+ objects can be reused in multiple different organizers minimizing code duplication.
12
+
13
+ When an organizer is instantiated a hash of arguments is passed in. This hash
14
+ is referred to as the context. The context hash is carried along throughout
15
+ the sequence of command executions and modified by each command. After a
16
+ successful run, the entire context hash (or a specified subset) is returned.
17
+
18
+ First, setup an Organizer class. An Organizer needs the following things defined:
19
+
20
+ * expects: keys that are required to be passed into initialize when an instance
21
+ of organizer is created. If not defined the organizer will accept arbitrary arguments.
22
+ * returns: keys that will be returned when the organizer has executed all of its commands
23
+ * commands: classes that define all the steps that the organizer will execute. The organizer
24
+ will call #execute on each command in order and the context hash is passed to each of
25
+ these commands. Any keys within the context that are modified will be merged back into
26
+ the organizer and passed along to the next command.
27
+
28
+ ```ruby
29
+ class ProcessSomethingComplex < SimpleService::Organizer
30
+
31
+ # optional - ensures the following keys are provided during instantiation
32
+ # leave out to accept any arguments/keys
33
+ expects :something, :another_thing
34
+
35
+ # optional - specifies which keys get returned after #execute is called on
36
+ # an organizer instance
37
+ returns :modified_thing
38
+
39
+ # what steps comprise this service
40
+ # #execute will be called on an instance of each class in sequence
41
+ commands DoSomethingImportant, DoAnotherStep
42
+
43
+ end
44
+ ```
45
+
46
+ Next, define all command classes that make up the service. Each should inherit
47
+ from SimpleService::Command and define similar things to the organizer:
48
+
49
+ ```ruby
50
+ class DoSomethingImportant < SimpleService::Command
51
+
52
+ # optional - creates getter/setter for each key specified,
53
+ # leave blank to accept arbitrary args
54
+ expects :something
55
+
56
+ # optional - creates getter/setter for each key specified,
57
+ # leave blank to return entire context hash
58
+ returns :modified_something, :another_thing
59
+
60
+ # required - this is where the work gets done, should only
61
+ # do one thing (single responsibility principle)
62
+ # getters and setters are available for each key specified
63
+ # in expects and returns. If not using expects and returns
64
+ # simply interact with the context hash directly
65
+ def execute
66
+ # uses getters and setters to modify the context
67
+ self.modified_something = self.something.to_i + 1
68
+
69
+ # or act directly on the context hash
70
+ context[:modified_something] = context[:something].to_i + 1
71
+
72
+ # no need to return anything specific, either the keys
73
+ # specified in returns will be returned or the entire
74
+ # context if no returns are defined
75
+ end
76
+
77
+ end
78
+
79
+ class DoSomethingImportant < SimpleService::Command
80
+ ...
81
+ end
82
+ ```
83
+
84
+ ## Usage
85
+
86
+ Using the service is straight forward - just instantiate it, passing in the
87
+ intial context hash, and then call execute.
88
+
89
+ ```ruby
90
+ starting_context = {
91
+ something: '1',
92
+ :another_thing: AnotherThing.new
93
+ }
94
+ modified_context = ProcessSomethingComplex.new(starting_context).execute
95
+
96
+ modified_context[:modified_thing] # => 2
97
+ ```
98
+
99
+ If you are using this with a Rails app, placing top level services in
100
+ app/services/ and all commands in app/services/commands/ is recommended. If
101
+ not using rails, a similar structure would also be recommended.
102
+
103
+ ## Inspiration and Rationale
104
+
105
+ This gem is heavily inspired by two very nice gems: [mutations](https://github.com/cypriss/mutations) and
106
+ [light-service](https://github.com/adomokos/light-service).
107
+
108
+ Mutations is a great gem, but lacks the concept of a top level organizer.
109
+ LightService brings in the notion of the organizer object, but doesn't create
110
+ instances of its action objects (what are referred to as commands here). Using
111
+ instances rather than class level execute definitions allows the use of private
112
+ methods within the command for more complex commands that still do a single thing.
113
+
114
+ The other goal of this gem is to do as little as possible above and beyond
115
+ just using plain old Ruby objects (PORO's). Things like error handling, logging,
116
+ and context status will be left up to the individual to implement in a way that
117
+ best suits their use case.
118
+
119
+ ## Installation
120
+
121
+ Add this line to your application's Gemfile:
122
+
123
+ gem 'simple_service'
124
+
125
+ And then execute:
126
+
127
+ $ bundle
128
+
129
+ Or install it yourself as:
130
+
131
+ $ gem install simple_service
132
+
133
+ ## Contributing
134
+
135
+ 1. Fork it
136
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
137
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
138
+ 4. Push to the branch (`git push origin my-new-feature`)
139
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ begin
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task :default => :spec
9
+ rescue LoadError
10
+ # no rspec available
11
+ end
@@ -0,0 +1,30 @@
1
+ require 'rubygems'
2
+ require 'pry'
3
+ require 'simple_service'
4
+
5
+ class ConcatName < SimpleService::Command
6
+ expects :first_name, :last_name
7
+ returns :name
8
+
9
+ def execute
10
+ self.name = "#{first_name} #{last_name}"
11
+ end
12
+ end
13
+
14
+ class CreateHelloString < SimpleService::Command
15
+ expects :name
16
+ returns :hello
17
+
18
+ def execute
19
+ self.hello = "#{name}, say hello world!"
20
+ end
21
+ end
22
+
23
+ class SayHello < SimpleService::Organizer
24
+ expects :first_name, :last_name
25
+ returns :hello
26
+ commands ConcatName, CreateHelloString
27
+ end
28
+
29
+ result = SayHello.new(first_name: 'Ruby', last_name: 'Gem').execute
30
+ puts result[:hello]
@@ -0,0 +1,57 @@
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
@@ -0,0 +1,48 @@
1
+ module SimpleService
2
+ class Command
3
+
4
+ include ServiceBase::InstanceMethods
5
+ extend ServiceBase::ClassMethods
6
+
7
+ attr_accessor :context
8
+
9
+ def initialize(context={})
10
+ @context = context
11
+ setup_execute_chain
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
+
25
+ def all_specified_context_keys
26
+ (expects + returns)
27
+ end
28
+
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
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,8 @@
1
+ module SimpleService
2
+
3
+ class OrganizerCommandsNotDefinedError < StandardError; end;
4
+ class CommandParentClassInvalidError < StandardError; end;
5
+ class ExpectedKeyError < StandardError; end;
6
+ class ExecuteNotDefinedError < StandardError; end;
7
+ class ReturnKeyError < StandardError; end;
8
+ end
@@ -0,0 +1,38 @@
1
+ module SimpleService
2
+ class Organizer
3
+
4
+ include ServiceBase::InstanceMethods
5
+ extend ServiceBase::ClassMethods
6
+
7
+ attr_accessor :context
8
+
9
+ def initialize(context={})
10
+ @context = context
11
+
12
+ ArgumentValidator.new(
13
+ context: context,
14
+ expects: expects,
15
+ returns: returns,
16
+ commands: commands
17
+ ).execute
18
+
19
+ setup_execute_chain
20
+ end
21
+
22
+ def self.commands(*args)
23
+ @commands = args
24
+ end
25
+
26
+ def commands
27
+ self.class.instance_variable_get('@commands')
28
+ end
29
+
30
+ def execute
31
+ commands.each do |command|
32
+ @context.merge!(command.new(context).execute)
33
+ end
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -0,0 +1,60 @@
1
+ module SimpleService
2
+ module ServiceBase
3
+
4
+ module ClassMethods
5
+ def expects(*args)
6
+ @expects = args
7
+ end
8
+
9
+ def returns(*args)
10
+ @returns = args
11
+ end
12
+ end
13
+
14
+ module InstanceMethods
15
+
16
+ def setup_execute_chain
17
+ self.class.class_eval do
18
+
19
+ # grab the method object and hold onto it here
20
+ execute_method = instance_method(:execute)
21
+
22
+ # redefine the execute method, call the existing execute method object,
23
+ # and then run return key checking... allows user to implement execute in
24
+ # their individual command classes without having to call super or any
25
+ # other method to return only specific context keys
26
+ define_method :execute do
27
+ execute_method.bind(self).call
28
+ find_specified_return_keys
29
+ end
30
+ end
31
+ end
32
+
33
+ def find_specified_return_keys
34
+ if returns.nil? || returns.empty?
35
+ context
36
+ else
37
+ returns.inject({}) do |to_return, return_param|
38
+ if context.has_key?(return_param)
39
+ to_return[return_param] = context[return_param]
40
+ else
41
+ error_msg = "#{self.class} tried to return #{return_param}, but it did not exist in the context: #{context.inspect}"
42
+ raise ReturnKeyError, error_msg
43
+ end
44
+
45
+ to_return
46
+ end
47
+ end
48
+ end
49
+
50
+ def expects
51
+ self.class.instance_variable_get('@expects') || []
52
+ end
53
+
54
+ def returns
55
+ self.class.instance_variable_get('@returns') || []
56
+ end
57
+ end
58
+
59
+ end
60
+ end
@@ -0,0 +1,3 @@
1
+ module SimpleService
2
+ VERSION = '1.0.1'
3
+ end
@@ -0,0 +1,10 @@
1
+ require 'simple_service/service_base'
2
+ require 'simple_service/argument_validator'
3
+ require 'simple_service/command'
4
+ require 'simple_service/exceptions'
5
+ require 'simple_service/organizer'
6
+ require 'simple_service/version'
7
+
8
+ module SimpleService
9
+ # Your code goes here...
10
+ end
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'simple_service/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'simple_service'
8
+ spec.version = SimpleService::VERSION
9
+ spec.authors = ['Jarrod Spillers']
10
+ spec.email = ['jarrod@stacktact.com']
11
+ spec.description = %q{A minimal service object composer with support for individual commands and top level organizer objects}
12
+ spec.summary = spec.description
13
+ spec.homepage = 'https://github.com/jspillers/simple_service'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_development_dependency 'bundler', '~> 1.3'
22
+ spec.add_development_dependency 'rake', '~> 10.4.2'
23
+ spec.add_development_dependency 'rspec', '~> 3.2.0'
24
+ spec.add_development_dependency 'pry', '~> 0.10.1'
25
+ spec.add_development_dependency 'codeclimate-test-reporter'
26
+ end
@@ -0,0 +1,70 @@
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
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleService::Command do
4
+
5
+ class ValidCommand < SimpleService::Command
6
+
7
+ expects :foo, :bar
8
+ returns :bar, :baz
9
+
10
+ def execute
11
+ context.merge!(
12
+ bar: 'modified',
13
+ baz: 'blah'
14
+ )
15
+ end
16
+
17
+ end
18
+
19
+ class NoExecuteDefinedCommand < SimpleService::Command
20
+ end
21
+
22
+ describe '#execute' do
23
+
24
+ context 'when #returns is not empty' do
25
+ it 'returns the correct keys from the context' do
26
+ expect(
27
+ ValidCommand.new(foo: 'blah', bar: 'meh').execute
28
+ ).to eql(bar: 'modified', baz: 'blah')
29
+ end
30
+ end
31
+
32
+ context 'raises error' do
33
+
34
+ it 'when command does not define an execute method' do
35
+ expect {
36
+ NoExecuteDefinedCommand.new.execute
37
+ }.to raise_error(
38
+ SimpleService::ExecuteNotDefinedError,
39
+ 'NoExecuteDefinedCommand - does not define an execute method'
40
+ )
41
+ end
42
+
43
+ end
44
+
45
+ end
46
+
47
+ describe 'context' do
48
+
49
+ it 'defines getters for each expected key' do
50
+ expect(
51
+ ValidCommand.new(foo: 'blah', bar: 'meh')
52
+ ).to respond_to :foo
53
+ end
54
+
55
+ it 'defines setters for each expected key' do
56
+ command = ValidCommand.new(foo: 'blah', bar: 'meh')
57
+ command.foo = 'changed'
58
+ command.bar = 'changed'
59
+
60
+ expect(command.context).to eql({ foo: 'changed', bar: 'changed' })
61
+ end
62
+
63
+ it 'getter updates @context' do
64
+ command = ValidCommand.new(foo: 'blah', bar: 'meh')
65
+ command.foo = 'changed'
66
+ expect(command.context).to eql({ foo: 'changed', bar: 'meh'})
67
+ end
68
+
69
+ end
70
+
71
+ end
@@ -0,0 +1,96 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleService::Organizer do
4
+
5
+ context 'classes with expects and returns' do
6
+
7
+ class TestCommandOne < SimpleService::Command
8
+ expects :foo
9
+ returns :foo, :bar
10
+ def execute
11
+ context.merge!(bar: 'bar')
12
+ end
13
+ end
14
+
15
+ class TestCommandTwo < SimpleService::Command
16
+ expects :foo, :bar
17
+ returns :foo, :bar, :baz
18
+ def execute
19
+ context.merge!(baz: 'baz')
20
+ end
21
+ end
22
+
23
+ class TestOrganizer < SimpleService::Organizer
24
+ expects :foo
25
+ returns :foo, :bar, :baz
26
+ commands TestCommandOne, TestCommandTwo
27
+ end
28
+
29
+ describe '#execute' do
30
+ it 'returns the correct hash' do
31
+ expect(
32
+ TestOrganizer.new(foo: 'foo').execute
33
+ ).to eql(foo: 'foo', bar: 'bar', baz: 'baz')
34
+ end
35
+
36
+ end
37
+
38
+ end
39
+
40
+ context 'classes with only expects' do
41
+
42
+ class TestCommandThree < SimpleService::Command
43
+ expects :foo
44
+ def execute
45
+ context.merge!(bar: 'bar')
46
+ end
47
+ end
48
+
49
+ class TestCommandFour < SimpleService::Command
50
+ expects :foo, :bar
51
+ def execute
52
+ context.merge!(baz: 'baz')
53
+ end
54
+ end
55
+
56
+ class TestOrganizerTwo < SimpleService::Organizer
57
+ expects :foo
58
+ commands TestCommandThree, TestCommandFour
59
+ end
60
+
61
+ describe '#execute' do
62
+ it 'returns the entire context' do
63
+ expect(
64
+ TestOrganizerTwo.new(foo: 'foo', extra: 'extra').execute
65
+ ).to eql(foo: 'foo', bar: 'bar', baz: 'baz', extra: 'extra')
66
+ end
67
+
68
+ end
69
+
70
+ end
71
+
72
+ describe 'service using getters and setters' do
73
+
74
+ class GetterSetterCommand < SimpleService::Command
75
+ expects :foo, :bar
76
+ returns :baz
77
+ def execute
78
+ self.baz = self.foo
79
+ end
80
+ end
81
+
82
+ class GetterSetterOrganizer < SimpleService::Organizer
83
+ expects :foo, :bar
84
+ returns :baz
85
+ commands GetterSetterCommand
86
+ end
87
+
88
+ it 'returns the correct hash' do
89
+ expect(
90
+ GetterSetterOrganizer.new(foo: 'baz', bar: 'bar').execute
91
+ ).to eql({ baz: 'baz' })
92
+ end
93
+
94
+ end
95
+
96
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleService do
4
+
5
+ end
@@ -0,0 +1,10 @@
1
+ $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib', 'simple_service')
2
+ $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
3
+ $LOAD_PATH << File.join(File.dirname(__FILE__))
4
+
5
+ require 'codeclimate-test-reporter'
6
+ CodeClimate::TestReporter.start
7
+
8
+ require 'pry'
9
+ require 'rspec'
10
+ require 'simple_service'
metadata ADDED
@@ -0,0 +1,143 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: simple_service
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jarrod Spillers
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-04-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: 10.4.2
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: 10.4.2
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: 3.2.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 3.2.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 0.10.1
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: 0.10.1
69
+ - !ruby/object:Gem::Dependency
70
+ name: codeclimate-test-reporter
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: A minimal service object composer with support for individual commands
84
+ and top level organizer objects
85
+ email:
86
+ - jarrod@stacktact.com
87
+ executables: []
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - .gitignore
92
+ - .rspec
93
+ - .travis.yml
94
+ - Gemfile
95
+ - LICENSE
96
+ - LICENSE.txt
97
+ - README.md
98
+ - Rakefile
99
+ - example/hello_world.rb
100
+ - lib/simple_service.rb
101
+ - lib/simple_service/argument_validator.rb
102
+ - lib/simple_service/command.rb
103
+ - lib/simple_service/exceptions.rb
104
+ - lib/simple_service/organizer.rb
105
+ - lib/simple_service/service_base.rb
106
+ - lib/simple_service/version.rb
107
+ - simple_service.gemspec
108
+ - spec/lib/argument_validator_spec.rb
109
+ - spec/lib/command_spec.rb
110
+ - spec/lib/organizer_spec.rb
111
+ - spec/simple_service_spec.rb
112
+ - spec/spec_helper.rb
113
+ homepage: https://github.com/jspillers/simple_service
114
+ licenses:
115
+ - MIT
116
+ metadata: {}
117
+ post_install_message:
118
+ rdoc_options: []
119
+ require_paths:
120
+ - lib
121
+ required_ruby_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ required_rubygems_version: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - '>='
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ requirements: []
132
+ rubyforge_project:
133
+ rubygems_version: 2.4.2
134
+ signing_key:
135
+ specification_version: 4
136
+ summary: A minimal service object composer with support for individual commands and
137
+ top level organizer objects
138
+ test_files:
139
+ - spec/lib/argument_validator_spec.rb
140
+ - spec/lib/command_spec.rb
141
+ - spec/lib/organizer_spec.rb
142
+ - spec/simple_service_spec.rb
143
+ - spec/spec_helper.rb