simple_action 0.0.1.pre1

Sign up to get free protection for your applications and to get access to all the features.
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