blacksheep 0.2.0 → 0.3.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 75dfef125950bec755e918dba9e56bf6877ab8a3baedc2e42d16b62e31aa395c
4
- data.tar.gz: 4ef04a290cd93670d126e910022cada3a16bb446af06eb26e759073c87e2a3b6
3
+ metadata.gz: f5e427c080e5f5eaf01f76d9436ff18a36e183318acb2b942105566b34be7c03
4
+ data.tar.gz: 22221c3900e3dd7d09c796e15e14d765c07cd307add2bbb39696b0767a17f088
5
5
  SHA512:
6
- metadata.gz: '0084555561e9b92801cf7524379c6e3523eda987a612beb869f8be81abf69c4ebba673ebf609c1310074f7f2d65c954998061cb70701e1052a6efb6507431eeb'
7
- data.tar.gz: d5e729097addb0df435e051c8289de2e8c0ca06d1d17d1690c630ab251a657d169719b5dc70cde2744537aac5f0cf544d9ee05d2596668151ff306609d5054b2
6
+ metadata.gz: cf17a2e2d7732162e0578567d8f04206da221f63d766294670c8b549126e24dd43d5a56451eabb4af6a8a37889ea4aa483a9c77b85c85b38308aec6fe76550c0
7
+ data.tar.gz: 02cfecdffd2c6d09c3dca2440b6f130e33ae564ab6ba06ba729733f1c2bcc0d9c6605e8db2ef86e307cce4f7bc9250da0f133cb24551b2ad32337ac7d1e23f54
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- blacksheep (0.1.0)
4
+ blacksheep (0.3.2)
5
5
  dry-matcher
6
6
 
7
7
  GEM
@@ -38,4 +38,4 @@ DEPENDENCIES
38
38
  rspec (~> 3.0)
39
39
 
40
40
  BUNDLED WITH
41
- 1.17.2
41
+ 1.17.3
data/README.md CHANGED
@@ -24,24 +24,24 @@ Or install it yourself as:
24
24
 
25
25
  ### Actions
26
26
 
27
- Core if blacksheep is the Blacksheep::Action. It provides basic fuctionality to handle rest API actions - but can handle other actions as well. The core methods of Actions are:
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
28
 
29
- * #perform, and…
30
- * #call
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
31
 
32
32
  `#perform` takes a block that is executed with the params passed. #perform has the following api:
33
33
  `#perform(params, current_user: (default to nil), **options)`
34
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`
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
36
 
37
37
 
38
38
  ```ruby
39
- ##perform sample
39
+ #perform sample
40
40
  action_result = Blacksheep::Action.new.perform(params) do |params|
41
41
  # do somethin with the params that return a `Blacksheep::ActionResult`
42
42
  end
43
43
 
44
- ##perform sample
44
+ #call sample
45
45
  action_result = MyAction.new.call(params, current_user: current_user)
46
46
  ```
47
47
 
@@ -50,14 +50,14 @@ action_result = MyAction.new.call(params, current_user: current_user)
50
50
 
51
51
  ### Decorators
52
52
 
53
- This alone does not give any benefit. It more interesting to modifiy the action with decorators such as:
53
+ This alone does not give any benefit. Modifying the action with decorators adds additional functionality:
54
54
 
55
55
  * `JsonTransformer`
56
56
  * `Localizer`
57
57
  * `DefaultErrorHandler`
58
58
  * `ResultMatcher`
59
59
 
60
- The decaorators can be configured globaly by defining them in an initializer.
60
+ The decaorators can be configured globally by defining them in an initializer.
61
61
 
62
62
  ```ruby
63
63
  # Defining decorator wheras innermost is first
@@ -74,7 +74,7 @@ A localizer sets the I18n locale when passed in a request parameter named `_loca
74
74
 
75
75
  #### Blacksheep::Decorators::DefaultErrorHandler
76
76
 
77
- A default error handler can be used in API opertions. The handler catches an error and returns a JsonResultObject such as
77
+ A default error handler can be used in API opertions. The handler catches an error and returns an ActionResult such as
78
78
 
79
79
  ```ruby
80
80
  def handle_exception(exception)
@@ -93,20 +93,20 @@ def handle_exception(exception)
93
93
  end
94
94
  ```
95
95
 
96
- You can write your own Errorhandler by including the module `Blacksheep::Decorators::ErrorHandler` and implementing the method `#handle(exception)`.
96
+ You can write your own ErrorHandler by including the module `Blacksheep::Decorators::ErrorHandler` and implementing the method `#handle_exception(<Exception>)`.
97
97
 
98
98
 
99
99
  #### Blacksheep::Decorators::JsonTransformer
100
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 tranforms 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 paramter keys are tranformed to `snake_case` before going into the action and are transformed back into CamelCase when leaving the operation.
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
103
 
104
104
  If JsonTransfomer is used the action should return a simple JSON structure which is transfformed and stored in an ActionResult.
105
105
 
106
106
 
107
107
  #### Blacksheep::Decorators::ResultMatcher
108
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 matcher decorator enables to write a matchers such as e.g.
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
110
 
111
111
  ```ruby
112
112
  MyAction.new.call(params) do |m|
@@ -122,7 +122,7 @@ MyAction.new.call(params) do |m|
122
122
  end
123
123
  ```
124
124
 
125
- The action has to return a Blacksheep::ActionResult which is check for status :ok in sucess case and any other status in failure case.
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
126
 
127
127
 
128
128
  ## Development
@@ -134,7 +134,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
134
134
  ```
135
135
  gem build blacksheep
136
136
  gem push blacksheep-0.x.y.gem
137
- ```
137
+ ``
138
138
 
139
139
  ## Contributing
140
140
 
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
- # spec.metadata["source_code_uri"] = "Put your gem's public repo URL here."
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,9 +1,12 @@
1
1
  require "blacksheep/version"
2
2
  require "blacksheep/action_result"
3
+ require "blacksheep/action_error"
3
4
  require "blacksheep/action_decorator"
5
+ require "blacksheep/decorators/error_handler"
4
6
  require "blacksheep/decorators/default_error_handler"
5
7
  require "blacksheep/decorators/json_transformer"
6
8
  require "blacksheep/decorators/result_matcher"
9
+ require "blacksheep/decorators/localizer"
7
10
  require "blacksheep/action"
8
11
  require "blacksheep/version"
9
12
 
@@ -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|
@@ -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,16 @@
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', status: :internal_server_error)
8
+ @identifier = identifier
9
+ @title = title
10
+ @status = status
11
+
12
+ super(message)
13
+ end
14
+
15
+ end
16
+ end
@@ -8,6 +8,33 @@ module Blacksheep
8
8
  @status = status
9
9
  end
10
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
+
11
38
  def set_data(value)
12
39
  @data = value
13
40
 
@@ -7,64 +7,57 @@ module Blacksheep
7
7
  def handle(exception)
8
8
  json = status = nil
9
9
 
10
- # case exception
11
- # when Exceptions::ValidationException
12
- # errors = []
13
- # exception.model.errors.each do |attribute, message|
14
- # errors << {
15
- # title: "'#{attribute}' validation error",
16
- # detail: message,
17
- # }
18
- # end
19
- # json = {
20
- # errors: errors
21
- # }
22
- # status = :unprocessable_entity # 422
23
- # when Pundit::NotAuthorizedError
24
- # json = {
25
- # errors: [
26
- # pointer: {
27
- # source: not_authorized_pointer(exception)
28
- # },
29
- # title: "#{exception.class}",
30
- # detail: "#{exception.message}",
31
- # ]
32
- # }
33
- # status = :unauthorized # 401
34
- # when Exceptions::AuthenticationInvalid
35
- # json = {
36
- # errors: [
37
- # pointer: {
38
- # source: 'Secured Module'
39
- # },
40
- # title: "#{exception.class}",
41
- # detail: "#{exception.message}",
42
- # ]
43
- # }
44
- # status = :unauthorized # 401
45
- # else
46
- # json = {
47
- # errors: [
48
- # pointer: {
49
- # source: 'Internal'
50
- # },
51
- # title: "#{exception.class}",
52
- # detail: "#{exception.message}",
53
- # ]
54
- # }
55
- # status = :internal_server_error # 500
56
- # end
10
+ case exception
11
+ when Blacksheep::ActionError
12
+ json = {
13
+ errors: [
14
+ pointer: {
15
+ source: exception.backtrace.first,
16
+ identifier: exception.identifier,
17
+ },
18
+ title: exception.title,
19
+ detail: exception.message,
20
+ ]
21
+ }
57
22
 
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
23
+ status = exception.status
24
+
25
+ # when Pundit::NotAuthorizedError
26
+ # json = {
27
+ # errors: [
28
+ # pointer: {
29
+ # source: not_authorized_pointer(exception)
30
+ # },
31
+ # title: "#{exception.class}",
32
+ # detail: "#{exception.message}",
33
+ # ]
34
+ # }
35
+ # status = :unauthorized # 401
36
+ # when Exceptions::AuthenticationInvalid
37
+ # json = {
38
+ # errors: [
39
+ # pointer: {
40
+ # source: 'Secured Module'
41
+ # },
42
+ # title: "#{exception.class}",
43
+ # detail: "#{exception.message}",
44
+ # ]
45
+ # }
46
+ # status = :unauthorized # 401
47
+
48
+ else
49
+ json = {
50
+ errors: [
51
+ pointer: {
52
+ source: 'Internal'
53
+ },
54
+ title: "#{exception.class}",
55
+ detail: "#{exception.message}",
56
+ ]
57
+ }
58
+ end
59
+
60
+ status ||= :internal_server_error
68
61
 
69
62
  ActionResult.new(json, status)
70
63
  end
@@ -1,7 +1,7 @@
1
1
  module Blacksheep
2
2
  module Decorators
3
- # @class Blacksheep::Decorators::ErrorHandler
4
- class ErrorHandler
3
+ # @module Blacksheep::Decorators::ErrorHandler
4
+ module ErrorHandler
5
5
 
6
6
  def call(*)
7
7
  super
@@ -5,10 +5,10 @@ module Blacksheep
5
5
 
6
6
  attr_reader :case, :params
7
7
 
8
- def call(params, **options)
8
+ def call(params, current_user: nil, **options)
9
9
  detect_case(params)
10
10
 
11
- transformed_params = self.transformed_params(params)
11
+ transformed_params = self.transform_params(params)
12
12
 
13
13
  json = super(transformed_params, **options)
14
14
 
@@ -20,9 +20,10 @@ module Blacksheep
20
20
  def perform(params, current_user: nil, **options, &block)
21
21
  detect_case(params)
22
22
 
23
- transformed_params = self.transformed_params(params)
23
+ transformed_params = self.transform_params(params)
24
+
25
+ json = super(transformed_params, current_user: current_user, **options, &block)
24
26
 
25
- json = block.call(transformed_params)
26
27
  transformed_json = transform_result(json)
27
28
 
28
29
  ActionResult.new(transformed_json, :ok)
@@ -34,7 +35,7 @@ module Blacksheep
34
35
  #
35
36
  # @return [Array, Hash] The params converted into snake_case
36
37
  # @see #snakecase_keys
37
- def transformed_params(params)
38
+ def transform_params(params)
38
39
  case @case
39
40
  when 'snake', 'as_is'
40
41
  params
@@ -1,10 +1,10 @@
1
1
  module Blacksheep
2
2
  module Decorators
3
3
 
4
- # @class Blacksheep::Decorators::Localozer
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
@@ -1,3 +1,3 @@
1
1
  module Blacksheep
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.2"
3
3
  end
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.2.0
4
+ version: 0.3.2
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-17 00:00:00.000000000 Z
11
+ date: 2021-06-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dry-matcher
@@ -87,6 +87,7 @@ 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
90
91
  - lib/blacksheep/action_result.rb
91
92
  - lib/blacksheep/decorators/default_error_handler.rb
92
93
  - lib/blacksheep/decorators/error_handler.rb
@@ -99,6 +100,7 @@ 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: