blacksheep 0.2.0 → 0.3.2

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