simple_action 0.0.1.pre1

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.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MzUwZDEyY2UxMjMwMzZlZWE2ODg0MjMzMjUwZTJhYTIzZGE3ODM0Nw==
5
+ data.tar.gz: !binary |-
6
+ ZjE0MmM4ZmExM2FmZGQwOGVlNTI4ZTJkZTBhN2M3ZjQ4MzZkMjQ1Yw==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ NzAxYjQxMGQ2ZWEwNDMxZDAyMGFkMWUxYzZiMDkxNjUzYTZkODk5ZjBmMjRl
10
+ MjA1MDBmZWQyMjVkNjJlNTUwNWNmZWQ3Yzg3Zjg3MGM2ZjExY2JhNzM0ZDIw
11
+ ZDE5MDcxM2JkOGUyYjQwZGFjODFkZmQ5NTJlZjU5ZmQxMDY2NDM=
12
+ data.tar.gz: !binary |-
13
+ Nzg4ZjZjNWMzZDA2YjYyYWZkMTliNzEzZmI4NDllZmM4NjE1OTNlMGQyNDU0
14
+ MmY3NjE5MTcwM2E0NzE3ZTQwNmM3ZTc5NDAzM2IxYmRiZTRiMTk4N2FhYWVk
15
+ NmRiZDg5ZmMwZTMxZjg5ZmU1ZjZjYjg2ZDRhNGI3OTdlMWQzZWY=
data/.gitignore ADDED
@@ -0,0 +1,35 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /test/tmp/
9
+ /test/version_tmp/
10
+ /tmp/
11
+
12
+ ## Specific to RubyMotion:
13
+ .dat*
14
+ .repl_history
15
+ build/
16
+
17
+ ## Documentation cache and generated files:
18
+ /.yardoc/
19
+ /_yardoc/
20
+ /doc/
21
+ /rdoc/
22
+
23
+ ## Environment normalisation:
24
+ /.bundle/
25
+ /vendor/bundle
26
+ /lib/bundler/man/
27
+
28
+ # for a library or gem, you might want to ignore these files since the code is
29
+ # intended to run in multiple environments; otherwise, check them in:
30
+ # Gemfile.lock
31
+ # .ruby-version
32
+ # .ruby-gemset
33
+
34
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
35
+ .rvmrc
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --format progress
3
+ --warnings
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ simple_action_gem
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-1.9.3-p545
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,70 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ simple_action (0.0.1.pre1)
5
+ simple_params (>= 0.0.2.pre9, < 1.0)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activemodel (4.2.1)
11
+ activesupport (= 4.2.1)
12
+ builder (~> 3.1)
13
+ activesupport (4.2.1)
14
+ i18n (~> 0.7)
15
+ json (~> 1.7, >= 1.7.7)
16
+ minitest (~> 5.1)
17
+ thread_safe (~> 0.3, >= 0.3.4)
18
+ tzinfo (~> 1.1)
19
+ axiom-types (0.1.1)
20
+ descendants_tracker (~> 0.0.4)
21
+ ice_nine (~> 0.11.0)
22
+ thread_safe (~> 0.3, >= 0.3.1)
23
+ builder (3.2.2)
24
+ coderay (1.1.0)
25
+ coercible (1.0.0)
26
+ descendants_tracker (~> 0.0.1)
27
+ descendants_tracker (0.0.4)
28
+ thread_safe (~> 0.3, >= 0.3.1)
29
+ diff-lcs (1.2.5)
30
+ equalizer (0.0.11)
31
+ i18n (0.7.0)
32
+ ice_nine (0.11.1)
33
+ json (1.8.2)
34
+ method_source (0.8.2)
35
+ minitest (5.5.1)
36
+ pry (0.10.1)
37
+ coderay (~> 1.1.0)
38
+ method_source (~> 0.8.1)
39
+ slop (~> 3.4)
40
+ rake (10.4.2)
41
+ rspec (2.99.0)
42
+ rspec-core (~> 2.99.0)
43
+ rspec-expectations (~> 2.99.0)
44
+ rspec-mocks (~> 2.99.0)
45
+ rspec-core (2.99.2)
46
+ rspec-expectations (2.99.2)
47
+ diff-lcs (>= 1.1.3, < 2.0)
48
+ rspec-mocks (2.99.3)
49
+ simple_params (0.0.2.pre9)
50
+ activemodel (>= 3.0, < 5.0)
51
+ virtus (>= 1.0.0)
52
+ slop (3.6.0)
53
+ thread_safe (0.3.5)
54
+ tzinfo (1.2.2)
55
+ thread_safe (~> 0.1)
56
+ virtus (1.0.5)
57
+ axiom-types (~> 0.1)
58
+ coercible (~> 1.0)
59
+ descendants_tracker (~> 0.0, >= 0.0.3)
60
+ equalizer (~> 0.0, >= 0.0.9)
61
+
62
+ PLATFORMS
63
+ ruby
64
+
65
+ DEPENDENCIES
66
+ bundler (~> 1.5)
67
+ pry
68
+ rake (~> 10.1)
69
+ rspec (~> 2.6)
70
+ simple_action!
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Bryce Senz
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/README.md ADDED
@@ -0,0 +1,2 @@
1
+ # simple_action
2
+ A simple Service Object class for internal services, API endpoints, etc.
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ require 'active_model'
3
+
4
+ module SimpleAction
5
+ module AcceptsParams
6
+ extend ActiveSupport::Concern
7
+
8
+ attr_accessor :params_class
9
+
10
+ def params(&block)
11
+ @params_class = Class.new(Params).tap do |klass|
12
+ name_function = Proc.new {
13
+ def self.model_name
14
+ ActiveModel::Name.new(self, self, "Params")
15
+ end
16
+ }
17
+ klass.class_eval(&name_function)
18
+ klass.class_eval(&block)
19
+ end
20
+ end
21
+
22
+ def api_pie_documentation
23
+ @params_class.api_pie_documentation
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ require 'active_model'
3
+
4
+ module SimpleAction
5
+ module DelegatesToParams
6
+ extend ActiveSupport::Concern
7
+
8
+ def respond_to?(sym, include_private = false)
9
+ pass_sym_to_params?(sym) || super(sym, include_private)
10
+ end
11
+
12
+ def method_missing(sym, *args, &block)
13
+ return params.send(sym, *args, &block) if pass_sym_to_params?(sym)
14
+ super(sym, *args, &block)
15
+ end
16
+
17
+ private
18
+ def pass_sym_to_params?(sym)
19
+ params.present? &&
20
+ params_accessor?(sym) &&
21
+ params.respond_to?(sym)
22
+ end
23
+
24
+ def params_accessor?(sym)
25
+ stripped = sym.to_s.gsub('=', '').to_sym
26
+ params.attributes.include?(stripped)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,45 @@
1
+ # coding: utf-8
2
+
3
+ begin
4
+ require 'active_record'
5
+ rescue LoadError
6
+ module ActiveRecord
7
+ Rollback = Class.new(SimpleAction::Error)
8
+
9
+ class Base
10
+ def self.transaction(*)
11
+ yield
12
+ rescue Rollback
13
+ end
14
+ end
15
+ end
16
+ end
17
+
18
+ module SimpleAction
19
+ module Transactable
20
+ extend ActiveSupport::Concern
21
+
22
+ # @yield []
23
+ def transaction
24
+ return unless block_given?
25
+
26
+ if transaction?
27
+ ActiveRecord::Base.transaction(transaction_options) do
28
+ yield
29
+ end
30
+ else
31
+ yield
32
+ end
33
+ end
34
+
35
+ # @return [Boolean]
36
+ def transaction?
37
+ true
38
+ end
39
+
40
+ # @return [Hash]
41
+ def transaction_options
42
+ {}
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,10 @@
1
+ module SimpleAction
2
+ class Error < StandardError
3
+ end
4
+
5
+ class ImplementationError < Error
6
+ end
7
+
8
+ class ExecutionError < Error
9
+ end
10
+ end
@@ -0,0 +1,6 @@
1
+ require 'simple_params'
2
+
3
+ module SimpleAction
4
+ class Params < ::SimpleParams::Params
5
+ end
6
+ end
@@ -0,0 +1,25 @@
1
+ module SimpleAction
2
+ class Response
3
+ def initialize(service_object, result = nil)
4
+ @service_object = service_object
5
+ @result = result
6
+ valid?
7
+ end
8
+
9
+ def valid?
10
+ @service_object.valid?
11
+ end
12
+
13
+ def errors
14
+ @service_object.errors
15
+ end
16
+
17
+ def success?
18
+ valid?
19
+ end
20
+
21
+ def result
22
+ @result
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,51 @@
1
+ require_relative 'concerns/accepts_params'
2
+ require_relative 'concerns/transactable'
3
+ require_relative 'concerns/delegates_to_params'
4
+
5
+ module SimpleAction
6
+ class Service
7
+ extend AcceptsParams
8
+ extend Transactable
9
+ include DelegatesToParams
10
+
11
+ class << self
12
+ def run(params = {})
13
+ instance = self.new(params)
14
+ result = transaction do
15
+ instance.execute if instance.valid?
16
+ end
17
+ Response.new(instance, result)
18
+ end
19
+
20
+ def run!(params = {})
21
+ response = run(params)
22
+ if response.valid?
23
+ response.result
24
+ else
25
+ raise ExecutionError, response.errors.to_s
26
+ end
27
+ end
28
+ end
29
+
30
+ def initialize(params={})
31
+ @raw_params = params
32
+ @params = self.class.params_class.new(params)
33
+ end
34
+
35
+ def params
36
+ @params
37
+ end
38
+
39
+ def valid?
40
+ @params.valid?
41
+ end
42
+
43
+ def errors
44
+ @params.errors
45
+ end
46
+
47
+ def execute
48
+ raise ImplementationError, "subclasses must implement 'execute' method."
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,3 @@
1
+ module SimpleAction
2
+ VERSION = "0.0.1.pre1"
3
+ end
@@ -0,0 +1,8 @@
1
+ require 'simple_action/version'
2
+ require 'simple_action/error'
3
+ require 'simple_action/params'
4
+ require 'simple_action/response'
5
+ require 'simple_action/service'
6
+ require 'simple_action/concerns/accepts_params'
7
+ require 'simple_action/concerns/transactable'
8
+ require 'simple_action/concerns/delegates_to_params'
@@ -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_action/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "simple_action"
8
+ spec.version = SimpleAction::VERSION
9
+ spec.authors = ["brycesenz"]
10
+ spec.email = ["bryce.senz@gmail.com"]
11
+ spec.description = %q{Simple Service Object class for services & API endpoints}
12
+ spec.summary = %q{A DSL for specifying services objects, including parameters and execution}
13
+ spec.homepage = "https://github.com/brycesenz/simple_action"
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_dependency "simple_params", ">= 0.0.2.pre9", "< 1.0"
22
+ spec.add_development_dependency "bundler", "~> 1.5"
23
+ spec.add_development_dependency "rake", "~> 10.1"
24
+ spec.add_development_dependency "rspec", "~> 2.6"
25
+ spec.add_development_dependency "pry"
26
+ end
@@ -0,0 +1,13 @@
1
+ require 'active_model'
2
+
3
+ class DummyServiceObjectClass
4
+ include ActiveModel::Validations
5
+
6
+ attr_accessor :name
7
+
8
+ def initialize(params = {})
9
+ params.each { |k, v| send("#{k}=", v) }
10
+ end
11
+
12
+ validates :name, presence: true
13
+ end
@@ -0,0 +1,13 @@
1
+ class ParamsSpecClass < SimpleAction::Params
2
+ param :reference, type: :object, optional: true
3
+ param :name
4
+ param :age, type: :integer, optional: true
5
+ param :color, default: "red", validations: { inclusion: { in: ["red", "green"] }}
6
+
7
+ nested_hash :address do
8
+ param :street
9
+ param :city, validations: { length: { in: 4..40 } }
10
+ param :zip_code, optional: true
11
+ param :state, default: "North Carolina"
12
+ end
13
+ end
@@ -0,0 +1,10 @@
1
+ class ServiceSpecClass < SimpleAction::Service
2
+ params do
3
+ param :name
4
+ param :age, type: :integer, default: 23
5
+ end
6
+
7
+ def execute
8
+ (age * 3) + name.length
9
+ end
10
+ end
@@ -0,0 +1,182 @@
1
+ require 'spec_helper'
2
+ require 'fixtures/params_spec_class'
3
+
4
+ describe SimpleAction::Params do
5
+ describe "original_params", original_params: true do
6
+ it "returns symbolized params hash" do
7
+ params = ParamsSpecClass.new(name: "Tom", address: { "street" => "1 Main St."} )
8
+ params.original_params.should eq({
9
+ name: "Tom",
10
+ address: {
11
+ street: "1 Main St."
12
+ }
13
+ })
14
+ end
15
+
16
+ it "returns symbolized params for nested_hash" do
17
+ params = ParamsSpecClass.new(name: "Tom", address: { "street" => "1 Main St."} )
18
+ params.address.original_params.should eq({
19
+ street: "1 Main St."
20
+ })
21
+ end
22
+ end
23
+
24
+ describe "accessors", accessors: true do
25
+ let(:params) { ParamsSpecClass.new }
26
+
27
+ it "has getter and setter methods for object param" do
28
+ params.should respond_to(:reference)
29
+ params.reference.should be_nil
30
+ new_object = OpenStruct.new(count: 4)
31
+ params.reference = new_object
32
+ params.reference.should eq(new_object)
33
+ end
34
+
35
+ it "has getter and setter methods for required param" do
36
+ params.should respond_to(:name)
37
+ params.name.should be_nil
38
+ params.name = "Tom"
39
+ params.name.should eq("Tom")
40
+ end
41
+
42
+ it "has getter and setter methods for optional param" do
43
+ params.should respond_to(:age)
44
+ params.name.should be_nil
45
+ params.age = 19
46
+ params.age.should eq(19)
47
+ end
48
+
49
+ describe "nested params", nested: true do
50
+ it "has getter and setter methods for required param" do
51
+ params.address.should respond_to(:street)
52
+ params.address.street.should be_nil
53
+ params.address.street = "1 Main St."
54
+ params.address.street.should eq("1 Main St.")
55
+ end
56
+
57
+ it "has getter and setter methods for optional param" do
58
+ params.address.should respond_to(:zip_code)
59
+ params.address.zip_code.should be_nil
60
+ params.address.zip_code = "20165"
61
+ params.address.zip_code.should eq("20165")
62
+ end
63
+ end
64
+ end
65
+
66
+ describe "attributes", attributes: true do
67
+ it "returns array of attribute symbols" do
68
+ params = ParamsSpecClass.new
69
+ params.attributes.should eq([:reference, :name, :age, :color, :address])
70
+ end
71
+ end
72
+
73
+ describe "array syntax", array_syntax: true do
74
+ let(:params) do
75
+ ParamsSpecClass.new(
76
+ name: "Bill",
77
+ age: 30,
78
+ address: {
79
+ city: "Greenville"
80
+ }
81
+ )
82
+ end
83
+
84
+ it "can access 'name' through array syntax" do
85
+ params[:name].should eq("Bill")
86
+ params["name"].should eq("Bill")
87
+ end
88
+
89
+ it "can set 'name' through array syntax" do
90
+ params[:name] = "Tom"
91
+ params[:name].should eq("Tom")
92
+ params["name"].should eq("Tom")
93
+ end
94
+
95
+ it "can access 'age' through array syntax" do
96
+ params[:age].should eq(30)
97
+ params["age"].should eq(30)
98
+ end
99
+
100
+ it "can set 'age' through array syntax" do
101
+ params[:age] = 42
102
+ params[:age].should eq(42)
103
+ params["age"].should eq(42)
104
+ end
105
+
106
+ describe "nested params", nested: true do
107
+ it "can access 'city' through array syntax" do
108
+ params[:address][:city].should eq("Greenville")
109
+ params["address"]["city"].should eq("Greenville")
110
+ end
111
+
112
+ it "can set 'city' through array syntax" do
113
+ params[:address][:city] = "Asheville"
114
+ params[:address][:city].should eq("Asheville")
115
+ params["address"]["city"].should eq("Asheville")
116
+ end
117
+ end
118
+ end
119
+
120
+ describe "validations", validations: true do
121
+ let(:params) { ParamsSpecClass.new }
122
+
123
+ it "validates presence of required param" do
124
+ params.should_not be_valid
125
+ params.errors[:name].should eq(["can't be blank"])
126
+ end
127
+
128
+ it "does not validate presence of optional param" do
129
+ params.should_not be_valid
130
+ params.errors[:age].should be_empty
131
+ end
132
+
133
+ it "does validate other validations of optional param" do
134
+ params = ParamsSpecClass.new(color: "blue")
135
+ params.should_not be_valid
136
+ params.errors[:color].should eq(["is not included in the list"])
137
+ end
138
+
139
+ describe "nested params", nested: true do
140
+ it "validates presence of required param" do
141
+ params.should_not be_valid
142
+ params.errors[:address][:street].should eq(["can't be blank"])
143
+ end
144
+
145
+ it "does not validate presence of optional param" do
146
+ params.should_not be_valid
147
+ params.errors[:address][:zip_code].should be_empty
148
+ end
149
+ end
150
+
151
+ describe "#validate!" do
152
+ let(:params) { ParamsSpecClass.new }
153
+
154
+ it "raises error with valdiation descriptions" do
155
+ expect { params.validate! }.to raise_error(SimpleParamsError,
156
+ "{:name=>[\"can't be blank\"], :address=>{:street=>[\"can't be blank\"], :city=>[\"is too short (minimum is 4 characters)\", \"can't be blank\"]}}"
157
+ )
158
+ end
159
+ end
160
+ end
161
+
162
+ describe "api_pie_documentation", api_pie_documentation: true do
163
+ it "generates valida api_pie documentation" do
164
+ documentation = ParamsSpecClass.api_pie_documentation
165
+ api_docs = <<-API_PIE_DOCS
166
+ param:reference, Object, desc:'', required: false
167
+ param :name, String, desc: '', required: true
168
+ param :age, Integer, desc: '', required: false
169
+ param :color, String, desc: '', required: true
170
+ param :address, Hash, desc: '', required: true do
171
+ param :street, String, desc: '', required: true
172
+ param :city, String, desc: '', required: true
173
+ param :zip_code, String, desc: '', required: false
174
+ param :state, String, desc: '', required: true
175
+ end
176
+ API_PIE_DOCS
177
+
178
+ expect(documentation).to be_a String
179
+ expect(documentation.gsub(/\s+/, "")).to eq api_docs.gsub(/\s+/, "")
180
+ end
181
+ end
182
+ end
@@ -0,0 +1,84 @@
1
+ require 'spec_helper'
2
+ require 'fixtures/dummy_service_object_class'
3
+
4
+ describe SimpleAction::Response do
5
+ describe "#valid?" do
6
+ context "with valid object" do
7
+ let(:object) { DummyServiceObjectClass.new(name: "Dummy") }
8
+ let(:response) { described_class.new(object) }
9
+
10
+ it "is valid" do
11
+ response.should be_valid
12
+ end
13
+ end
14
+
15
+ context "with invalid object" do
16
+ let(:object) { DummyServiceObjectClass.new(name: nil) }
17
+ let(:response) { described_class.new(object) }
18
+
19
+ it "is not valid" do
20
+ response.should_not be_valid
21
+ end
22
+ end
23
+ end
24
+
25
+ describe "#errors" do
26
+ context "with valid object" do
27
+ let(:object) { DummyServiceObjectClass.new(name: "Dummy") }
28
+ let(:response) { described_class.new(object) }
29
+
30
+ it "has no errors" do
31
+ response.errors.should be_empty
32
+ end
33
+ end
34
+
35
+ context "with invalid object" do
36
+ let(:object) { DummyServiceObjectClass.new(name: nil) }
37
+ let(:response) { described_class.new(object) }
38
+
39
+ it "has errors" do
40
+ response.errors[:name].should eq(["can't be blank"])
41
+ end
42
+ end
43
+ end
44
+
45
+ describe "#success?" do
46
+ context "with valid object" do
47
+ let(:object) { DummyServiceObjectClass.new(name: "Dummy") }
48
+ let(:response) { described_class.new(object) }
49
+
50
+ it "is success" do
51
+ response.should be_success
52
+ end
53
+ end
54
+
55
+ context "with invalid object" do
56
+ let(:object) { DummyServiceObjectClass.new(name: nil) }
57
+ let(:response) { described_class.new(object) }
58
+
59
+ it "is not success" do
60
+ response.should_not be_success
61
+ end
62
+ end
63
+ end
64
+
65
+ describe "#result" do
66
+ let(:object) { DummyServiceObjectClass.new(name: "Dummy") }
67
+
68
+ context "with no result provided" do
69
+ let(:response) { described_class.new(object) }
70
+
71
+ it "is nil" do
72
+ response.result.should be_nil
73
+ end
74
+ end
75
+
76
+ context "with response provided" do
77
+ let(:response) { described_class.new(object, 53) }
78
+
79
+ it "is 53" do
80
+ response.result.should eq(53)
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,125 @@
1
+ require 'spec_helper'
2
+ require 'fixtures/service_spec_class'
3
+
4
+ describe SimpleAction::Service do
5
+ describe "class_methods", class_methods: true do
6
+ describe "#run", run: true do
7
+ context "with invalid attributes" do
8
+ let(:outcome) { ServiceSpecClass.run(age: 12) }
9
+
10
+ it "is not valid?" do
11
+ outcome.should_not be_valid
12
+ end
13
+
14
+ it "is not success?" do
15
+ outcome.should_not be_success
16
+ end
17
+
18
+ it "has no result" do
19
+ outcome.result.should eq(nil)
20
+ end
21
+
22
+ it "returns errors" do
23
+ outcome.errors[:name].should eq(["can't be blank"])
24
+ end
25
+ end
26
+
27
+ context "with valid attributes" do
28
+ let(:outcome) { ServiceSpecClass.run(name: "David", age: 12) }
29
+
30
+ it "is valid?" do
31
+ outcome.should be_valid
32
+ end
33
+
34
+ it "is success?" do
35
+ outcome.should be_success
36
+ end
37
+
38
+ it "has result equal to output of execute", failing: true do
39
+ outcome.result.should eq(41)
40
+ end
41
+
42
+ it "returns empty errors" do
43
+ outcome.errors.should be_empty
44
+ end
45
+ end
46
+ end
47
+
48
+ describe "#run!", run!: true do
49
+ context "with invalid attributes" do
50
+ it "raises error" do
51
+ expect { ServiceSpecClass.run!(age: 12) }.to raise_error(StandardError,
52
+ "Name can't be blank"
53
+ )
54
+ end
55
+ end
56
+
57
+ context "with valid attributes" do
58
+ let(:outcome) { ServiceSpecClass.run!(name: "David", age: 12) }
59
+
60
+ it "is equal to the output of execute" do
61
+ outcome.should eq(41)
62
+ end
63
+ end
64
+ end
65
+
66
+ describe "#api_pie_documentation", api_pie_documentation: true do
67
+ it "equals params api_pie_documentation" do
68
+ ServiceSpecClass.api_pie_documentation.should eq("param :name, String, desc: '', required: true\nparam :age, Integer, desc: '', required: true")
69
+ end
70
+ end
71
+ end
72
+
73
+ describe "instance methods", instance_methods: true do
74
+ describe "#params", params: true do
75
+ it "assigns params" do
76
+ instance = ServiceSpecClass.new(name: "Nic Cage", age: "40")
77
+ instance.params.name.should eq("Nic Cage")
78
+ instance.params.age.should eq(40)
79
+ end
80
+ end
81
+
82
+ describe "#valid?", valid: true do
83
+ context "with invalid params" do
84
+ it "is false" do
85
+ ServiceSpecClass.new(age: 12).should_not be_valid
86
+ end
87
+ end
88
+
89
+ context "with valid params" do
90
+ it "is true" do
91
+ ServiceSpecClass.new(name: "Tom", age: 12).should be_valid
92
+ end
93
+ end
94
+ end
95
+
96
+ describe "#errors", errors: true do
97
+ context "with invalid params" do
98
+ let(:instance) { ServiceSpecClass.new(age: 12) }
99
+
100
+ it "is empty before validation" do
101
+ instance.errors.should be_empty
102
+ end
103
+
104
+ it "returns errors with correct messages" do
105
+ instance.valid?
106
+ instance.errors.should_not be_empty
107
+ instance.errors[:name].should eq(["can't be blank"])
108
+ end
109
+ end
110
+
111
+ context "with valid params" do
112
+ let(:instance) { ServiceSpecClass.new(age: 12, name: "Tom") }
113
+
114
+ it "is empty before validation" do
115
+ instance.errors.should be_empty
116
+ end
117
+
118
+ it "is empty after validation" do
119
+ instance.valid?
120
+ instance.errors.should be_empty
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,12 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'simple_action'
4
+ require 'pry'
5
+
6
+ Dir[File.join('.', 'spec', 'support', '**', '*.rb')].each {|f| require f}
7
+
8
+ # I18n.config.enforce_available_locales = true
9
+
10
+ RSpec.configure do |config|
11
+ config.mock_with :rspec
12
+ end
metadata ADDED
@@ -0,0 +1,152 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: simple_action
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1.pre1
5
+ platform: ruby
6
+ authors:
7
+ - brycesenz
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-04-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: simple_params
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: 0.0.2.pre9
20
+ - - <
21
+ - !ruby/object:Gem::Version
22
+ version: '1.0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 0.0.2.pre9
30
+ - - <
31
+ - !ruby/object:Gem::Version
32
+ version: '1.0'
33
+ - !ruby/object:Gem::Dependency
34
+ name: bundler
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ~>
38
+ - !ruby/object:Gem::Version
39
+ version: '1.5'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ version: '1.5'
47
+ - !ruby/object:Gem::Dependency
48
+ name: rake
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '10.1'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ~>
59
+ - !ruby/object:Gem::Version
60
+ version: '10.1'
61
+ - !ruby/object:Gem::Dependency
62
+ name: rspec
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ~>
66
+ - !ruby/object:Gem::Version
67
+ version: '2.6'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ~>
73
+ - !ruby/object:Gem::Version
74
+ version: '2.6'
75
+ - !ruby/object:Gem::Dependency
76
+ name: pry
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ! '>='
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ! '>='
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ description: Simple Service Object class for services & API endpoints
90
+ email:
91
+ - bryce.senz@gmail.com
92
+ executables: []
93
+ extensions: []
94
+ extra_rdoc_files: []
95
+ files:
96
+ - .gitignore
97
+ - .rspec
98
+ - .ruby-gemset
99
+ - .ruby-version
100
+ - Gemfile
101
+ - Gemfile.lock
102
+ - LICENSE
103
+ - README.md
104
+ - lib/simple_action.rb
105
+ - lib/simple_action/concerns/accepts_params.rb
106
+ - lib/simple_action/concerns/delegates_to_params.rb
107
+ - lib/simple_action/concerns/transactable.rb
108
+ - lib/simple_action/error.rb
109
+ - lib/simple_action/params.rb
110
+ - lib/simple_action/response.rb
111
+ - lib/simple_action/service.rb
112
+ - lib/simple_action/version.rb
113
+ - simple_action.gemspec
114
+ - spec/fixtures/dummy_service_object_class.rb
115
+ - spec/fixtures/params_spec_class.rb
116
+ - spec/fixtures/service_spec_class.rb
117
+ - spec/params_spec.rb
118
+ - spec/response_spec.rb
119
+ - spec/service_spec.rb
120
+ - spec/spec_helper.rb
121
+ homepage: https://github.com/brycesenz/simple_action
122
+ licenses:
123
+ - MIT
124
+ metadata: {}
125
+ post_install_message:
126
+ rdoc_options: []
127
+ require_paths:
128
+ - lib
129
+ required_ruby_version: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ required_rubygems_version: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ! '>'
137
+ - !ruby/object:Gem::Version
138
+ version: 1.3.1
139
+ requirements: []
140
+ rubyforge_project:
141
+ rubygems_version: 2.4.6
142
+ signing_key:
143
+ specification_version: 4
144
+ summary: A DSL for specifying services objects, including parameters and execution
145
+ test_files:
146
+ - spec/fixtures/dummy_service_object_class.rb
147
+ - spec/fixtures/params_spec_class.rb
148
+ - spec/fixtures/service_spec_class.rb
149
+ - spec/params_spec.rb
150
+ - spec/response_spec.rb
151
+ - spec/service_spec.rb
152
+ - spec/spec_helper.rb