trailblazer-endpoint 0.0.1 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +16 -0
- data/Appraisals +5 -0
- data/CHANGES.md +26 -0
- data/README.md +40 -5
- data/Rakefile +7 -1
- data/gemfiles/rails_app.gemfile +12 -0
- data/lib/trailblazer/endpoint.rb +29 -14
- data/lib/trailblazer/endpoint/adapter.rb +30 -121
- data/lib/trailblazer/endpoint/builder.rb +1 -1
- data/lib/trailblazer/endpoint/controller.rb +223 -0
- data/lib/trailblazer/endpoint/dsl.rb +29 -0
- data/lib/trailblazer/endpoint/options.rb +92 -0
- data/lib/trailblazer/endpoint/protocol.rb +5 -8
- data/lib/trailblazer/endpoint/version.rb +1 -1
- data/test/adapter/api_test.rb +6 -11
- data/test/adapter/web_test.rb +2 -5
- data/test/config_test.rb +128 -0
- data/test/docs/controller_test.rb +339 -58
- data/test/endpoint_test.rb +1 -1
- data/test/rails-app/.gitignore +8 -2
- data/test/rails-app/.ruby-version +1 -0
- data/test/rails-app/Gemfile +15 -9
- data/test/rails-app/Gemfile.lock +162 -121
- data/test/rails-app/app/concepts/app/api/v1/representer/errors.rb +16 -0
- data/test/rails-app/app/concepts/auth/jwt.rb +35 -0
- data/test/rails-app/app/concepts/auth/operation/authenticate.rb +32 -0
- data/test/rails-app/app/concepts/auth/operation/policy.rb +9 -0
- data/test/rails-app/app/concepts/song/cell/create.rb +4 -0
- data/test/rails-app/app/concepts/song/cell/new.rb +4 -0
- data/test/rails-app/app/concepts/song/operation/create.rb +17 -0
- data/test/rails-app/app/concepts/song/operation/show.rb +10 -0
- data/test/rails-app/app/concepts/song/representer.rb +5 -0
- data/test/rails-app/app/concepts/song/view/create.erb +1 -0
- data/test/rails-app/app/concepts/song/view/new.erb +1 -0
- data/test/rails-app/app/controllers/api/v1/songs_controller.rb +41 -0
- data/test/rails-app/app/controllers/application_controller.rb +8 -1
- data/test/rails-app/app/controllers/application_controller/api.rb +107 -0
- data/test/rails-app/app/controllers/application_controller/web.rb +44 -0
- data/test/rails-app/app/controllers/auth_controller.rb +44 -0
- data/test/rails-app/app/controllers/home_controller.rb +5 -0
- data/test/rails-app/app/controllers/songs_controller.rb +71 -13
- data/test/rails-app/app/models/song.rb +3 -0
- data/test/rails-app/app/models/user.rb +7 -0
- data/test/rails-app/bin/bundle +114 -0
- data/test/rails-app/bin/rails +4 -0
- data/test/rails-app/bin/rake +4 -0
- data/test/rails-app/bin/setup +33 -0
- data/test/rails-app/config/application.rb +26 -3
- data/test/rails-app/config/credentials.yml.enc +1 -0
- data/test/rails-app/config/database.yml +2 -2
- data/test/rails-app/config/environments/development.rb +7 -17
- data/test/rails-app/config/environments/production.rb +28 -23
- data/test/rails-app/config/environments/test.rb +8 -12
- data/test/rails-app/config/initializers/application_controller_renderer.rb +6 -4
- data/test/rails-app/config/initializers/cors.rb +16 -0
- data/test/rails-app/config/initializers/trailblazer.rb +2 -0
- data/test/rails-app/config/locales/en.yml +11 -1
- data/test/rails-app/config/master.key +1 -0
- data/test/rails-app/config/routes.rb +16 -4
- data/test/rails-app/db/schema.rb +15 -0
- data/test/rails-app/test/controllers/api_songs_controller_test.rb +87 -0
- data/test/rails-app/test/controllers/songs_controller_test.rb +80 -147
- data/test/rails-app/test/test_helper.rb +7 -1
- data/test/test_helper.rb +0 -2
- data/trailblazer-endpoint.gemspec +2 -1
- metadata +70 -22
- data/test/rails-app/config/initializers/cookies_serializer.rb +0 -5
- data/test/rails-app/config/initializers/new_framework_defaults.rb +0 -24
- data/test/rails-app/config/initializers/session_store.rb +0 -3
- data/test/rails-app/config/secrets.yml +0 -22
- data/test/rails-app/test/helpers/.keep +0 -0
- data/test/rails-app/test/integration/.keep +0 -0
- data/test/rails-app/test/mailers/.keep +0 -0
- data/test/rails-app/vendor/assets/javascripts/.keep +0 -0
- data/test/rails-app/vendor/assets/stylesheets/.keep +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4dd0d753bd8dc039e3f55e66d80d3d9d4904fcc0d442ea62860fbab4a0b05d5e
|
4
|
+
data.tar.gz: 0ecfa53ed1607d4d3785d47ffef3f817033b18ec29c6cbbf06e4f466c90a2638
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7762ada8e3fafbd1a68e5f4045af8e57b03568745ac55236d756da6a4fe681f6818abd4e27b737b162872b9ebd4589f440b1b7ebee01729d2cfd6dd88702d980
|
7
|
+
data.tar.gz: 6f56d293369de1da783002e8d9f602f2847eafbe2f7ad80f5f6a08fc305542f3d432d7c9878376cc421a38de58e19d60eac2d436fe2650191b36f66d149bb722
|
data/.gitignore
ADDED
data/Appraisals
ADDED
data/CHANGES.md
CHANGED
@@ -1,3 +1,29 @@
|
|
1
|
+
# 0.0.6
|
2
|
+
|
3
|
+
* `Controller::endpoint` short form introduced.
|
4
|
+
* Minor changes for `Controller.module`.
|
5
|
+
* Lots of cleanups.
|
6
|
+
|
7
|
+
# 0.0.5
|
8
|
+
|
9
|
+
* Removed `Protocol::Failure`. Until we have `Railway::End::Failure`, use a normal `Activity::End` everywhere instead of introducing our own.
|
10
|
+
* Default `with_or_etc:invoke` is `TaskWrap.invoke`.
|
11
|
+
|
12
|
+
# 0.0.4
|
13
|
+
|
14
|
+
* Use new `context-0.3.1`.
|
15
|
+
* Don't use `wtf?`.
|
16
|
+
* Don't create a `Context` anymore in `Endpoint.arguments_for`.
|
17
|
+
|
18
|
+
# 0.0.3
|
19
|
+
|
20
|
+
* Introduce `Options`.
|
21
|
+
* Introduce `Controller::DSL`.
|
22
|
+
|
23
|
+
# 0.0.2
|
24
|
+
|
25
|
+
The `:collaboration` and `:dictionary` options for `arguments_for` are now optional and figured out by `workflow`.
|
26
|
+
|
1
27
|
# 0.0.1
|
2
28
|
|
3
29
|
* Provides very simple `Protocol` implementations for `Web` and `API`, same for `Adapter`.
|
data/README.md
CHANGED
@@ -1,11 +1,46 @@
|
|
1
1
|
# Trailblazer::Endpoint
|
2
2
|
|
3
|
-
*
|
3
|
+
*Endpoints handle authentication, authorization, calling the business logic and response rendering.*
|
4
4
|
|
5
|
-
|
5
|
+
## Overview
|
6
6
|
|
7
|
-
|
7
|
+
An endpoint links your routing with your business code. The idea is that your controllers are pure HTTP routers, calling the respective endpoint for each action. From there, the endpoint takes over, handles authentication, policies, executing the domain code, interpreting the result, and providing hooks to render a response.
|
8
8
|
|
9
|
-
|
9
|
+
Instead of dealing with a mix of `before_filter`s, Rack-middlewares, controller code and callbacks, an endpoint is just another activity and allows to be customized with the well-established Trailblazer mechanics.
|
10
10
|
|
11
|
-
|
11
|
+
|
12
|
+
In a Rails controller, a controller action could look as follows.
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
class DiagramsController < ApplicationController
|
16
|
+
endpoint Diagram::Operation::Create, [:is_logged_in?, :can_add_diagram?]
|
17
|
+
|
18
|
+
def create
|
19
|
+
endpoint Diagram::Operation::Create do |ctx, **|
|
20
|
+
redirect_to diagram_path(ctx[:diagram].id)
|
21
|
+
end.Or do |ctx, **|
|
22
|
+
render :form
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
```
|
27
|
+
|
28
|
+
While routing and redirecting/rendering still happens in Rails, all remaining steps are handled in the endpoint.
|
29
|
+
|
30
|
+
An API controller action, where the rendering is done generically, could look much simpler.
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
class API::V1::DiagramsController < ApplicationController
|
34
|
+
endpoint Diagram::Operation::Create, [:is_logged_in?, :can_add_diagram?]
|
35
|
+
|
36
|
+
def create
|
37
|
+
endpoint Diagram::Operation::Create
|
38
|
+
end
|
39
|
+
end
|
40
|
+
```
|
41
|
+
|
42
|
+
Endpoints are easily customized but their main intent is to reduce fuzzy controller code and providing best practices for both HTML-rendering controllers and APIs.
|
43
|
+
|
44
|
+
## Documentation
|
45
|
+
|
46
|
+
Read the [full documentation for endpoint](https://trailblazer.to/2.1/docs/endpoint.html) on our website.
|
data/Rakefile
CHANGED
@@ -5,6 +5,12 @@ task :default => [:test]
|
|
5
5
|
|
6
6
|
Rake::TestTask.new(:test) do |test|
|
7
7
|
test.libs << 'test'
|
8
|
-
test.test_files = FileList['test/endpoint_test.rb', 'test/docs/*_test.rb', "test/adapter/*_test.rb"]
|
8
|
+
test.test_files = FileList['test/endpoint_test.rb', 'test/docs/*_test.rb', "test/adapter/*_test.rb", "test/config_test.rb"]
|
9
|
+
test.verbose = true
|
10
|
+
end
|
11
|
+
|
12
|
+
Rake::TestTask.new('test-rails-app') do |test|
|
13
|
+
test.libs << 'test'
|
14
|
+
test.test_files = FileList['test/rails-app/test/test_helper.rb', 'test/rails-app/test/**/*.rb']
|
9
15
|
test.verbose = true
|
10
16
|
end
|
data/lib/trailblazer/endpoint.rb
CHANGED
@@ -2,8 +2,7 @@ module Trailblazer
|
|
2
2
|
class Endpoint
|
3
3
|
# Create an {Endpoint} class with the provided adapter and protocol.
|
4
4
|
# This builder also sets up taskWrap filters around the {domain_activity} execution.
|
5
|
-
def self.build(protocol:, adapter:, domain_activity:, scope_domain_ctx: true, domain_ctx_filter: nil,
|
6
|
-
|
5
|
+
def self.build(protocol:, adapter:, domain_activity:, scope_domain_ctx: true, domain_ctx_filter: nil, protocol_block: ->(*) { Hash.new })
|
7
6
|
# special considerations around the {domain_activity} and its taskWrap:
|
8
7
|
#
|
9
8
|
# 1. domain_ctx_filter (e.g. to filter {current_user})
|
@@ -24,16 +23,21 @@ module Trailblazer
|
|
24
23
|
domain_ctx_filter_callable = [[Trailblazer::Activity::TaskWrap::Pipeline.method(:insert_before), "task_wrap.call_task", ["endpoint.domain_ctx_filter", domain_ctx_filter]]]
|
25
24
|
extensions_options[:extensions] << Trailblazer::Activity::TaskWrap::Extension(merge: domain_ctx_filter_callable) if domain_ctx_filter
|
26
25
|
|
26
|
+
# puts Trailblazer::Developer.render(protocol)
|
27
|
+
# puts
|
28
|
+
|
27
29
|
app_protocol = Class.new(protocol) do
|
28
30
|
step(Subprocess(domain_activity), {inherit: true, id: :domain_activity, replace: :domain_activity,
|
29
31
|
|
30
32
|
# FIXME: where does this go?
|
31
33
|
}.
|
32
34
|
merge(extensions_options).
|
33
|
-
merge(instance_exec(&
|
35
|
+
merge(instance_exec(&protocol_block)) # the block is evaluated in the {Protocol} context.
|
34
36
|
)
|
35
37
|
end
|
36
38
|
|
39
|
+
# puts Trailblazer::Developer.render(app_protocol)
|
40
|
+
|
37
41
|
Class.new(adapter) do
|
38
42
|
step(Subprocess(app_protocol), {inherit: true, id: :protocol, replace: :protocol})
|
39
43
|
end # app_adapter
|
@@ -47,12 +51,25 @@ module Trailblazer
|
|
47
51
|
}
|
48
52
|
end
|
49
53
|
|
54
|
+
def self.domain_ctx_filter(variables)
|
55
|
+
->(_ctx, ((ctx, a), b)) do # taskWrap interface
|
56
|
+
variables.each do |variable|
|
57
|
+
ctx[:domain_ctx][variable] = ctx[variable]
|
58
|
+
end
|
59
|
+
|
60
|
+
[_ctx, [[ctx, a], b]]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
50
64
|
# Runtime
|
51
65
|
# Invokes the endpoint for you and runs one of the three outcome blocks.
|
52
|
-
def self.with_or_etc(activity, args, failure_block:, success_block:, protocol_failure_block:)
|
66
|
+
def self.with_or_etc(activity, args, failure_block:, success_block:, protocol_failure_block:, invoke: Trailblazer::Activity::TaskWrap.method(:invoke))
|
67
|
+
# def self.with_or_etc(activity, args, failure_block:, success_block:, protocol_failure_block:, invoke: Trailblazer::Developer.method(:wtf?))
|
68
|
+
|
53
69
|
# args[1] = args[1].merge(focus_on: { variables: [:returned], steps: :invoke_workflow })
|
54
70
|
|
55
|
-
signal, (endpoint_ctx, _ ) = Trailblazer::Developer.wtf?(activity, args)
|
71
|
+
# signal, (endpoint_ctx, _ ) = Trailblazer::Developer.wtf?(activity, args)
|
72
|
+
signal, (endpoint_ctx, _ ) = invoke.call(activity, args) # translates to Trailblazer::Developer.wtf?(activity, args)
|
56
73
|
|
57
74
|
# this ctx is passed to the controller block.
|
58
75
|
block_ctx = endpoint_ctx[:domain_ctx].merge(endpoint_ctx: endpoint_ctx, signal: signal, errors: endpoint_ctx[:errors]) # DISCUSS: errors? status?
|
@@ -75,27 +92,22 @@ module Trailblazer
|
|
75
92
|
return signal, [endpoint_ctx]
|
76
93
|
end
|
77
94
|
|
78
|
-
# def self.default_success_if(success_id)
|
79
|
-
# ->(signal:, graph:, **) { signal[:lane_positions][suspend_activity].last == graph.find(success_id).task }
|
80
|
-
# end
|
81
|
-
|
82
95
|
#@ For WORKFLOW and operations. not sure this method will stay here.
|
83
|
-
def self.arguments_for(domain_ctx:,
|
84
|
-
|
96
|
+
def self.arguments_for(domain_ctx:, flow_options:, circuit_options: {}, **endpoint_options)
|
97
|
+
# we don't have to create the Ctx wrapping explicitly here. this is done via `:input`.
|
98
|
+
# domain_ctx = Trailblazer::Context::IndifferentAccess.build(domain_ctx, {}, [domain_ctx, flow_options], circuit_options)
|
85
99
|
|
86
100
|
[
|
87
101
|
[
|
88
102
|
{
|
89
|
-
activity: collaboration,
|
90
103
|
domain_ctx: domain_ctx, # DISCUSS: is this where {:resume_data} comes in?
|
91
104
|
# process_model_class: process_model_class,
|
92
105
|
# process_model_from_resume_data: process_model_from_resume_data,
|
93
106
|
# find_process_model: find_process_model,
|
94
107
|
# encrypted_resume_data: encrypted_resume_data,
|
95
108
|
|
96
|
-
dictionary: dictionary,
|
97
109
|
# cipher_key: cipher_key,
|
98
|
-
**
|
110
|
+
**endpoint_options,
|
99
111
|
},
|
100
112
|
flow_options
|
101
113
|
],
|
@@ -131,3 +143,6 @@ end
|
|
131
143
|
|
132
144
|
require "trailblazer/endpoint/protocol"
|
133
145
|
require "trailblazer/endpoint/adapter"
|
146
|
+
require "trailblazer/endpoint/dsl"
|
147
|
+
require "trailblazer/endpoint/controller"
|
148
|
+
require "trailblazer/endpoint/options"
|
@@ -9,20 +9,32 @@ module Trailblazer
|
|
9
9
|
|
10
10
|
|
11
11
|
module Adapter
|
12
|
-
class Web <Trailblazer::Activity::
|
12
|
+
class Web < Trailblazer::Activity::Path
|
13
13
|
_404_path = ->(*) { step :_404_status }
|
14
14
|
_401_path = ->(*) { step :_401_status }
|
15
15
|
_403_path = ->(*) { step :_403_status }
|
16
16
|
# _422_path = ->(*) { step :_422_status } # TODO: this is currently represented by the {failure} track.
|
17
17
|
|
18
|
+
# FIXME: is this really the only way to add an {End} to all this?
|
19
|
+
@state.update_sequence do |sequence:, **|
|
20
|
+
sequence = Activity::Path::DSL.append_end(sequence, task: Activity::End.new(semantic: :fail_fast), magnetic_to: :fail_fast, id: "End.fail_fast") # TODO: rename to {protocol_failure}
|
21
|
+
sequence = Activity::Path::DSL.append_end(sequence, task: Activity::End.new(semantic: :failure), magnetic_to: :failure, id: "End.failure")
|
22
|
+
|
23
|
+
recompile_activity!(sequence)
|
24
|
+
|
25
|
+
sequence
|
26
|
+
end
|
27
|
+
|
18
28
|
step Subprocess(Protocol), # this will get replaced
|
19
29
|
id: :protocol,
|
20
30
|
Output(:not_authorized) => Path(track_color: :not_authorized, connect_to: Id(:protocol_failure), &_403_path),
|
21
31
|
Output(:not_found) => Path(track_color: :not_found, connect_to: Id(:protocol_failure), &_404_path),
|
22
32
|
Output(:not_authenticated) => Path(track_color: :not_authenticated, connect_to: Id(:protocol_failure), &_401_path),
|
23
|
-
Output(:invalid_data) => Track(:failure) # application error, since it's usually a failed validation.
|
33
|
+
Output(:invalid_data) => Track(:failure), # application error, since it's usually a failed validation.
|
34
|
+
Output(:failure) => Track(:failure) # application error, since it's usually a failed validation.
|
35
|
+
|
36
|
+
step :protocol_failure, magnetic_to: nil, Output(:success) => Track(:fail_fast)#, Output(:failure) => Track(:fail_fast)
|
24
37
|
|
25
|
-
step :protocol_failure, magnetic_to: nil, Output(:success) => Track(:fail_fast), Output(:failure) => Track(:fail_fast)
|
26
38
|
|
27
39
|
def protocol_failure(ctx, **)
|
28
40
|
true
|
@@ -41,28 +53,34 @@ module Trailblazer
|
|
41
53
|
def _403_status(ctx, **)
|
42
54
|
ctx[:status] = 403
|
43
55
|
end
|
44
|
-
end
|
56
|
+
end # Web
|
45
57
|
|
46
58
|
class API < Web
|
47
59
|
step :_200_status, after: :protocol
|
48
60
|
|
49
|
-
def _200_status(ctx, **)
|
50
|
-
ctx[:status] =
|
61
|
+
def _200_status(ctx, success_status: 200, **)
|
62
|
+
ctx[:status] = success_status
|
51
63
|
end
|
52
64
|
|
53
|
-
|
65
|
+
step :_422_status, before: "End.failure", magnetic_to: :failure, Output(:success) => Track(:failure)
|
54
66
|
|
55
67
|
def _422_status(ctx, **)
|
56
68
|
ctx[:status] = 422
|
57
69
|
end
|
58
70
|
|
59
71
|
|
60
|
-
def self.insert_error_handler_steps(adapter)
|
72
|
+
def self.insert_error_handler_steps(adapter) # TODO: evaluate if needed?
|
61
73
|
adapter = Class.new(adapter) do
|
62
|
-
|
63
|
-
|
74
|
+
API.insert_error_handler_steps!(self)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.insert_error_handler_steps!(adapter)
|
79
|
+
adapter.instance_exec do
|
80
|
+
step :handle_not_authenticated, magnetic_to: :not_authenticated, Output(:success) => Track(:not_authenticated), before: :_401_status
|
81
|
+
step :handle_not_authorized, magnetic_to: :not_authorized, Output(:success) => Track(:not_authorized), before: :_403_status
|
64
82
|
# step :handle_not_found, magnetic_to: :not_found, Output(:success) => Track(:not_found), Output(:failure) => Track(:not_found)
|
65
|
-
|
83
|
+
step :handle_invalid_data, before: :_422_status, magnetic_to: :failure, Output(:success) => Track(:failure)
|
66
84
|
end
|
67
85
|
end
|
68
86
|
|
@@ -81,117 +99,8 @@ module Trailblazer
|
|
81
99
|
end
|
82
100
|
end
|
83
101
|
end
|
84
|
-
end
|
85
|
-
|
86
|
-
# Basic endpoint adapter for a HTTP document API.
|
87
|
-
# As always: "work in progress" ;)
|
88
|
-
#
|
89
|
-
# {End.fail_fast} currently implies a 4xx-able error.
|
90
|
-
class API_ < Trailblazer::Activity::FastTrack
|
91
|
-
_404_path = ->(*) { step :_404_status }
|
92
|
-
_401_path = ->(*) { step :_401_status; step :_401_error_message }
|
93
|
-
_403_path = ->(*) { step :_403_status }
|
94
|
-
# _422_path = ->(*) { step :_422_status } # TODO: this is currently represented by the {failure} track.
|
95
|
-
|
96
|
-
# The API Adapter automatically wires well-defined outputs for you to well-defined paths. :)
|
97
|
-
# FIXME
|
98
|
-
|
99
|
-
step Subprocess(Protocol), # this will get replaced
|
100
|
-
id: :protocol,
|
101
|
-
Output(:not_authorized) => Path(track_color: :_403, connect_to: Id(:render_protocol_failure_config), &_403_path),
|
102
|
-
Output(:not_found) => Path(track_color: :_404, connect_to: Id(:protocol_failure), &_404_path),
|
103
|
-
Output(:not_authenticated) => Path(track_color: :_401, connect_to: Id(:render_protocol_failure_config), &_401_path), # head(401), representer: Representer::Error, message: no token
|
104
|
-
Output(:invalid_data) => Track(:failure) # application error, since it's usually a failed validation.
|
105
|
-
|
106
|
-
# extensions: [Trailblazer::Activity::TaskWrap::Extension(merge: TERMINUS_HANDLER)]
|
107
|
-
# failure is automatically wired to failure, being an "application error" vs. a "protocol error (auth, etc)"
|
108
|
-
|
109
|
-
|
110
|
-
fail :failure_render_config
|
111
|
-
fail :failure_config_status
|
112
|
-
fail :render_failure
|
113
|
-
|
114
|
-
step :success_render_config
|
115
|
-
step :success_render_status
|
116
|
-
step :render_success
|
117
|
-
|
118
|
-
|
119
|
-
# DISCUSS: "protocol failure" and "application failure" should be the same path, probably?
|
120
|
-
step :render_protocol_failure_config, magnetic_to: nil, Output(:success) => Path(connect_to: Id("End.fail_fast")) do
|
121
|
-
step :render_protocol_failure
|
122
|
-
step :protocol_failure
|
123
|
-
end
|
124
|
-
|
125
|
-
=begin
|
126
|
-
render_protocol_failure_config # representer
|
127
|
-
render_protocol_failure # Representer.new
|
128
|
-
protocol_failure # true
|
129
|
-
=end
|
130
|
-
|
131
|
-
def success_render_status(ctx, **)
|
132
|
-
ctx[:status] = 200
|
133
|
-
end
|
134
|
-
|
135
|
-
def success_render_config(ctx, representer:, **)
|
136
|
-
true
|
137
|
-
end
|
138
|
-
|
139
|
-
def render_protocol_failure_config(*args)
|
140
|
-
failure_render_config(*args)
|
141
|
-
end
|
142
|
-
|
143
|
-
# ROAR
|
144
|
-
def render_success(ctx, representer:, domain_ctx:, **)
|
145
|
-
model = domain_ctx[:model]
|
146
|
-
ctx[:json] = representer.new(model).to_json # FIXME: use the same as render_failure.
|
147
|
-
end
|
148
|
-
|
149
|
-
def failure_render_config(ctx, error_representer:, **)
|
150
|
-
ctx[:representer] = error_representer
|
151
|
-
end
|
152
|
-
|
153
|
-
def failure_config_status(ctx, **)
|
154
|
-
ctx[:status] = 422
|
155
|
-
end
|
156
|
-
|
157
|
-
def protocol_failure(*args)
|
158
|
-
#failure_config(*args)
|
159
|
-
true
|
160
|
-
end
|
161
|
-
def render_protocol_failure(*args)
|
162
|
-
render_failure(*args)
|
163
|
-
end
|
164
|
-
|
165
|
-
# ROAR
|
166
|
-
def render_failure(ctx, error_representer:, errors:, **)
|
167
|
-
# render_success(*args)
|
168
|
-
ctx[:json] = error_representer.new(errors).to_json
|
169
|
-
end
|
170
|
-
# how/where would we configure each endpoint? (per action)
|
171
|
-
# class Endpoint
|
172
|
-
# representer ...
|
173
|
-
# message ...
|
174
|
-
|
175
|
-
def _401_status(ctx, **)
|
176
|
-
ctx[:status] = 401
|
177
|
-
end
|
178
|
-
|
179
|
-
def _404_status(ctx, **)
|
180
|
-
ctx[:status] = 404
|
181
|
-
end
|
182
|
-
|
183
|
-
def _403_status(ctx, **)
|
184
|
-
ctx[:status] = 403
|
185
|
-
end
|
186
|
-
|
187
|
-
def _401_error_message(ctx, **)
|
188
|
-
ctx[:error_message] = "Authentication credentials were not provided or invalid."
|
189
|
-
end
|
102
|
+
end # API
|
190
103
|
|
191
|
-
# def exec_success(ctx, success_block:, **)
|
192
|
-
# success_block.call(ctx, **ctx.to_hash) # DISCUSS: use Nested(dynamic) ?
|
193
|
-
# end
|
194
|
-
end
|
195
104
|
end
|
196
105
|
end
|
197
106
|
end
|
@@ -35,7 +35,7 @@ module Trailblazer
|
|
35
35
|
def endpoint_for(id:, builder:, default_options:, **config)
|
36
36
|
options = build_options_for(builder: builder, **config)
|
37
37
|
|
38
|
-
return id, Trailblazer::Endpoint.build(default_options.merge(options[:options_for_build])
|
38
|
+
return id, Trailblazer::Endpoint.build(default_options.merge(options[:options_for_build]).merge(protocol_block: options[:protocol_block]))
|
39
39
|
end
|
40
40
|
|
41
41
|
# {dsl_options} being something like
|