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.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +16 -0
  3. data/Appraisals +5 -0
  4. data/CHANGES.md +26 -0
  5. data/README.md +40 -5
  6. data/Rakefile +7 -1
  7. data/gemfiles/rails_app.gemfile +12 -0
  8. data/lib/trailblazer/endpoint.rb +29 -14
  9. data/lib/trailblazer/endpoint/adapter.rb +30 -121
  10. data/lib/trailblazer/endpoint/builder.rb +1 -1
  11. data/lib/trailblazer/endpoint/controller.rb +223 -0
  12. data/lib/trailblazer/endpoint/dsl.rb +29 -0
  13. data/lib/trailblazer/endpoint/options.rb +92 -0
  14. data/lib/trailblazer/endpoint/protocol.rb +5 -8
  15. data/lib/trailblazer/endpoint/version.rb +1 -1
  16. data/test/adapter/api_test.rb +6 -11
  17. data/test/adapter/web_test.rb +2 -5
  18. data/test/config_test.rb +128 -0
  19. data/test/docs/controller_test.rb +339 -58
  20. data/test/endpoint_test.rb +1 -1
  21. data/test/rails-app/.gitignore +8 -2
  22. data/test/rails-app/.ruby-version +1 -0
  23. data/test/rails-app/Gemfile +15 -9
  24. data/test/rails-app/Gemfile.lock +162 -121
  25. data/test/rails-app/app/concepts/app/api/v1/representer/errors.rb +16 -0
  26. data/test/rails-app/app/concepts/auth/jwt.rb +35 -0
  27. data/test/rails-app/app/concepts/auth/operation/authenticate.rb +32 -0
  28. data/test/rails-app/app/concepts/auth/operation/policy.rb +9 -0
  29. data/test/rails-app/app/concepts/song/cell/create.rb +4 -0
  30. data/test/rails-app/app/concepts/song/cell/new.rb +4 -0
  31. data/test/rails-app/app/concepts/song/operation/create.rb +17 -0
  32. data/test/rails-app/app/concepts/song/operation/show.rb +10 -0
  33. data/test/rails-app/app/concepts/song/representer.rb +5 -0
  34. data/test/rails-app/app/concepts/song/view/create.erb +1 -0
  35. data/test/rails-app/app/concepts/song/view/new.erb +1 -0
  36. data/test/rails-app/app/controllers/api/v1/songs_controller.rb +41 -0
  37. data/test/rails-app/app/controllers/application_controller.rb +8 -1
  38. data/test/rails-app/app/controllers/application_controller/api.rb +107 -0
  39. data/test/rails-app/app/controllers/application_controller/web.rb +44 -0
  40. data/test/rails-app/app/controllers/auth_controller.rb +44 -0
  41. data/test/rails-app/app/controllers/home_controller.rb +5 -0
  42. data/test/rails-app/app/controllers/songs_controller.rb +71 -13
  43. data/test/rails-app/app/models/song.rb +3 -0
  44. data/test/rails-app/app/models/user.rb +7 -0
  45. data/test/rails-app/bin/bundle +114 -0
  46. data/test/rails-app/bin/rails +4 -0
  47. data/test/rails-app/bin/rake +4 -0
  48. data/test/rails-app/bin/setup +33 -0
  49. data/test/rails-app/config/application.rb +26 -3
  50. data/test/rails-app/config/credentials.yml.enc +1 -0
  51. data/test/rails-app/config/database.yml +2 -2
  52. data/test/rails-app/config/environments/development.rb +7 -17
  53. data/test/rails-app/config/environments/production.rb +28 -23
  54. data/test/rails-app/config/environments/test.rb +8 -12
  55. data/test/rails-app/config/initializers/application_controller_renderer.rb +6 -4
  56. data/test/rails-app/config/initializers/cors.rb +16 -0
  57. data/test/rails-app/config/initializers/trailblazer.rb +2 -0
  58. data/test/rails-app/config/locales/en.yml +11 -1
  59. data/test/rails-app/config/master.key +1 -0
  60. data/test/rails-app/config/routes.rb +16 -4
  61. data/test/rails-app/db/schema.rb +15 -0
  62. data/test/rails-app/test/controllers/api_songs_controller_test.rb +87 -0
  63. data/test/rails-app/test/controllers/songs_controller_test.rb +80 -147
  64. data/test/rails-app/test/test_helper.rb +7 -1
  65. data/test/test_helper.rb +0 -2
  66. data/trailblazer-endpoint.gemspec +2 -1
  67. metadata +70 -22
  68. data/test/rails-app/config/initializers/cookies_serializer.rb +0 -5
  69. data/test/rails-app/config/initializers/new_framework_defaults.rb +0 -24
  70. data/test/rails-app/config/initializers/session_store.rb +0 -3
  71. data/test/rails-app/config/secrets.yml +0 -22
  72. data/test/rails-app/test/helpers/.keep +0 -0
  73. data/test/rails-app/test/integration/.keep +0 -0
  74. data/test/rails-app/test/mailers/.keep +0 -0
  75. data/test/rails-app/vendor/assets/javascripts/.keep +0 -0
  76. 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: a13cc4ea9b50a656f620578a75ccd11aa01106bc22be8975e8758a660d1a13aa
4
- data.tar.gz: 4c006bbfeab10458615ee658e862cf152b42b17f1c0d8302f9d1308b8cdc1425
3
+ metadata.gz: 4dd0d753bd8dc039e3f55e66d80d3d9d4904fcc0d442ea62860fbab4a0b05d5e
4
+ data.tar.gz: 0ecfa53ed1607d4d3785d47ffef3f817033b18ec29c6cbbf06e4f466c90a2638
5
5
  SHA512:
6
- metadata.gz: 53dfeec3df63a69bbe4f481f58eaa6c71e32d55044066fda4eb7dc8579ef1b973079ff8fa6b7cbd7a6f4ce4ecdb767d25f37a6bf68eee99626557f1a1de2ab71
7
- data.tar.gz: 99b9e753a78f182ad274c677aa9f1c33bc85fbd8ad4ce57c2574a4b4ef29d3400e3553c6484674e3d75cec41dcacea76f601db77aee7273fdd066ec3c41c17c7
6
+ metadata.gz: 7762ada8e3fafbd1a68e5f4045af8e57b03568745ac55236d756da6a4fe681f6818abd4e27b737b162872b9ebd4589f440b1b7ebee01729d2cfd6dd88702d980
7
+ data.tar.gz: 6f56d293369de1da783002e8d9f602f2847eafbe2f7ad80f5f6a08fc305542f3d432d7c9878376cc421a38de58e19d60eac2d436fe2650191b36f66d149bb722
@@ -0,0 +1,16 @@
1
+ .bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /log
10
+ tmp
11
+ .DS_Store
12
+ log/
13
+ *.iml
14
+ .idea
15
+ *.swp
16
+ gemfiles/*.lock
@@ -0,0 +1,5 @@
1
+ appraise 'rails-app' do
2
+ gem 'rails', '6.0.3.1'
3
+ gem 'sqlite3', '~> 1.4'
4
+ gem "trailblazer-operation"
5
+ end
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
- *Generic HTTP handlers for operation results.*
3
+ *Endpoints handle authentication, authorization, calling the business logic and response rendering.*
4
4
 
5
- Decouple finding out *what happened* from *what to do*.
5
+ ## Overview
6
6
 
7
- t test/controllers/songs_controller_test.rb --backtrace
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
- ## TODO
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
- * make travis build run `cd test/rails-app/ && rake`
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
@@ -0,0 +1,12 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "multi_json"
6
+ gem "minitest-line"
7
+ gem "dry-validation"
8
+ gem "rails", "6.0.3.1"
9
+ gem "sqlite3", "~> 1.4"
10
+ gem "trailblazer-operation"
11
+
12
+ gemspec path: "../"
@@ -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, &block)
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(&block)) # the block is evaluated in the {Protocol} context.
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:, collaboration:, dictionary: collaboration.to_h[:dictionary], flow_options:, circuit_options: {}, **options)
84
- domain_ctx = Trailblazer::Context::IndifferentAccess.build(domain_ctx, {}, [domain_ctx, flow_options], circuit_options)
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
- **options,
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::FastTrack
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] = 200
61
+ def _200_status(ctx, success_status: 200, **)
62
+ ctx[:status] = success_status
51
63
  end
52
64
 
53
- fail :_422_status, before: "End.failure"
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
- step :handle_not_authenticated, magnetic_to: :not_authenticated, Output(:success) => Track(:not_authenticated), Output(:failure) => Track(:not_authenticated), before: :_401_status
63
- step :handle_not_authorized, magnetic_to: :not_authorized, Output(:success) => Track(:not_authorized), Output(:failure) => Track(:not_authorized), before: :_403_status
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
- fail :handle_invalid_data
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]), &options[:protocol_block])
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