blacksheep 0.1.0 → 0.2.0

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: 5e39f0b5524839016bc9a6811e51257f49a2d5f00cf42d3d9fe07ab01de6b602
4
- data.tar.gz: c0d169df550b722a11ffa2aaf7ea0ef5657f3c64ad5f7b8b6ac2c10419ba7ef0
3
+ metadata.gz: 75dfef125950bec755e918dba9e56bf6877ab8a3baedc2e42d16b62e31aa395c
4
+ data.tar.gz: 4ef04a290cd93670d126e910022cada3a16bb446af06eb26e759073c87e2a3b6
5
5
  SHA512:
6
- metadata.gz: 589637c6979dbaebe1756f95ebe0038a7b707059b4a809f56d1d6575bbd4b5e2f8822bb54815e93491f0517b22a71ccb06d690da05b5396ea30fbe6c9acabb59
7
- data.tar.gz: b12064a64112255dc2b75aacf1a3ff2245131c96ccd5a12a863242e5642c10d97096f19010981c97b53940a905988bffd04508d77f337846e24dded666e874de
6
+ metadata.gz: '0084555561e9b92801cf7524379c6e3523eda987a612beb869f8be81abf69c4ebba673ebf609c1310074f7f2d65c954998061cb70701e1052a6efb6507431eeb'
7
+ data.tar.gz: d5e729097addb0df435e051c8289de2e8c0ca06d1d17d1690c630ab251a657d169719b5dc70cde2744537aac5f0cf544d9ee05d2596668151ff306609d5054b2
data/README.md CHANGED
@@ -22,7 +22,108 @@ Or install it yourself as:
22
22
 
23
23
  ## Usage
24
24
 
25
- TODO: Write usage instructions here
25
+ ### Actions
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:
28
+
29
+ * #perform, and…
30
+ * #call
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`
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
+ ##perform 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. It more interesting to modifiy the action with decorators such as:
54
+
55
+ * `JsonTransformer`
56
+ * `Localizer`
57
+ * `DefaultErrorHandler`
58
+ * `ResultMatcher`
59
+
60
+ The decaorators can be configured globaly 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 a JsonResultObject 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)`.
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 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.
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 matcher decorator enables to write a matchers such as e.g.
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 check for status :ok in sucess 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/lib/blacksheep.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  require "blacksheep/version"
2
- require "blacksheep/json_meta"
3
- require "blacksheep/json_result"
2
+ require "blacksheep/action_result"
4
3
  require "blacksheep/action_decorator"
5
4
  require "blacksheep/decorators/default_error_handler"
6
5
  require "blacksheep/decorators/json_transformer"
@@ -57,8 +57,8 @@ module Blacksheep
57
57
  block.call(params)
58
58
  end
59
59
 
60
- def json_result(json, status: :ok)
61
- JsonResult.new(json, status)
60
+ def action_result(data, status: :ok)
61
+ ActionResult.new(data, status)
62
62
  end
63
63
 
64
64
  end
@@ -1,15 +1,15 @@
1
1
  module Blacksheep
2
- class JsonResult
2
+ class ActionResult
3
3
 
4
- attr_reader :json, :status
4
+ attr_reader :data, :status
5
5
 
6
- def initialize(json, status)
7
- @json = json
6
+ def initialize(data, status)
7
+ @data = data
8
8
  @status = status
9
9
  end
10
10
 
11
- def set_json(value)
12
- @json = value
11
+ def set_data(value)
12
+ @data = value
13
13
 
14
14
  self
15
15
  end
@@ -24,9 +24,9 @@ module Blacksheep
24
24
  @status == :ok
25
25
  end
26
26
 
27
- def render(json_wrap: 'data')
27
+ def render_json(json_wrap: 'data')
28
28
  {
29
- json: wrap(json, json_wrap: json_wrap),
29
+ json: wrap(@data, json_wrap: json_wrap),
30
30
  status: status
31
31
  }
32
32
  end
@@ -2,19 +2,7 @@ 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
8
  json = status = nil
@@ -78,7 +66,7 @@ module Blacksheep
78
66
  }
79
67
  status = :internal_server_error # 500
80
68
 
81
- JsonResult.new(json, status)
69
+ ActionResult.new(json, status)
82
70
  end
83
71
 
84
72
  # def not_authorized_pointer(exception)
@@ -0,0 +1,24 @@
1
+ module Blacksheep
2
+ module Decorators
3
+ # @class Blacksheep::Decorators::ErrorHandler
4
+ class 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
@@ -6,7 +6,6 @@ module Blacksheep
6
6
  attr_reader :case, :params
7
7
 
8
8
  def call(params, **options)
9
- puts transformer: "*" * 50
10
9
  detect_case(params)
11
10
 
12
11
  transformed_params = self.transformed_params(params)
@@ -15,7 +14,7 @@ module Blacksheep
15
14
 
16
15
  transformed_json = transform_result(json)
17
16
 
18
- JsonResult.new(transformed_json, :ok)
17
+ ActionResult.new(transformed_json, :ok)
19
18
  end
20
19
 
21
20
  def perform(params, current_user: nil, **options, &block)
@@ -26,7 +25,7 @@ module Blacksheep
26
25
  json = block.call(transformed_params)
27
26
  transformed_json = transform_result(json)
28
27
 
29
- JsonResult.new(transformed_json, :ok)
28
+ ActionResult.new(transformed_json, :ok)
30
29
  end
31
30
 
32
31
 
@@ -42,7 +41,7 @@ module Blacksheep
42
41
  when 'camel'
43
42
  snakecase_keys(params)
44
43
  else
45
- raise Blackseep::Error, "unknown_case #{@case}"
44
+ raise Blacksheep::Error, "unknown_case #{@case}"
46
45
  end
47
46
  end
48
47
 
@@ -54,14 +53,22 @@ module Blacksheep
54
53
  # @return [Array, Hash] The rsult structure with keys converted to source caseing
55
54
  # @see #camelize_keys
56
55
  def transform_result(obj)
57
- case @case
56
+ is_action_result, data = if obj.kind_of?(Blacksheep::ActionResult)
57
+ [ true, obj.data ]
58
+ else
59
+ [ false, obj ]
60
+ end
61
+
62
+ converted_data = case @case
58
63
  when 'snake', 'as_is'
59
- obj
64
+ data
60
65
  when 'camel'
61
- camelize_keys(obj)
66
+ camelize_keys(data)
62
67
  else
63
- raise Blackseep::Error, "unknown_case #{@case}"
68
+ raise Blacksheep::Error, "unknown_case #{@case}"
64
69
  end
70
+
71
+ is_action_result ? obj.set_data(converted_data) : converted_data
65
72
  end
66
73
 
67
74
  #
@@ -5,19 +5,19 @@ module Blacksheep
5
5
  # @class Blacksheep::Decorators::ResultMatcher
6
6
  class ResultMatcher < ActionDecorator
7
7
  Matcher = -> {
8
- # Match `json_result` with status :ok for success
9
- success_case = Dry::Matcher::Case.new do |json_result, _|
10
- if json_result.success?
11
- json_result
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 `json_result` with status not :ok` for failure - other status' can be distinguished
19
- failure_case = Dry::Matcher::Case.new do |json_result, patterns|
20
- if !json_result.success! && (patterns.empty? || patterns.include?(json_result.status))
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 Blackseep::Error, 'JsonResultMatcher does not support #perform'
38
+ raise Blacksheep::Error, 'ResultMatcher does not support #perform'
40
39
  end
41
40
 
42
41
  end
@@ -1,3 +1,3 @@
1
1
  module Blacksheep
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: blacksheep
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martin Schweizer
@@ -87,12 +87,12 @@ files:
87
87
  - lib/blacksheep.rb
88
88
  - lib/blacksheep/action.rb
89
89
  - lib/blacksheep/action_decorator.rb
90
+ - lib/blacksheep/action_result.rb
90
91
  - lib/blacksheep/decorators/default_error_handler.rb
92
+ - lib/blacksheep/decorators/error_handler.rb
91
93
  - lib/blacksheep/decorators/json_transformer.rb
92
94
  - lib/blacksheep/decorators/localizer.rb
93
95
  - lib/blacksheep/decorators/result_matcher.rb
94
- - lib/blacksheep/json_meta.rb
95
- - lib/blacksheep/json_result.rb
96
96
  - lib/blacksheep/version.rb
97
97
  homepage: http://verticonaut.me
98
98
  licenses:
@@ -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