tradesman 0.3.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +78 -17
- data/lib/tradesman/builders/base.rb +4 -0
- data/lib/tradesman/builders/create.rb +12 -1
- data/lib/tradesman/builders/create_for_parent.rb +16 -3
- data/lib/tradesman/builders/delete.rb +12 -1
- data/lib/tradesman/builders/update.rb +2 -1
- data/lib/tradesman/class_methods.rb +37 -0
- data/lib/tradesman/configuration.rb +2 -2
- data/lib/tradesman/error_handling.rb +32 -0
- data/lib/tradesman/errors.rb +20 -7
- data/lib/tradesman/mixins/existing_records_multiple_execute.rb +26 -0
- data/lib/tradesman/mixins/new_records_multiple_execute.rb +15 -0
- data/lib/tradesman/template.rb +11 -12
- data/lib/tradesman.rb +5 -19
- data/spec/tradesman_spec.rb +218 -9
- metadata +8 -5
- data/lib/tradesman/run_methods.rb +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 88a8291acc6f38c6d19ff311c2c2ab950c755288
|
4
|
+
data.tar.gz: dca95fa986b0e498bec27f5205fbec416d547c78
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e403a3da8460e086194e472c92d2827e2e132da3f2150dc26b7a7d248b476f851289f70e6fc95959efd7ee90646981eaaf29bd12a78c94c111fe918893b8563d
|
7
|
+
data.tar.gz: c601b711e3e59ae362c9fed58870c1b5e3f92e488963d49a9a956c27c0156e9869ce7520bdfc50e55d46643f4cd9ca67006efb26253523e3972fa2f4b178ba4e
|
data/README.md
CHANGED
@@ -1,19 +1,28 @@
|
|
1
1
|
# Tradesman
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
Tradesman dynamically generates classes with human-readble names that handle the pass, fail, and invalid results of common create, update, and delete actions.
|
3
|
+
Tradesman lets you invoke human-readble classes that handle the pass, fail, and invalid cases of common create, update, and delete actions without having to write the code!
|
6
4
|
|
7
5
|
## Usage
|
8
6
|
|
9
7
|
```ruby
|
10
|
-
# Simple - Returns
|
11
|
-
outcome = Tradesman::CreateUser.
|
8
|
+
# Simple - Returns a successful Outcome
|
9
|
+
outcome = Tradesman::CreateUser.go(user_params)
|
12
10
|
outcome.success? #=> true
|
11
|
+
outcome.failure? #=> false
|
13
12
|
outcome.result #=> User Entity
|
14
13
|
|
14
|
+
# With invalid parameters - returns an invalid Outcome
|
15
|
+
outcome = Tradesman::CreateUser.go(invalid_user_params)
|
16
|
+
outcome.success? #=> false
|
17
|
+
outcome.failure? #=> true
|
18
|
+
outcome.result #=> Error Class
|
19
|
+
outcome.type #=> :validation
|
20
|
+
|
21
|
+
# With invalid parameters - fail loudly!
|
22
|
+
outcome = Tradesman::CreateUser.go!(invalid_user_params) #=> raises Tradesman::Invalid or Tradesman::Failure
|
23
|
+
|
15
24
|
# Passing a block - Well-suited for Controllers
|
16
|
-
Tradesman::UpdateUser.
|
25
|
+
Tradesman::UpdateUser.go(params[:id], user_update_params) do
|
17
26
|
success do |result|
|
18
27
|
render(text: 'true', status: 200)
|
19
28
|
end
|
@@ -22,18 +31,70 @@ Tradesman::UpdateUser.run({ id: params[:id] }.merge(user_update_params)) do
|
|
22
31
|
render(text: 'false', status: 404)
|
23
32
|
end
|
24
33
|
|
25
|
-
failure do |
|
34
|
+
failure do |error|
|
26
35
|
render(text: 'false', status: 400)
|
27
36
|
end
|
28
37
|
end
|
29
38
|
|
30
|
-
#
|
31
|
-
Tradesman::DeleteUser.
|
39
|
+
# Delete
|
40
|
+
Tradesman::DeleteUser.go(params[:id])
|
41
|
+
|
42
|
+
# Create as a child of an existing record
|
43
|
+
Tradesman::CreateUserForEmployer.go(employer, user_params)
|
44
|
+
|
45
|
+
# Create multiple records
|
46
|
+
Tradesman::CreateUser.go([user_params, user_params, user_params])
|
47
|
+
|
48
|
+
# Create multiple for a single parent
|
49
|
+
Tradesman::CreateUserForEmployer.go(employer, [user_params, user_params, user_params])
|
50
|
+
|
51
|
+
# Update multiple records with 1 set of parameters
|
52
|
+
Tradesman::UpdateUser.go([user1, user2, user3], update_params)
|
32
53
|
|
33
|
-
#
|
34
|
-
|
54
|
+
# Update n records with n sets of parameters
|
55
|
+
# Whenever you pass an id, you can either pass the id itself,
|
56
|
+
# or an object that response to :id
|
57
|
+
update_params = {
|
58
|
+
user1.id => user1_params,
|
59
|
+
user2.id => user2_params,
|
60
|
+
user3.id => user3_params
|
61
|
+
}
|
62
|
+
Tradesman::UpdateUser.go(update_params.keys, update_params.values)
|
63
|
+
|
64
|
+
|
65
|
+
# Delete multiple records
|
66
|
+
Tradesman::DeleteUser.go([id1, id2, id3])
|
35
67
|
```
|
36
68
|
|
69
|
+
## Parsing Rules
|
70
|
+
|
71
|
+
Classes have the following structure:
|
72
|
+
|
73
|
+
`Method` + `Record`
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
# Examples:
|
77
|
+
CreateUser
|
78
|
+
UpdateEmployer
|
79
|
+
DeleteBlogPost
|
80
|
+
```
|
81
|
+
|
82
|
+
Where **Method** is one of `Create`, `Update`, or `Delete`, and **Record** is your model classname, CamelCased.
|
83
|
+
Note that model namespaces are ignored.
|
84
|
+
|
85
|
+
The only exception is when you create a record for a parent. These classes have the following structure:
|
86
|
+
|
87
|
+
`Method` + `Record` + `'For'` + `ParentRecord`
|
88
|
+
|
89
|
+
```ruby
|
90
|
+
# Examples
|
91
|
+
CreateUserForEmployer
|
92
|
+
CreateInvoiceForCustomer
|
93
|
+
```
|
94
|
+
|
95
|
+
Where 'For' is a string literal and **ParentRecord** is the parent model classname, CamelCased.
|
96
|
+
|
97
|
+
|
37
98
|
## Why is this necessary?
|
38
99
|
|
39
100
|
At Onfido, we observed that many Create, Update and Delete actions we programmed were are simple and repeated (albeit with different records and parameter lists) in several locations. They can generally be broken in to the following steps:
|
@@ -51,7 +112,7 @@ def update
|
|
51
112
|
return render(text: 'false', status: 404) unless @user
|
52
113
|
|
53
114
|
@user.assign_attributes(user_params)
|
54
|
-
return render(text: 'false', status:
|
115
|
+
return render(text: 'false', status: 422) unless @user.save
|
55
116
|
|
56
117
|
render 'user'
|
57
118
|
end
|
@@ -68,14 +129,14 @@ Tradesman is designed to handle the above and a few other common use-cases to re
|
|
68
129
|
|
69
130
|
Tradesman version of the above:
|
70
131
|
```ruby
|
71
|
-
Tradesman::UpdateUser.
|
132
|
+
Tradesman::UpdateUser.go(user_id, user_params) do
|
72
133
|
success do |result|
|
73
134
|
@user = result
|
74
135
|
render 'user'
|
75
136
|
end
|
76
137
|
|
77
138
|
invalid do |error|
|
78
|
-
render(text:
|
139
|
+
render(text: error.message, status: 422)
|
79
140
|
end
|
80
141
|
|
81
142
|
failure { |result| render(text: 'false', status: 400) } # If you prefer one-liners
|
@@ -84,7 +145,7 @@ end
|
|
84
145
|
private
|
85
146
|
|
86
147
|
def user_params
|
87
|
-
params.permit(:
|
148
|
+
params.permit(:first_name, :last_name, :email)
|
88
149
|
end
|
89
150
|
```
|
90
151
|
|
@@ -94,8 +155,8 @@ The Tradesman version says exactly what it does, is cruft free, and is much quic
|
|
94
155
|
|
95
156
|
**Define your adapter**
|
96
157
|
|
97
|
-
_config/initializers/tradesman.rb_
|
98
158
|
```ruby
|
159
|
+
# config/initializers/tradesman.rb
|
99
160
|
Tradesman.configure { |config| config.adapter = :active_record }
|
100
161
|
```
|
101
162
|
|
@@ -120,8 +181,8 @@ end
|
|
120
181
|
|
121
182
|
In order to help Tradesman lazy load these models, you need to enable development mode and configure any namespaces:
|
122
183
|
|
123
|
-
_config/initializers/tradesman.rb_
|
124
184
|
```ruby
|
185
|
+
# config/initializers/tradesman.rb
|
125
186
|
Tradesman.configure do |config|
|
126
187
|
config.adapter = :active_record
|
127
188
|
config.development_mode = Rails.env.development?
|
@@ -5,11 +5,22 @@ module Tradesman
|
|
5
5
|
|
6
6
|
def template_class(args)
|
7
7
|
Class.new(::Tradesman::Template) do
|
8
|
+
include ::Tradesman::NewRecordsMultipleExecute
|
8
9
|
@store = Tradesman.adapter.context_for_entity(args[:subject])
|
9
10
|
|
11
|
+
class << self
|
12
|
+
def go(params, *context, &block)
|
13
|
+
run_and_convert_exceptions { run(params, *context, &block) }
|
14
|
+
end
|
15
|
+
|
16
|
+
def go!(params, *context)
|
17
|
+
run_and_convert_exceptions { run!(params, *context) }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
10
21
|
private
|
11
22
|
|
12
|
-
def
|
23
|
+
def execute_single(params)
|
13
24
|
self.class.adapter.create!(params)
|
14
25
|
end
|
15
26
|
end
|
@@ -5,6 +5,7 @@ module Tradesman
|
|
5
5
|
|
6
6
|
def template_class(args)
|
7
7
|
Class.new(::Tradesman::Template) do
|
8
|
+
include ::Tradesman::ExistingRecordsMultipleExecute
|
8
9
|
@store = Tradesman.adapter.context_for_entity(args[:subject])
|
9
10
|
@parent_store = Tradesman.adapter.context_for_entity(args[:parent])
|
10
11
|
@parent_key = args[:parent]
|
@@ -19,14 +20,26 @@ module Tradesman
|
|
19
20
|
|
20
21
|
private
|
21
22
|
|
22
|
-
def
|
23
|
-
parent = self.class.parent_adapter.get!(params[:
|
24
|
-
self.class.adapter.create!(params.except(:
|
23
|
+
def execute_single(params)
|
24
|
+
parent = self.class.parent_adapter.get!(params[:id])
|
25
|
+
self.class.adapter.create!(params.except(:id).merge(relation_id => parent.id))
|
25
26
|
end
|
26
27
|
|
27
28
|
def relation_id
|
28
29
|
"#{self.class.parent_key}_id"
|
29
30
|
end
|
31
|
+
|
32
|
+
def execute_multiple(params_hash)
|
33
|
+
params = params_hash[:params] || params_hash.except(:id)
|
34
|
+
|
35
|
+
params.map do |params|
|
36
|
+
begin
|
37
|
+
execute_single({ id: params_hash[:id] }.merge(params))
|
38
|
+
rescue *self.class.expected_errors_map.keys => e
|
39
|
+
Horza::Entities::Single.new(id: params[:id], valid: false, message: e.message)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
30
43
|
end
|
31
44
|
end
|
32
45
|
end
|
@@ -5,11 +5,22 @@ module Tradesman
|
|
5
5
|
|
6
6
|
def template_class(args)
|
7
7
|
Class.new(::Tradesman::Template) do
|
8
|
+
include ::Tradesman::ExistingRecordsMultipleExecute
|
8
9
|
@store = Tradesman.adapter.context_for_entity(args[:subject])
|
9
10
|
|
11
|
+
class << self
|
12
|
+
def go(obj, *context, &block)
|
13
|
+
run_and_convert_exceptions { run(tzu_params(obj, {}), *context, &block) }
|
14
|
+
end
|
15
|
+
|
16
|
+
def go!(obj, *context)
|
17
|
+
run_and_convert_exceptions { run!(tzu_params(obj, {}), *context) }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
10
21
|
private
|
11
22
|
|
12
|
-
def
|
23
|
+
def execute_single(params)
|
13
24
|
self.class.adapter.delete!(params[:id])
|
14
25
|
end
|
15
26
|
end
|
@@ -5,11 +5,12 @@ module Tradesman
|
|
5
5
|
|
6
6
|
def template_class(args)
|
7
7
|
Class.new(::Tradesman::Template) do
|
8
|
+
include ::Tradesman::ExistingRecordsMultipleExecute
|
8
9
|
@store = Tradesman.adapter.context_for_entity(args[:subject])
|
9
10
|
|
10
11
|
private
|
11
12
|
|
12
|
-
def
|
13
|
+
def execute_single(params)
|
13
14
|
self.class.adapter.update!(params[:id], params.except(:id))
|
14
15
|
end
|
15
16
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Tradesman
|
2
|
+
module ClassMethods
|
3
|
+
attr_reader :store
|
4
|
+
|
5
|
+
def adapter
|
6
|
+
Tradesman.adapter.new(store)
|
7
|
+
end
|
8
|
+
|
9
|
+
def go(obj, params, *context, &block)
|
10
|
+
run_and_convert_exceptions { run(tzu_params(obj, params), *context, &block) }
|
11
|
+
end
|
12
|
+
|
13
|
+
def go!(obj, params, *context)
|
14
|
+
run_and_convert_exceptions { run!(tzu_params(obj, params), *context) }
|
15
|
+
end
|
16
|
+
|
17
|
+
def tzu_params(obj, params)
|
18
|
+
{ id: prepare_ids(obj) }.merge(prepare_params(params))
|
19
|
+
end
|
20
|
+
|
21
|
+
def prepare_ids(obj)
|
22
|
+
return id_from_obj(obj) unless obj.is_a? Array
|
23
|
+
obj.map { |object| id_from_obj(object) }
|
24
|
+
end
|
25
|
+
|
26
|
+
def id_from_obj(obj)
|
27
|
+
return obj.id if obj.respond_to? :id
|
28
|
+
raise Tradesman::InvalidId.new('ID must be an integer') unless obj.is_a? Integer
|
29
|
+
obj
|
30
|
+
end
|
31
|
+
|
32
|
+
def prepare_params(params)
|
33
|
+
return params unless params.is_a? Array
|
34
|
+
{ params: params }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -14,7 +14,7 @@ module Tradesman
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def adapter
|
17
|
-
raise ::Tradesman::
|
17
|
+
raise ::Tradesman::Base.new('Adapter has not been configured') unless configuration.adapter
|
18
18
|
@adapter ||= configuration.adapter
|
19
19
|
end
|
20
20
|
end
|
@@ -32,7 +32,7 @@ module Tradesman
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def namespaces=(namespaces)
|
35
|
-
fail Tradesman::
|
35
|
+
fail Tradesman::Base.new 'namespaces must be an array' unless namespaces.is_a? Array
|
36
36
|
Horza.configure { |config| config.namespaces = namespaces }
|
37
37
|
@namespaces = namespaces
|
38
38
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Tradesman
|
2
|
+
module ErrorHandling
|
3
|
+
def run_and_convert_exceptions(&block)
|
4
|
+
block.call
|
5
|
+
rescue *expected_errors_map.keys => e
|
6
|
+
raise tradesman_error_from_gem_error(e.class)
|
7
|
+
end
|
8
|
+
|
9
|
+
def tradesman_error_from_gem_error(gem_error)
|
10
|
+
expected_errors_map[gem_error]
|
11
|
+
end
|
12
|
+
|
13
|
+
def expected_errors_map
|
14
|
+
expected_tzu_errors_map.merge(expected_horza_errors_map)
|
15
|
+
end
|
16
|
+
|
17
|
+
def expected_tzu_errors_map
|
18
|
+
{
|
19
|
+
Tzu::Invalid => Tradesman::Invalid,
|
20
|
+
Tzu::Failure => Tradesman::Failure,
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def expected_horza_errors_map
|
25
|
+
{
|
26
|
+
Horza::Errors::RecordNotFound => Tradesman::RecordNotFound,
|
27
|
+
Horza::Errors::RecordInvalid => Tradesman::RecordInvalid,
|
28
|
+
Horza::Errors::UnknownAttributeError => Tradesman::UnknownAttributeError
|
29
|
+
}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/tradesman/errors.rb
CHANGED
@@ -1,12 +1,25 @@
|
|
1
1
|
module Tradesman
|
2
|
-
|
3
|
-
|
4
|
-
|
2
|
+
class Base < StandardError
|
3
|
+
end
|
4
|
+
|
5
|
+
class MethodNotImplemented < StandardError
|
6
|
+
end
|
7
|
+
|
8
|
+
class InvalidId < StandardError
|
9
|
+
end
|
10
|
+
|
11
|
+
class Invalid < StandardError
|
12
|
+
end
|
13
|
+
|
14
|
+
class Failure < StandardError
|
15
|
+
end
|
5
16
|
|
6
|
-
|
7
|
-
|
17
|
+
class RecordNotFound < StandardError
|
18
|
+
end
|
19
|
+
|
20
|
+
class RecordInvalid < StandardError
|
21
|
+
end
|
8
22
|
|
9
|
-
|
10
|
-
end
|
23
|
+
class UnknownAttributeError < StandardError
|
11
24
|
end
|
12
25
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Tradesman
|
2
|
+
module ExistingRecordsMultipleExecute
|
3
|
+
private
|
4
|
+
|
5
|
+
def execute_multiple(params_hash)
|
6
|
+
params = params_hash[:params] || params_hash.except(:id)
|
7
|
+
|
8
|
+
params_hash[:id].to_enum.with_index.map do |id, index|
|
9
|
+
begin
|
10
|
+
execute_single(single_params(id, params, index))
|
11
|
+
rescue *self.class.expected_errors_map.keys => e
|
12
|
+
Horza::Entities::Single.new(id: id, valid: false, message: e.message)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def single_params(id, params, index)
|
18
|
+
{ id: id }.merge(params_at_index(params, index))
|
19
|
+
end
|
20
|
+
|
21
|
+
def params_at_index(params, index)
|
22
|
+
return params unless params.is_a? Array
|
23
|
+
params[index]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Tradesman
|
2
|
+
module NewRecordsMultipleExecute
|
3
|
+
private
|
4
|
+
|
5
|
+
def execute_multiple(params_array)
|
6
|
+
params_array.map do |params|
|
7
|
+
begin
|
8
|
+
execute_single(params)
|
9
|
+
rescue *self.class.expected_errors_map.keys => e
|
10
|
+
Horza::Entities::Single.new(id: nil, valid: false, message: e.message)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/tradesman/template.rb
CHANGED
@@ -2,25 +2,24 @@ module Tradesman
|
|
2
2
|
class Template
|
3
3
|
include ::Tzu
|
4
4
|
include ::Tzu::Validation
|
5
|
-
|
6
|
-
|
7
|
-
attr_reader :store
|
8
|
-
|
9
|
-
def adapter
|
10
|
-
Tradesman.adapter.new(store)
|
11
|
-
end
|
12
|
-
end
|
5
|
+
extend ::Tradesman::ClassMethods
|
6
|
+
extend ::Tradesman::ErrorHandling
|
13
7
|
|
14
8
|
def call(params)
|
15
|
-
|
16
|
-
|
9
|
+
return execute_single(params) unless (params.is_a?(Array) || params[:id].is_a?(Array) || params[:params].is_a?(Array))
|
10
|
+
execute_multiple(params)
|
11
|
+
rescue *self.class.expected_horza_errors_map.keys => e
|
17
12
|
invalid! e
|
18
13
|
end
|
19
14
|
|
20
15
|
private
|
21
16
|
|
22
|
-
def
|
23
|
-
raise Tradesman::
|
17
|
+
def execute_single(params)
|
18
|
+
raise Tradesman::MethodNotImplemented.new('You must implement execute_single in a child class')
|
19
|
+
end
|
20
|
+
|
21
|
+
def execute_multiple(params_hash)
|
22
|
+
raise Tradesman::MethodNotImplemented.new('You must implement execute_multiple in a child class')
|
24
23
|
end
|
25
24
|
end
|
26
25
|
end
|
data/lib/tradesman.rb
CHANGED
@@ -1,44 +1,30 @@
|
|
1
1
|
require 'horza'
|
2
2
|
require 'tzu'
|
3
|
+
require 'tradesman/mixins/existing_records_multiple_execute'
|
4
|
+
require 'tradesman/mixins/new_records_multiple_execute'
|
3
5
|
require 'tradesman/builders'
|
4
6
|
require 'tradesman/builders/base'
|
5
7
|
require 'tradesman/builders/create'
|
6
8
|
require 'tradesman/builders/create_for_parent'
|
7
9
|
require 'tradesman/builders/delete'
|
8
10
|
require 'tradesman/builders/update'
|
11
|
+
require 'tradesman/class_methods'
|
9
12
|
require 'tradesman/configuration'
|
10
13
|
require 'tradesman/errors'
|
14
|
+
require 'tradesman/error_handling'
|
11
15
|
require 'tradesman/parser'
|
12
|
-
require 'tradesman/run_methods'
|
13
16
|
require 'tradesman/template'
|
14
17
|
|
15
18
|
module Tradesman
|
16
|
-
extend
|
19
|
+
extend Configuration
|
17
20
|
|
18
21
|
class << self
|
19
22
|
attr_writer :configuration
|
20
23
|
|
21
|
-
def included(base)
|
22
|
-
base.class_eval do
|
23
|
-
extend ::Tradesman::RunMethods
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
24
|
def const_missing(class_name)
|
28
25
|
parser = ::Tradesman::Parser.new(class_name)
|
29
26
|
return super(class_name) unless parser.match?
|
30
27
|
Builders.generate_class(parser)
|
31
28
|
end
|
32
29
|
end
|
33
|
-
|
34
|
-
def run
|
35
|
-
run!
|
36
|
-
rescue ::Tradesman::Errors::Base
|
37
|
-
end
|
38
|
-
|
39
|
-
def run!
|
40
|
-
call
|
41
|
-
rescue *Tradesman.adapter.expected_errors => e
|
42
|
-
raise ::Tradesman::Errors::Base.new(e.message)
|
43
|
-
end
|
44
30
|
end
|
data/spec/tradesman_spec.rb
CHANGED
@@ -51,7 +51,7 @@ describe Tradesman do
|
|
51
51
|
after { Tradesman.reset }
|
52
52
|
|
53
53
|
it 'throws error' do
|
54
|
-
expect { Tradesman.adapter }.to raise_error(Tradesman::
|
54
|
+
expect { Tradesman.adapter }.to raise_error(Tradesman::Base)
|
55
55
|
end
|
56
56
|
end
|
57
57
|
end
|
@@ -90,10 +90,10 @@ describe Tradesman do
|
|
90
90
|
end
|
91
91
|
end
|
92
92
|
|
93
|
-
context '#
|
93
|
+
context '#go' do
|
94
94
|
context 'Create' do
|
95
95
|
context 'when parameters are valid' do
|
96
|
-
let(:outcome) { Tradesman::CreateUser.
|
96
|
+
let(:outcome) { Tradesman::CreateUser.go(last_name: 'Turner') }
|
97
97
|
|
98
98
|
it 'creates a new record' do
|
99
99
|
expect(outcome.success?).to be true
|
@@ -106,16 +106,47 @@ describe Tradesman do
|
|
106
106
|
end
|
107
107
|
|
108
108
|
context 'when parameters are invalid' do
|
109
|
-
let(:outcome) { Tradesman::CreateStrictUser.
|
109
|
+
let(:outcome) { Tradesman::CreateStrictUser.go(first_name: 'Turner') }
|
110
110
|
it 'returns an invalid outcome' do
|
111
111
|
expect(outcome.success?).to be false
|
112
112
|
expect(outcome.type).to eq :validation
|
113
113
|
end
|
114
114
|
end
|
115
115
|
|
116
|
+
context 'multiple records' do
|
117
|
+
let(:outcome) { Tradesman::CreateStrictUser.go(param_list) }
|
118
|
+
context 'when all are valid' do
|
119
|
+
let(:param_list) { [{ last_name: 'Turner' }, { last_name: 'Smith' }, { last_name: 'Jones' }] }
|
120
|
+
|
121
|
+
it 'creates one record for each parameter set passed' do
|
122
|
+
expect(outcome.result.length).to eq param_list.length
|
123
|
+
outcome.result.each do |record|
|
124
|
+
expect(record.id.present?).to be true
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
context 'when one is valid' do
|
130
|
+
let(:param_list) { [{ first_name: 'Turner' }, { last_name: 'Smith' }, { age: 25 }] }
|
131
|
+
|
132
|
+
it 'creates invalid entities when params are invalid, valid entity otherwise' do
|
133
|
+
entities = outcome.result
|
134
|
+
expect(entities.length).to eq param_list.length
|
135
|
+
|
136
|
+
expect(entities.first.id).to be nil
|
137
|
+
expect(entities.first.valid?).to be false
|
138
|
+
|
139
|
+
expect(entities.second.id.is_a? Integer).to be true
|
140
|
+
|
141
|
+
expect(entities.third.id).to be nil
|
142
|
+
expect(entities.third.valid?).to be false
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
116
147
|
context 'for parent' do
|
117
148
|
let(:employer) { TradesmanSpec::Employer.create }
|
118
|
-
let(:outcome) { Tradesman::CreateUserForEmployer.
|
149
|
+
let(:outcome) { Tradesman::CreateUserForEmployer.go(employer.id, last_name: 'Turner') }
|
119
150
|
|
120
151
|
it 'creates a new record' do
|
121
152
|
expect(outcome.success?).to be true
|
@@ -130,6 +161,38 @@ describe Tradesman do
|
|
130
161
|
outcome
|
131
162
|
expect(employer.users.first.id).to eq outcome.result.id
|
132
163
|
end
|
164
|
+
|
165
|
+
context 'multiple records' do
|
166
|
+
let(:employer) { Tradesman::CreateEmployer.go({}).result }
|
167
|
+
let(:outcome) { Tradesman::CreateStrictUserForEmployer.go(employer, param_list) }
|
168
|
+
context 'when all are valid' do
|
169
|
+
let(:param_list) { [{ last_name: 'Turner' }, { last_name: 'Smith' }, { last_name: 'Jones' }] }
|
170
|
+
|
171
|
+
it 'creates one record for each parameter set passed' do
|
172
|
+
expect(outcome.result.length).to eq param_list.length
|
173
|
+
outcome.result.each do |record|
|
174
|
+
expect(record.id.present?).to be true
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
context 'when one is valid' do
|
180
|
+
let(:param_list) { [{ first_name: 'Turner' }, { last_name: 'Smith' }, { age: 25 }] }
|
181
|
+
|
182
|
+
it 'creates invalid entities when params are invalid, valid entity otherwise' do
|
183
|
+
entities = outcome.result
|
184
|
+
expect(entities.length).to eq param_list.length
|
185
|
+
|
186
|
+
expect(entities.first.id).to be nil
|
187
|
+
expect(entities.first.valid?).to be false
|
188
|
+
|
189
|
+
expect(entities.second.id.is_a? Integer).to be true
|
190
|
+
|
191
|
+
expect(entities.third.id).to be nil
|
192
|
+
expect(entities.third.valid?).to be false
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
133
196
|
end
|
134
197
|
end
|
135
198
|
end
|
@@ -137,7 +200,7 @@ describe Tradesman do
|
|
137
200
|
context 'Update' do
|
138
201
|
let(:user) { TradesmanSpec::User.create(last_name: 'Smith') }
|
139
202
|
context 'when parameters are valid' do
|
140
|
-
let(:outcome) { Tradesman::UpdateUser.
|
203
|
+
let(:outcome) { Tradesman::UpdateUser.go(user.id, last_name: 'Turner') }
|
141
204
|
|
142
205
|
it 'executes successfully' do
|
143
206
|
expect(outcome.success?).to be true
|
@@ -151,19 +214,165 @@ describe Tradesman do
|
|
151
214
|
|
152
215
|
context 'when parameters are invalid' do
|
153
216
|
let(:strict_user) { TradesmanSpec::StrictUser.create(last_name: 'Smith') }
|
154
|
-
let(:outcome) { Tradesman::UpdateStrictUser.
|
217
|
+
let(:outcome) { Tradesman::UpdateStrictUser.go(strict_user, last_name: nil) }
|
218
|
+
|
219
|
+
it 'returns an invalid outcome' do
|
220
|
+
expect(outcome.success?).to be false
|
221
|
+
expect(outcome.type).to eq :validation
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
context 'when id is invalid' do
|
226
|
+
it 'throws error' do
|
227
|
+
expect { Tradesman::UpdateStrictUser.go('not_an_integer', last_name: nil) }.to raise_error Tradesman::InvalidId
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
context 'multiple records' do
|
232
|
+
let(:valid_params) { { last_name: 'Turner' } }
|
233
|
+
let(:outcome) { Tradesman::UpdateStrictUser.go(records, params) }
|
234
|
+
|
235
|
+
# Hash of id => params
|
236
|
+
# Tradesman::UpdateStrictUser.go(hash.keys, hash.values)
|
155
237
|
|
238
|
+
context 'passing array of ids and one valid parameter set' do
|
239
|
+
let(:records) { Tradesman::CreateStrictUser.go([valid_params, valid_params, valid_params]).result }
|
240
|
+
let(:params) { { last_name: 'Smith' } }
|
241
|
+
|
242
|
+
it 'creates one record for each parameter set passed' do
|
243
|
+
expect(outcome.result.length).to eq records.length
|
244
|
+
outcome.result.each do |record|
|
245
|
+
expect(record.last_name).to eq 'Smith'
|
246
|
+
expect(record.id.present?).to be true
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
context 'passing array of ids and multiple valid parameters' do
|
252
|
+
let(:records) { Tradesman::CreateStrictUser.go([valid_params, valid_params, valid_params]).result }
|
253
|
+
let(:params) { [{ last_name: 'Smith' }, { last_name: 'Williams' }, { last_name: 'Jones' }] }
|
254
|
+
|
255
|
+
it 'creates one record for each parameter set passed' do
|
256
|
+
results = outcome.result
|
257
|
+
expect(results.length).to eq records.length
|
258
|
+
expect(results.first.last_name).to eq params.first[:last_name]
|
259
|
+
expect(results.second.last_name).to eq params.second[:last_name]
|
260
|
+
expect(results.last.last_name).to eq params.last[:last_name]
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
context 'Delete' do
|
267
|
+
context 'when parameters are valid' do
|
268
|
+
let!(:user) { TradesmanSpec::User.create }
|
269
|
+
let(:outcome) { Tradesman::DeleteUser.go(user) }
|
270
|
+
|
271
|
+
it 'executes successfully' do
|
272
|
+
expect(outcome.success?).to be true
|
273
|
+
expect(outcome.result).to be true
|
274
|
+
end
|
275
|
+
|
276
|
+
it 'deletes record' do
|
277
|
+
expect { outcome }.to change(TradesmanSpec::User, :count).by(-1)
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
context 'when input parameters are invalid' do
|
282
|
+
let(:outcome) { Tradesman::DeleteUser.go(999) }
|
156
283
|
it 'returns an invalid outcome' do
|
157
284
|
expect(outcome.success?).to be false
|
158
285
|
expect(outcome.type).to eq :validation
|
159
286
|
end
|
160
287
|
end
|
288
|
+
|
289
|
+
context 'multiple records' do
|
290
|
+
let(:valid_params) { { last_name: 'Turner' } }
|
291
|
+
let(:outcome) { Tradesman::DeleteStrictUser.go(records) }
|
292
|
+
|
293
|
+
context 'passing array of ids' do
|
294
|
+
let(:records) { Tradesman::CreateStrictUser.go([valid_params, valid_params, valid_params]).result }
|
295
|
+
|
296
|
+
it 'deletes all records' do
|
297
|
+
expect(outcome.result.length).to eq records.length
|
298
|
+
expect(outcome.result.uniq.first).to eq true
|
299
|
+
end
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
context '#go!' do
|
305
|
+
context 'Create' do
|
306
|
+
context 'when parameters are valid' do
|
307
|
+
let(:outcome) { Tradesman::CreateUser.go!(last_name: 'Turner') }
|
308
|
+
|
309
|
+
it 'creates a new record' do
|
310
|
+
expect(outcome.success?).to be true
|
311
|
+
expect(outcome.result.id.is_a? Integer).to be true
|
312
|
+
end
|
313
|
+
|
314
|
+
it 'returns Horza Entity' do
|
315
|
+
expect(outcome.result.is_a? Horza::Entities::Single).to be true
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
context 'when parameters are invalid' do
|
320
|
+
let(:outcome) { Tradesman::CreateStrictUser.go!({}) }
|
321
|
+
it 'throws error' do
|
322
|
+
expect { outcome }.to raise_error Tradesman::Invalid
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
context 'for parent' do
|
327
|
+
let(:employer) { TradesmanSpec::Employer.create }
|
328
|
+
let(:outcome) { Tradesman::CreateUserForEmployer.go!(employer.id, last_name: 'Turner') }
|
329
|
+
|
330
|
+
it 'creates a new record' do
|
331
|
+
expect(outcome.success?).to be true
|
332
|
+
expect(outcome.result.id.is_a? Integer).to be true
|
333
|
+
end
|
334
|
+
|
335
|
+
it 'associates child with parent' do
|
336
|
+
expect(outcome.result.employer_id).to eq employer.id
|
337
|
+
end
|
338
|
+
|
339
|
+
it 'associates parent with child' do
|
340
|
+
outcome
|
341
|
+
expect(employer.users.first.id).to eq outcome.result.id
|
342
|
+
end
|
343
|
+
end
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
context 'Update' do
|
348
|
+
let(:user) { TradesmanSpec::User.create(last_name: 'Smith') }
|
349
|
+
context 'when parameters are valid' do
|
350
|
+
let(:outcome) { Tradesman::UpdateUser.go!(user.id, last_name: 'Turner') }
|
351
|
+
|
352
|
+
it 'executes successfully' do
|
353
|
+
expect(outcome.success?).to be true
|
354
|
+
end
|
355
|
+
|
356
|
+
it 'updates record' do
|
357
|
+
expect(outcome.result.last_name).to eq 'Turner'
|
358
|
+
expect(user.reload.last_name).to eq 'Turner'
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
context 'when parameters are invalid' do
|
363
|
+
let(:strict_user) { TradesmanSpec::StrictUser.create(last_name: 'Smith') }
|
364
|
+
let(:outcome) { Tradesman::UpdateStrictUser.go!(strict_user, last_name: nil) }
|
365
|
+
|
366
|
+
it 'throws error' do
|
367
|
+
expect { outcome }.to raise_error Tradesman::Invalid
|
368
|
+
end
|
369
|
+
end
|
161
370
|
end
|
162
371
|
|
163
372
|
context 'Delete' do
|
164
373
|
context 'when parameters are valid' do
|
165
374
|
let!(:user) { TradesmanSpec::User.create }
|
166
|
-
let(:outcome) { Tradesman::DeleteUser.
|
375
|
+
let(:outcome) { Tradesman::DeleteUser.go!(user) }
|
167
376
|
|
168
377
|
it 'executes successfully' do
|
169
378
|
expect(outcome.success?).to be true
|
@@ -176,7 +385,7 @@ describe Tradesman do
|
|
176
385
|
end
|
177
386
|
|
178
387
|
context 'when input parameters are invalid' do
|
179
|
-
let(:outcome) { Tradesman::DeleteUser.
|
388
|
+
let(:outcome) { Tradesman::DeleteUser.go(999) }
|
180
389
|
it 'returns an invalid outcome' do
|
181
390
|
expect(outcome.success?).to be false
|
182
391
|
expect(outcome.type).to eq :validation
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tradesman
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Blake Turner
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-06-
|
12
|
+
date: 2015-06-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: horza
|
@@ -17,14 +17,14 @@ dependencies:
|
|
17
17
|
requirements:
|
18
18
|
- - "~>"
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: 0.3.
|
20
|
+
version: 0.3.5
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
25
|
- - "~>"
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
version: 0.3.
|
27
|
+
version: 0.3.5
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: tzu
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
@@ -138,10 +138,13 @@ files:
|
|
138
138
|
- lib/tradesman/builders/create_for_parent.rb
|
139
139
|
- lib/tradesman/builders/delete.rb
|
140
140
|
- lib/tradesman/builders/update.rb
|
141
|
+
- lib/tradesman/class_methods.rb
|
141
142
|
- lib/tradesman/configuration.rb
|
143
|
+
- lib/tradesman/error_handling.rb
|
142
144
|
- lib/tradesman/errors.rb
|
145
|
+
- lib/tradesman/mixins/existing_records_multiple_execute.rb
|
146
|
+
- lib/tradesman/mixins/new_records_multiple_execute.rb
|
143
147
|
- lib/tradesman/parser.rb
|
144
|
-
- lib/tradesman/run_methods.rb
|
145
148
|
- lib/tradesman/template.rb
|
146
149
|
- spec/builders_spec.rb
|
147
150
|
- spec/parser_spec.rb
|