blacksheep 0.1.0 → 0.3.1
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 +4 -4
- data/Gemfile.lock +2 -2
- data/README.md +107 -1
- data/blacksheep.gemspec +1 -1
- data/lib/blacksheep.rb +4 -2
- data/lib/blacksheep/action.rb +9 -4
- data/lib/blacksheep/action_decorator.rb +20 -0
- data/lib/blacksheep/action_error.rb +15 -0
- data/lib/blacksheep/action_result.rb +70 -0
- data/lib/blacksheep/decorators/default_error_handler.rb +50 -72
- data/lib/blacksheep/decorators/error_handler.rb +24 -0
- data/lib/blacksheep/decorators/json_transformer.rb +21 -13
- data/lib/blacksheep/decorators/localizer.rb +4 -3
- data/lib/blacksheep/decorators/result_matcher.rb +8 -9
- data/lib/blacksheep/version.rb +1 -1
- metadata +6 -4
- data/lib/blacksheep/json_meta.rb +0 -41
- data/lib/blacksheep/json_result.rb +0 -43
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7e104e67c03822bfb437736bf0beb1dca0cb9c4ced32a3027c359193cf730573
|
4
|
+
data.tar.gz: 6bff8f6260ab533267122865740890643bc1cd2e59870cfb48bc85c47fb8a8d3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 34aed33d507dec1a11a3b372bb8fcb5cc5d824ea213e512ef2b5ecc27f5e89cb3550d1c1b6e6d0a02c7a4bd380a103373ad30e4a4317d48cc75287633be22ba5
|
7
|
+
data.tar.gz: 3b95215a11cc3f7937f3db323de40596d15839adc87e644eb2cf7a99e79f621c687faa45f4b62446212280e3b13b8750951147e29968018a69b55da446ff3861
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -22,7 +22,108 @@ Or install it yourself as:
|
|
22
22
|
|
23
23
|
## Usage
|
24
24
|
|
25
|
-
|
25
|
+
### Actions
|
26
|
+
|
27
|
+
Core of blacksheep is the `Blacksheep::Action`. It provides basic functionality to handle rest API actions - but can handle other actions as well. The core methods of actions are:
|
28
|
+
|
29
|
+
* #perform with a block that implements the action
|
30
|
+
* #call on an action instance for processing and a potential block for result matching (see dcorators below).
|
31
|
+
|
32
|
+
`#perform` takes a block that is executed with the params passed. #perform has the following api:
|
33
|
+
`#perform(params, current_user: (default to nil), **options)`
|
34
|
+
|
35
|
+
`#call` can be used when a Blacksheep::Action is sublassed as an action processing its opertation in a call method with the same signature of `#perform`. When using the `ResultMatcher` decorator a block can be used for result matching.
|
36
|
+
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
#perform sample
|
40
|
+
action_result = Blacksheep::Action.new.perform(params) do |params|
|
41
|
+
# do somethin with the params that return a `Blacksheep::ActionResult`
|
42
|
+
end
|
43
|
+
|
44
|
+
#call sample
|
45
|
+
action_result = MyAction.new.call(params, current_user: current_user)
|
46
|
+
```
|
47
|
+
|
48
|
+
`Blacksheeep::ActionResult` has a data and a status attribute. In case of json api actions its expected to store a json response into the data attribute, and the respective http status into the status attribute.
|
49
|
+
|
50
|
+
|
51
|
+
### Decorators
|
52
|
+
|
53
|
+
This alone does not give any benefit. Modifying the action with decorators adds additional functionality:
|
54
|
+
|
55
|
+
* `JsonTransformer`
|
56
|
+
* `Localizer`
|
57
|
+
* `DefaultErrorHandler`
|
58
|
+
* `ResultMatcher`
|
59
|
+
|
60
|
+
The decaorators can be configured globally by defining them in an initializer.
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
# Defining decorator wheras innermost is first
|
64
|
+
Blacksheep::Action.add_decorator(Blacksheep::Decorators::Localizer)
|
65
|
+
Blacksheep::Action.add_decorator(Blacksheep::Decorators::DefaultErrorHandler)
|
66
|
+
Blacksheep::Action.add_decorator(Blacksheep::Decorators::JsonTransformer)
|
67
|
+
Blacksheep::Action.add_decorator(Blacksheep::Decorators::ResultMatcher)
|
68
|
+
```
|
69
|
+
|
70
|
+
#### Blacksheep::Decorators::Localizer
|
71
|
+
|
72
|
+
A localizer sets the I18n locale when passed in a request parameter named `_locale`.
|
73
|
+
|
74
|
+
|
75
|
+
#### Blacksheep::Decorators::DefaultErrorHandler
|
76
|
+
|
77
|
+
A default error handler can be used in API opertions. The handler catches an error and returns an ActionResult such as…
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
def handle_exception(exception)
|
81
|
+
json = {
|
82
|
+
errors: [
|
83
|
+
pointer: {
|
84
|
+
source: 'Internal'
|
85
|
+
},
|
86
|
+
title: "#{exception.class}",
|
87
|
+
detail: "#{exception.message}",
|
88
|
+
]
|
89
|
+
}
|
90
|
+
status = :internal_server_error # 500
|
91
|
+
|
92
|
+
ActionResult.new(json, status)
|
93
|
+
end
|
94
|
+
```
|
95
|
+
|
96
|
+
You can write your own ErrorHandler by including the module `Blacksheep::Decorators::ErrorHandler` and implementing the method `#handle_exception(<Exception>)`.
|
97
|
+
|
98
|
+
|
99
|
+
#### Blacksheep::Decorators::JsonTransformer
|
100
|
+
|
101
|
+
Assuming the params is a json payload with a specific caseing (e.g. camelCase when used in a JS application such as Vue) the JsonTransfomer takes the params and transforms it's keys into snake_case as used in ruby often.
|
102
|
+
The request has to define the case passed (and hence desired response casing) in the parameter `_case`. If the case is requests as `camel` then parameter keys are transformed to `snake_case` before beeing passed into the action and are transformed back into CamelCase when leaving the operation.
|
103
|
+
|
104
|
+
If JsonTransfomer is used the action should return a simple JSON structure which is transfformed and stored in an ActionResult.
|
105
|
+
|
106
|
+
|
107
|
+
#### Blacksheep::Decorators::ResultMatcher
|
108
|
+
|
109
|
+
This decorator can be used when implementing your own actions by subclassing `Blacksheep::Action` and using the `#call` style for processing. Adding the `ResultMatcher` decorator enables to write a matcher block such as…
|
110
|
+
|
111
|
+
```ruby
|
112
|
+
MyAction.new.call(params) do |m|
|
113
|
+
m.success do |action_result|
|
114
|
+
# do something in success case
|
115
|
+
end
|
116
|
+
m.failure :unauthorized do |action_result|
|
117
|
+
# special handling for unauthorized access
|
118
|
+
end
|
119
|
+
m.failure do |v|
|
120
|
+
# any other failure
|
121
|
+
end
|
122
|
+
end
|
123
|
+
```
|
124
|
+
|
125
|
+
The action has to return a Blacksheep::ActionResult which is checked for status `:ok` for success case and any other status in failure case.
|
126
|
+
|
26
127
|
|
27
128
|
## Development
|
28
129
|
|
@@ -30,6 +131,11 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
|
30
131
|
|
31
132
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
32
133
|
|
134
|
+
```
|
135
|
+
gem build blacksheep
|
136
|
+
gem push blacksheep-0.x.y.gem
|
137
|
+
``
|
138
|
+
|
33
139
|
## Contributing
|
34
140
|
|
35
141
|
Bug reports and pull requests are welcome on GitHub at https://github.com/verticonaut/blacksheep.
|
data/blacksheep.gemspec
CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
|
|
18
18
|
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
19
19
|
if spec.respond_to?(:metadata)
|
20
20
|
spec.metadata["homepage_uri"] = spec.homepage
|
21
|
-
|
21
|
+
spec.metadata["source_code_uri"] = "https://github.com/verticonaut/blacksheep"
|
22
22
|
# spec.metadata["changelog_uri"] = "Put your gem's CHANGELOG.md URL here."
|
23
23
|
else
|
24
24
|
raise "RubyGems 2.0 or newer is required to protect against " \
|
data/lib/blacksheep.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
require "blacksheep/version"
|
2
|
-
require "blacksheep/
|
3
|
-
require "blacksheep/
|
2
|
+
require "blacksheep/action_result"
|
3
|
+
require "blacksheep/action_error"
|
4
4
|
require "blacksheep/action_decorator"
|
5
|
+
require "blacksheep/decorators/error_handler"
|
5
6
|
require "blacksheep/decorators/default_error_handler"
|
6
7
|
require "blacksheep/decorators/json_transformer"
|
7
8
|
require "blacksheep/decorators/result_matcher"
|
9
|
+
require "blacksheep/decorators/localizer"
|
8
10
|
require "blacksheep/action"
|
9
11
|
require "blacksheep/version"
|
10
12
|
|
data/lib/blacksheep/action.rb
CHANGED
@@ -28,11 +28,16 @@ module Blacksheep
|
|
28
28
|
@@decorators ||= []
|
29
29
|
end
|
30
30
|
|
31
|
+
#
|
32
|
+
# Adds a decorator to the list of decorated to be applied on Balcksheep::Actions
|
33
|
+
# @param decorator [type] [description]
|
34
|
+
#
|
35
|
+
# @return [type] [description]
|
31
36
|
def add_decorator(decorator)
|
32
|
-
decorators << decorator
|
37
|
+
decorators << decorator unless decorators.include?(decorator)
|
33
38
|
end
|
34
39
|
|
35
|
-
def new(*)
|
40
|
+
def new(*arguments, &block)
|
36
41
|
instance = super
|
37
42
|
|
38
43
|
decorators.each do |decorator|
|
@@ -57,8 +62,8 @@ module Blacksheep
|
|
57
62
|
block.call(params)
|
58
63
|
end
|
59
64
|
|
60
|
-
def
|
61
|
-
|
65
|
+
def action_result(data, status: :ok)
|
66
|
+
ActionResult.new(data, status)
|
62
67
|
end
|
63
68
|
|
64
69
|
end
|
@@ -1,9 +1,29 @@
|
|
1
1
|
require 'delegate'
|
2
2
|
|
3
3
|
module Blacksheep
|
4
|
+
# @class Blacksheep::ActionDecorator
|
4
5
|
class ActionDecorator < SimpleDelegator
|
6
|
+
|
7
|
+
# Access to the decorators class - since original class is overwritten to return the model class.
|
8
|
+
#
|
9
|
+
# @return [Class] The class of the deocrator.
|
10
|
+
# @see [#class]
|
11
|
+
alias_method :__class__, :class
|
12
|
+
|
5
13
|
def class
|
6
14
|
__getobj__.class
|
7
15
|
end
|
16
|
+
|
17
|
+
#
|
18
|
+
# Just for curiosity - get the decorators chain
|
19
|
+
#
|
20
|
+
# @return [type] [description]
|
21
|
+
def decorators_chain
|
22
|
+
decorated = __getobj__
|
23
|
+
chain = decorated.kind_of?(Blacksheep::ActionDecorator) ? decorated.decorators_chain : [ decorated.class ]
|
24
|
+
|
25
|
+
chain.unshift(self.__class__)
|
26
|
+
end
|
27
|
+
|
8
28
|
end
|
9
29
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Blacksheep
|
2
|
+
#
|
3
|
+
# @class Blacksheep::ActionError
|
4
|
+
class ActionError < StandardError
|
5
|
+
attr_reader :identifier, :title
|
6
|
+
|
7
|
+
def initialize(message, title: 'Error', identifier: 'undefined')
|
8
|
+
@identifier = identifier
|
9
|
+
@title = title
|
10
|
+
|
11
|
+
super(message)
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Blacksheep
|
2
|
+
class ActionResult
|
3
|
+
|
4
|
+
attr_reader :data, :status
|
5
|
+
|
6
|
+
def initialize(data, status)
|
7
|
+
@data = data
|
8
|
+
@status = status
|
9
|
+
end
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def success(message)
|
13
|
+
json = {
|
14
|
+
_meta: {
|
15
|
+
message: message
|
16
|
+
}
|
17
|
+
}
|
18
|
+
|
19
|
+
new(json, :ok)
|
20
|
+
end
|
21
|
+
|
22
|
+
def error(title: 'Error', message:, status: :internal_server_error, pointer: 'unspecified')
|
23
|
+
json = {
|
24
|
+
errors: [
|
25
|
+
pointer: {
|
26
|
+
source: pointer
|
27
|
+
},
|
28
|
+
title: title,
|
29
|
+
detail: message,
|
30
|
+
]
|
31
|
+
}
|
32
|
+
status = :internal_server_error
|
33
|
+
|
34
|
+
new(json, status)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def set_data(value)
|
39
|
+
@data = value
|
40
|
+
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
def set_status(value)
|
45
|
+
@status = value
|
46
|
+
|
47
|
+
self
|
48
|
+
end
|
49
|
+
|
50
|
+
def success?
|
51
|
+
@status == :ok
|
52
|
+
end
|
53
|
+
|
54
|
+
def render_json(json_wrap: 'data')
|
55
|
+
{
|
56
|
+
json: wrap(@data, json_wrap: json_wrap),
|
57
|
+
status: status
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def wrap(json, json_wrap:)
|
64
|
+
wrap = success? ? json_wrap : nil
|
65
|
+
|
66
|
+
wrap.present? ? { wrap => json } : json
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
@@ -2,83 +2,61 @@ module Blacksheep
|
|
2
2
|
module Decorators
|
3
3
|
# @class Blacksheep::Decorators::DefaultErrorHandler
|
4
4
|
class DefaultErrorHandler < ActionDecorator
|
5
|
-
|
6
|
-
def call(*)
|
7
|
-
puts error_handler: "*" * 50
|
8
|
-
super
|
9
|
-
rescue => exception
|
10
|
-
handle(exception)
|
11
|
-
end
|
12
|
-
|
13
|
-
def perform(*)
|
14
|
-
super
|
15
|
-
rescue => exception
|
16
|
-
handle(exception)
|
17
|
-
end
|
5
|
+
include ErrorHandler
|
18
6
|
|
19
7
|
def handle(exception)
|
20
|
-
json =
|
8
|
+
json = nil
|
9
|
+
status = :internal_server_error
|
10
|
+
|
11
|
+
case exception
|
12
|
+
when Blacksheep::ActionError
|
13
|
+
json = {
|
14
|
+
errors: [
|
15
|
+
pointer: {
|
16
|
+
source: exception.backtrace.first,
|
17
|
+
identifier: exception.identifier,
|
18
|
+
},
|
19
|
+
title: exception.title,
|
20
|
+
detail: exception.message,
|
21
|
+
]
|
22
|
+
}
|
21
23
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
# }
|
45
|
-
# status = :unauthorized # 401
|
46
|
-
# when Exceptions::AuthenticationInvalid
|
47
|
-
# json = {
|
48
|
-
# errors: [
|
49
|
-
# pointer: {
|
50
|
-
# source: 'Secured Module'
|
51
|
-
# },
|
52
|
-
# title: "#{exception.class}",
|
53
|
-
# detail: "#{exception.message}",
|
54
|
-
# ]
|
55
|
-
# }
|
56
|
-
# status = :unauthorized # 401
|
57
|
-
# else
|
58
|
-
# json = {
|
59
|
-
# errors: [
|
60
|
-
# pointer: {
|
61
|
-
# source: 'Internal'
|
62
|
-
# },
|
63
|
-
# title: "#{exception.class}",
|
64
|
-
# detail: "#{exception.message}",
|
65
|
-
# ]
|
66
|
-
# }
|
67
|
-
# status = :internal_server_error # 500
|
68
|
-
# end
|
24
|
+
# when Pundit::NotAuthorizedError
|
25
|
+
# json = {
|
26
|
+
# errors: [
|
27
|
+
# pointer: {
|
28
|
+
# source: not_authorized_pointer(exception)
|
29
|
+
# },
|
30
|
+
# title: "#{exception.class}",
|
31
|
+
# detail: "#{exception.message}",
|
32
|
+
# ]
|
33
|
+
# }
|
34
|
+
# status = :unauthorized # 401
|
35
|
+
# when Exceptions::AuthenticationInvalid
|
36
|
+
# json = {
|
37
|
+
# errors: [
|
38
|
+
# pointer: {
|
39
|
+
# source: 'Secured Module'
|
40
|
+
# },
|
41
|
+
# title: "#{exception.class}",
|
42
|
+
# detail: "#{exception.message}",
|
43
|
+
# ]
|
44
|
+
# }
|
45
|
+
# status = :unauthorized # 401
|
69
46
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
47
|
+
else
|
48
|
+
json = {
|
49
|
+
errors: [
|
50
|
+
pointer: {
|
51
|
+
source: 'Internal'
|
52
|
+
},
|
53
|
+
title: "#{exception.class}",
|
54
|
+
detail: "#{exception.message}",
|
55
|
+
]
|
56
|
+
}
|
57
|
+
end
|
80
58
|
|
81
|
-
|
59
|
+
ActionResult.new(json, status)
|
82
60
|
end
|
83
61
|
|
84
62
|
# def not_authorized_pointer(exception)
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Blacksheep
|
2
|
+
module Decorators
|
3
|
+
# @module Blacksheep::Decorators::ErrorHandler
|
4
|
+
module ErrorHandler
|
5
|
+
|
6
|
+
def call(*)
|
7
|
+
super
|
8
|
+
rescue => exception
|
9
|
+
handle(exception)
|
10
|
+
end
|
11
|
+
|
12
|
+
def perform(*)
|
13
|
+
super
|
14
|
+
rescue => exception
|
15
|
+
handle(exception)
|
16
|
+
end
|
17
|
+
|
18
|
+
def handle(exception)
|
19
|
+
raise Blacksheep::Error, 'Subclass responsibility'
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -5,28 +5,28 @@ module Blacksheep
|
|
5
5
|
|
6
6
|
attr_reader :case, :params
|
7
7
|
|
8
|
-
def call(params, **options)
|
9
|
-
puts transformer: "*" * 50
|
8
|
+
def call(params, current_user: nil, **options)
|
10
9
|
detect_case(params)
|
11
10
|
|
12
|
-
transformed_params = self.
|
11
|
+
transformed_params = self.transform_params(params)
|
13
12
|
|
14
13
|
json = super(transformed_params, **options)
|
15
14
|
|
16
15
|
transformed_json = transform_result(json)
|
17
16
|
|
18
|
-
|
17
|
+
ActionResult.new(transformed_json, :ok)
|
19
18
|
end
|
20
19
|
|
21
20
|
def perform(params, current_user: nil, **options, &block)
|
22
21
|
detect_case(params)
|
23
22
|
|
24
|
-
transformed_params = self.
|
23
|
+
transformed_params = self.transform_params(params)
|
24
|
+
|
25
|
+
json = super(transformed_params, current_user: current_user, **options, &block)
|
25
26
|
|
26
|
-
json = block.call(transformed_params)
|
27
27
|
transformed_json = transform_result(json)
|
28
28
|
|
29
|
-
|
29
|
+
ActionResult.new(transformed_json, :ok)
|
30
30
|
end
|
31
31
|
|
32
32
|
|
@@ -35,14 +35,14 @@ module Blacksheep
|
|
35
35
|
#
|
36
36
|
# @return [Array, Hash] The params converted into snake_case
|
37
37
|
# @see #snakecase_keys
|
38
|
-
def
|
38
|
+
def transform_params(params)
|
39
39
|
case @case
|
40
40
|
when 'snake', 'as_is'
|
41
41
|
params
|
42
42
|
when 'camel'
|
43
43
|
snakecase_keys(params)
|
44
44
|
else
|
45
|
-
raise
|
45
|
+
raise Blacksheep::Error, "unknown_case #{@case}"
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
@@ -54,14 +54,22 @@ module Blacksheep
|
|
54
54
|
# @return [Array, Hash] The rsult structure with keys converted to source caseing
|
55
55
|
# @see #camelize_keys
|
56
56
|
def transform_result(obj)
|
57
|
-
|
57
|
+
is_action_result, data = if obj.kind_of?(Blacksheep::ActionResult)
|
58
|
+
[ true, obj.data ]
|
59
|
+
else
|
60
|
+
[ false, obj ]
|
61
|
+
end
|
62
|
+
|
63
|
+
converted_data = case @case
|
58
64
|
when 'snake', 'as_is'
|
59
|
-
|
65
|
+
data
|
60
66
|
when 'camel'
|
61
|
-
camelize_keys(
|
67
|
+
camelize_keys(data)
|
62
68
|
else
|
63
|
-
raise
|
69
|
+
raise Blacksheep::Error, "unknown_case #{@case}"
|
64
70
|
end
|
71
|
+
|
72
|
+
is_action_result ? obj.set_data(converted_data) : converted_data
|
65
73
|
end
|
66
74
|
|
67
75
|
#
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module Blacksheep
|
2
2
|
module Decorators
|
3
3
|
|
4
|
-
# @class Blacksheep::Decorators::
|
4
|
+
# @class Blacksheep::Decorators::Localizer
|
5
5
|
class Localizer < ActionDecorator
|
6
6
|
|
7
|
-
def call(params, **)
|
7
|
+
def call(params, current_user: nil, **options)
|
8
8
|
if (locale = params[:_locale])
|
9
9
|
I18n.with_locale(locale) do
|
10
10
|
super
|
@@ -14,7 +14,8 @@ module Blacksheep
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
def perform(params, **)
|
17
|
+
def perform(params, current_user: nil, **options)
|
18
|
+
|
18
19
|
if (locale = params[:_locale])
|
19
20
|
I18n.with_locale(locale) do
|
20
21
|
super
|
@@ -5,19 +5,19 @@ module Blacksheep
|
|
5
5
|
# @class Blacksheep::Decorators::ResultMatcher
|
6
6
|
class ResultMatcher < ActionDecorator
|
7
7
|
Matcher = -> {
|
8
|
-
# Match `
|
9
|
-
success_case = Dry::Matcher::Case.new do |
|
10
|
-
if
|
11
|
-
|
8
|
+
# Match `action_result` with status :ok for success
|
9
|
+
success_case = Dry::Matcher::Case.new do |action_result, _|
|
10
|
+
if action_result.success?
|
11
|
+
action_result
|
12
12
|
else
|
13
13
|
# this is a constant from dry/core/constants
|
14
14
|
Dry::Matcher::Undefined
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
-
# Match `
|
19
|
-
failure_case = Dry::Matcher::Case.new do |
|
20
|
-
if !
|
18
|
+
# Match `action_result` with status not :ok` for failure - other status' can be distinguished
|
19
|
+
failure_case = Dry::Matcher::Case.new do |action_result, patterns|
|
20
|
+
if !action_result.success! && (patterns.empty? || patterns.include?(action_result.status))
|
21
21
|
value
|
22
22
|
else
|
23
23
|
Dry::Matcher::Undefined
|
@@ -31,12 +31,11 @@ module Blacksheep
|
|
31
31
|
include Dry::Matcher.for(:call, with: Matcher)
|
32
32
|
|
33
33
|
def call(*)
|
34
|
-
puts matcher: "*" * 50
|
35
34
|
super
|
36
35
|
end
|
37
36
|
|
38
37
|
def perform(*)
|
39
|
-
raise
|
38
|
+
raise Blacksheep::Error, 'ResultMatcher does not support #perform'
|
40
39
|
end
|
41
40
|
|
42
41
|
end
|
data/lib/blacksheep/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: blacksheep
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Martin Schweizer
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-05-
|
11
|
+
date: 2021-05-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dry-matcher
|
@@ -87,18 +87,20 @@ files:
|
|
87
87
|
- lib/blacksheep.rb
|
88
88
|
- lib/blacksheep/action.rb
|
89
89
|
- lib/blacksheep/action_decorator.rb
|
90
|
+
- lib/blacksheep/action_error.rb
|
91
|
+
- lib/blacksheep/action_result.rb
|
90
92
|
- lib/blacksheep/decorators/default_error_handler.rb
|
93
|
+
- lib/blacksheep/decorators/error_handler.rb
|
91
94
|
- lib/blacksheep/decorators/json_transformer.rb
|
92
95
|
- lib/blacksheep/decorators/localizer.rb
|
93
96
|
- lib/blacksheep/decorators/result_matcher.rb
|
94
|
-
- lib/blacksheep/json_meta.rb
|
95
|
-
- lib/blacksheep/json_result.rb
|
96
97
|
- lib/blacksheep/version.rb
|
97
98
|
homepage: http://verticonaut.me
|
98
99
|
licenses:
|
99
100
|
- MIT
|
100
101
|
metadata:
|
101
102
|
homepage_uri: http://verticonaut.me
|
103
|
+
source_code_uri: https://github.com/verticonaut/blacksheep
|
102
104
|
post_install_message:
|
103
105
|
rdoc_options: []
|
104
106
|
require_paths:
|
data/lib/blacksheep/json_meta.rb
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
module Blacksheep
|
2
|
-
class JsonMeta
|
3
|
-
|
4
|
-
attr_reader :json
|
5
|
-
|
6
|
-
def initialize(json = {})
|
7
|
-
@json = json
|
8
|
-
end
|
9
|
-
|
10
|
-
class << self
|
11
|
-
def success(title: nil, detail: nil)
|
12
|
-
new.success(title: title, detail: detail)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def success(title: nil, detail: nil)
|
17
|
-
result = {
|
18
|
-
success: true,
|
19
|
-
}
|
20
|
-
|
21
|
-
if title.present?
|
22
|
-
result[:title] = title
|
23
|
-
elsif detail.present?
|
24
|
-
result[:title] = 'Success'
|
25
|
-
end
|
26
|
-
|
27
|
-
result[:detail] = detail if detail.present?
|
28
|
-
|
29
|
-
json[:result] = result
|
30
|
-
|
31
|
-
self
|
32
|
-
end
|
33
|
-
|
34
|
-
def as_json
|
35
|
-
{
|
36
|
-
jsonMeta: json
|
37
|
-
}
|
38
|
-
end
|
39
|
-
|
40
|
-
end
|
41
|
-
end
|
@@ -1,43 +0,0 @@
|
|
1
|
-
module Blacksheep
|
2
|
-
class JsonResult
|
3
|
-
|
4
|
-
attr_reader :json, :status
|
5
|
-
|
6
|
-
def initialize(json, status)
|
7
|
-
@json = json
|
8
|
-
@status = status
|
9
|
-
end
|
10
|
-
|
11
|
-
def set_json(value)
|
12
|
-
@json = value
|
13
|
-
|
14
|
-
self
|
15
|
-
end
|
16
|
-
|
17
|
-
def set_status(value)
|
18
|
-
@status = value
|
19
|
-
|
20
|
-
self
|
21
|
-
end
|
22
|
-
|
23
|
-
def success?
|
24
|
-
@status == :ok
|
25
|
-
end
|
26
|
-
|
27
|
-
def render(json_wrap: 'data')
|
28
|
-
{
|
29
|
-
json: wrap(json, json_wrap: json_wrap),
|
30
|
-
status: status
|
31
|
-
}
|
32
|
-
end
|
33
|
-
|
34
|
-
private
|
35
|
-
|
36
|
-
def wrap(json, json_wrap:)
|
37
|
-
wrap = success? ? json_wrap : nil
|
38
|
-
|
39
|
-
wrap.present? ? { wrap => json } : json
|
40
|
-
end
|
41
|
-
|
42
|
-
end
|
43
|
-
end
|