Class: TurboBoost::Commands::Runner
- Inherits:
-
Object
- Object
- TurboBoost::Commands::Runner
- Defined in:
- lib/turbo_boost/commands/runner.rb
Constant Summary collapse
- SUPPORTED_MEDIA_TYPES =
{ "text/html" => true, "text/vnd.turbo-boost.html" => true, "text/vnd.turbo-stream.html" => true }.freeze
Instance Attribute Summary collapse
-
#controller ⇒ Object
readonly
Returns the value of attribute controller.
-
#state_manager ⇒ Object
readonly
Returns the value of attribute state_manager.
Instance Method Summary collapse
- #command_aborted? ⇒ Boolean
- #command_class ⇒ Object
- #command_class_name ⇒ Object
- #command_errored? ⇒ Boolean
- #command_instance ⇒ Object
- #command_method_name ⇒ Object
- #command_name ⇒ Object
- #command_params ⇒ Object
- #command_performed? ⇒ Boolean
- #command_performing? ⇒ Boolean
- #command_requested? ⇒ Boolean
- #command_succeeded? ⇒ Boolean
- #command_valid? ⇒ Boolean
- #controller_action_prevented? ⇒ Boolean
-
#cookies ⇒ Object
Same implementation as ActionController::Base but with public visibility.
- #handle_command_event(*args) ⇒ Object
-
#initialize(controller, state_manager) ⇒ Runner
constructor
A new instance of Runner.
- #message_verifier ⇒ Object
- #meta_tag ⇒ Object
- #prevent_controller_action(error: nil) ⇒ Object
- #render_response(html: "", status: nil, headers: {}) ⇒ Object
- #run ⇒ Object
- #should_prevent_controller_action? ⇒ Boolean
- #turbo_stream ⇒ Object
- #update_response ⇒ Object
Constructor Details
#initialize(controller, state_manager) ⇒ Runner
Returns a new instance of Runner.
14 15 16 17 |
# File 'lib/turbo_boost/commands/runner.rb', line 14 def initialize(controller, state_manager) @controller = controller @state_manager = state_manager end |
Instance Attribute Details
#controller ⇒ Object (readonly)
Returns the value of attribute controller.
12 13 14 |
# File 'lib/turbo_boost/commands/runner.rb', line 12 def controller @controller end |
#state_manager ⇒ Object (readonly)
Returns the value of attribute state_manager.
12 13 14 |
# File 'lib/turbo_boost/commands/runner.rb', line 12 def state_manager @state_manager end |
Instance Method Details
#command_aborted? ⇒ Boolean
94 95 96 |
# File 'lib/turbo_boost/commands/runner.rb', line 94 def command_aborted? !!command_instance&.aborted? end |
#command_class ⇒ Object
84 85 86 |
# File 'lib/turbo_boost/commands/runner.rb', line 84 def command_class @command_class ||= command_class_name&.safe_constantize end |
#command_class_name ⇒ Object
71 72 73 74 75 76 |
# File 'lib/turbo_boost/commands/runner.rb', line 71 def command_class_name return nil unless command_requested? name = command_name.split("#").first name << "Command" unless name.end_with?("Command") name end |
#command_errored? ⇒ Boolean
98 99 100 |
# File 'lib/turbo_boost/commands/runner.rb', line 98 def command_errored? !!command_instance&.errored? end |
#command_instance ⇒ Object
88 89 90 91 92 |
# File 'lib/turbo_boost/commands/runner.rb', line 88 def command_instance @command_instance ||= command_class&.new(controller, state_manager, command_params).tap do |instance| instance&.add_observer self, :handle_command_event end end |
#command_method_name ⇒ Object
78 79 80 81 82 |
# File 'lib/turbo_boost/commands/runner.rb', line 78 def command_method_name return nil unless command_requested? return "perform" unless command_name.include?("#") command_name.split("#").last end |
#command_name ⇒ Object
66 67 68 69 |
# File 'lib/turbo_boost/commands/runner.rb', line 66 def command_name return nil unless command_requested? command_params[:name] end |
#command_params ⇒ Object
58 59 60 61 62 63 64 |
# File 'lib/turbo_boost/commands/runner.rb', line 58 def command_params return ActionController::Parameters.new if controller.params[:turbo_boost_command].nil? @command_params ||= begin payload = parsed_command_params.deep_transform_keys(&:underscore) ActionController::Parameters.new(payload).permit! end end |
#command_performed? ⇒ Boolean
106 107 108 |
# File 'lib/turbo_boost/commands/runner.rb', line 106 def command_performed? !!command_instance&.performed? end |
#command_performing? ⇒ Boolean
102 103 104 |
# File 'lib/turbo_boost/commands/runner.rb', line 102 def command_performing? !!command_instance&.performing? end |
#command_requested? ⇒ Boolean
30 31 32 |
# File 'lib/turbo_boost/commands/runner.rb', line 30 def command_requested? command_params.present? end |
#command_succeeded? ⇒ Boolean
110 111 112 |
# File 'lib/turbo_boost/commands/runner.rb', line 110 def command_succeeded? !!command_instance&.succeeded? end |
#command_valid? ⇒ Boolean
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/turbo_boost/commands/runner.rb', line 34 def command_valid? return false unless command_requested? # validate class unless command_instance.is_a?(TurboBoost::Commands::Command) raise TurboBoost::Commands::InvalidClassError, "`#{command_class_name}` is not a subclass of `TurboBoost::Commands::Command`!" end # validate method unless command_instance.respond_to?(command_method_name) raise TurboBoost::Commands::InvalidMethodError, "`#{command_class_name}` does not define the public method `#{command_method_name}`!" end # validate csrf token unless valid_client_token? raise TurboBoost::InvalidTokenError, "CSRF token mismatch! The request header `TurboBoost-Token: #{client_token}` does not match the expected value of `#{server_token}`." end true end |
#controller_action_prevented? ⇒ Boolean
114 115 116 |
# File 'lib/turbo_boost/commands/runner.rb', line 114 def controller_action_prevented? !!@controller_action_prevented end |
#cookies ⇒ Object
Same implementation as ActionController::Base but with public visibility
183 184 185 |
# File 'lib/turbo_boost/commands/runner.rb', line 183 def controller.request. end |
#handle_command_event(*args) ⇒ Object
187 188 189 190 191 192 193 194 |
# File 'lib/turbo_boost/commands/runner.rb', line 187 def handle_command_event(*args) event = args.shift = args. case event when :aborted, :errored then prevent_controller_action error: [:error] when :performed then prevent_controller_action if should_prevent_controller_action? end end |
#message_verifier ⇒ Object
178 179 180 |
# File 'lib/turbo_boost/commands/runner.rb', line 178 def ActiveSupport::MessageVerifier.new Rails.application.secret_key_base, digest: "SHA256" end |
#meta_tag ⇒ Object
19 20 21 22 23 24 25 26 27 28 |
# File 'lib/turbo_boost/commands/runner.rb', line 19 def masked_token = .generate(new_token) = { id: "turbo-boost", name: "turbo-boost", content: masked_token, data: {busy: false, state: state_manager.payload} } controller.view_context.tag("meta", ).html_safe end |
#prevent_controller_action(error: nil) ⇒ Object
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'lib/turbo_boost/commands/runner.rb', line 132 def prevent_controller_action(error: nil) return if controller_action_prevented? @controller_action_prevented = true case error when nil render_response status: response_status append_success_to_response when TurboBoost::Commands::AbortError render_response status: error.http_status_code, headers: {"TurboBoost-Command-Status": error.} append_streams_to_response_body when TurboBoost::Commands::PerformError render_response status: error.http_status_code, headers: {"TurboBoost-Command-Status": error.} append_error_to_response error else render_response status: :internal_server_error, headers: {"TurboBoost-Command-Status": error.} append_error_to_response error end # called before `write_cookie` so all state is emitted to the DOM state_manager. # truncates state to stay within cookie size limits (4k) end |
#render_response(html: "", status: nil, headers: {}) ⇒ Object
169 170 171 172 |
# File 'lib/turbo_boost/commands/runner.rb', line 169 def render_response(html: "", status: nil, headers: {}) controller.render html: html, layout: false, status: status || response_status append_to_response_headers headers.merge(TurboBoost: :Append) end |
#run ⇒ Object
123 124 125 126 127 128 129 130 |
# File 'lib/turbo_boost/commands/runner.rb', line 123 def run return unless command_valid? return if command_aborted? return if command_errored? return if command_performing? return if command_performed? command_instance.perform_with_callbacks command_method_name end |
#should_prevent_controller_action? ⇒ Boolean
118 119 120 121 |
# File 'lib/turbo_boost/commands/runner.rb', line 118 def should_prevent_controller_action? return false unless command_performed? command_instance.should_prevent_controller_action? command_method_name end |
#turbo_stream ⇒ Object
174 175 176 |
# File 'lib/turbo_boost/commands/runner.rb', line 174 def turbo_stream @turbo_stream ||= Turbo::Streams::TagBuilder.new(controller.view_context) end |
#update_response ⇒ Object
155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/turbo_boost/commands/runner.rb', line 155 def update_response return if @update_response_performed @update_response_performed = true return if controller_action_prevented? append_to_response_headers # called before `write_cookie` so all state is emitted to the DOM state_manager. # truncates state to stay within cookie size limits (4k) append_success_to_response if command_succeeded? rescue => error Rails.logger.error "TurboBoost::Commands::Runner failed to update the response! #{error.}" end |