Class: TurboReflex::Runner
- Inherits:
-
Object
- Object
- TurboReflex::Runner
- Defined in:
- lib/turbo_reflex/runner.rb
Instance Attribute Summary collapse
-
#controller ⇒ Object
readonly
Returns the value of attribute controller.
-
#state_manager ⇒ Object
(also: #state)
readonly
Returns the value of attribute state_manager.
Instance Method Summary collapse
- #controller_action_prevented? ⇒ Boolean
-
#cookies ⇒ Object
Same implementation as ActionController::Base but with public visibility.
-
#initialize(controller) ⇒ Runner
constructor
A new instance of Runner.
- #message_verifier ⇒ Object
- #meta_tag ⇒ Object
- #prevent_controller_action(error: nil) ⇒ Object
- #reflex_class ⇒ Object
- #reflex_class_name ⇒ Object
- #reflex_element ⇒ Object
- #reflex_errored? ⇒ Boolean
- #reflex_instance ⇒ Object
- #reflex_method_name ⇒ Object
- #reflex_name ⇒ Object
- #reflex_params ⇒ Object
- #reflex_performed? ⇒ Boolean
- #reflex_requested? ⇒ Boolean
- #reflex_succeeded? ⇒ Boolean
- #reflex_valid? ⇒ Boolean
- #render_response(html: "", status: nil, headers: {TurboReflex: :Append}) ⇒ Object
- #run ⇒ Object
- #should_prevent_controller_action? ⇒ Boolean
- #turbo_stream ⇒ Object
- #update_response ⇒ Object
Constructor Details
#initialize(controller) ⇒ Runner
Returns a new instance of Runner.
13 14 15 16 |
# File 'lib/turbo_reflex/runner.rb', line 13 def initialize(controller) @controller = controller @state_manager = TurboReflex::StateManager.new(self) end |
Instance Attribute Details
#controller ⇒ Object (readonly)
Returns the value of attribute controller.
8 9 10 |
# File 'lib/turbo_reflex/runner.rb', line 8 def controller @controller end |
#state_manager ⇒ Object (readonly) Also known as: state
Returns the value of attribute state_manager.
8 9 10 |
# File 'lib/turbo_reflex/runner.rb', line 8 def state_manager @state_manager end |
Instance Method Details
#controller_action_prevented? ⇒ Boolean
104 105 106 |
# File 'lib/turbo_reflex/runner.rb', line 104 def controller_action_prevented? !!@controller_action_prevented end |
#cookies ⇒ Object
Same implementation as ActionController::Base but with public visibility
171 172 173 |
# File 'lib/turbo_reflex/runner.rb', line 171 def request. end |
#message_verifier ⇒ Object
166 167 168 |
# File 'lib/turbo_reflex/runner.rb', line 166 def ActiveSupport::MessageVerifier.new Rails.application.secret_key_base, digest: "SHA256" end |
#meta_tag ⇒ Object
18 19 20 21 22 23 24 25 26 27 |
# File 'lib/turbo_reflex/runner.rb', line 18 def masked_token = .generate(new_token) = { id: "turbo-reflex", name: "turbo-reflex", content: masked_token, data: {busy: false, state: state_manager.payload} } view_context.tag("meta", ).html_safe end |
#prevent_controller_action(error: nil) ⇒ Object
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/turbo_reflex/runner.rb', line 129 def prevent_controller_action(error: nil) return if controller_action_prevented? @controller_action_prevented = true if error render_response status: :internal_server_error append_error_to_response error else render_response append_success_to_response 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 |
#reflex_class ⇒ Object
88 89 90 |
# File 'lib/turbo_reflex/runner.rb', line 88 def reflex_class @reflex_class ||= reflex_class_name&.safe_constantize end |
#reflex_class_name ⇒ Object
77 78 79 80 |
# File 'lib/turbo_reflex/runner.rb', line 77 def reflex_class_name return nil unless reflex_requested? reflex_name.split("#").first end |
#reflex_element ⇒ Object
65 66 67 68 69 70 |
# File 'lib/turbo_reflex/runner.rb', line 65 def reflex_element return nil if reflex_params.blank? @reflex_element ||= Struct .new(*reflex_params[:element_attributes].keys.map { |key| key.to_s.parameterize.underscore.to_sym }) .new(*reflex_params[:element_attributes].values) end |
#reflex_errored? ⇒ Boolean
100 101 102 |
# File 'lib/turbo_reflex/runner.rb', line 100 def reflex_errored? !!@reflex_errored end |
#reflex_instance ⇒ Object
92 93 94 |
# File 'lib/turbo_reflex/runner.rb', line 92 def reflex_instance @reflex_instance ||= reflex_class&.new(self) end |
#reflex_method_name ⇒ Object
82 83 84 85 86 |
# File 'lib/turbo_reflex/runner.rb', line 82 def reflex_method_name return nil unless reflex_requested? return "noop" unless reflex_name.include?("#") reflex_name.split("#").last end |
#reflex_name ⇒ Object
72 73 74 75 |
# File 'lib/turbo_reflex/runner.rb', line 72 def reflex_name return nil unless reflex_requested? reflex_params[:name] end |
#reflex_params ⇒ Object
57 58 59 60 61 62 63 |
# File 'lib/turbo_reflex/runner.rb', line 57 def reflex_params return ActionController::Parameters.new if params[:turbo_reflex].nil? @reflex_params ||= begin payload = parsed_reflex_params.deep_transform_keys(&:underscore) ActionController::Parameters.new(payload).permit! end end |
#reflex_performed? ⇒ Boolean
96 97 98 |
# File 'lib/turbo_reflex/runner.rb', line 96 def reflex_performed? !!@reflex_performed end |
#reflex_requested? ⇒ Boolean
29 30 31 |
# File 'lib/turbo_reflex/runner.rb', line 29 def reflex_requested? reflex_params.present? end |
#reflex_succeeded? ⇒ Boolean
108 109 110 |
# File 'lib/turbo_reflex/runner.rb', line 108 def reflex_succeeded? reflex_performed? && !reflex_errored? end |
#reflex_valid? ⇒ Boolean
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/turbo_reflex/runner.rb', line 33 def reflex_valid? return false unless reflex_requested? # validate class unless reflex_instance.is_a?(TurboReflex::Base) raise TurboReflex::InvalidClassError, "`#{reflex_class_name}` is not a subclass of `TurboReflex::Base`!" end # validate method unless reflex_instance.respond_to?(reflex_method_name) raise TurboReflex::InvalidMethodError, "`#{reflex_class_name}` does not define the public method `#{reflex_method_name}`!" end # validate csrf token unless valid_client_token? raise TurboReflex::InvalidTokenError, "CSRF token mismatch! The request header `TurboReflex-Token: #{client_token}` does not match the expected value of `#{server_token}`." end true end |
#render_response(html: "", status: nil, headers: {TurboReflex: :Append}) ⇒ Object
157 158 159 160 |
# File 'lib/turbo_reflex/runner.rb', line 157 def render_response(html: "", status: nil, headers: {TurboReflex: :Append}) headers.each { |key, value| response.set_header key.to_s, value.to_s } render html: html, layout: false, status: status || response_status end |
#run ⇒ Object
117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/turbo_reflex/runner.rb', line 117 def run return unless reflex_valid? return if reflex_performed? @reflex_performed = true reflex_instance.public_send reflex_method_name prevent_controller_action if should_prevent_controller_action? rescue => error @reflex_errored = true raise error if controller_action_prevented? prevent_controller_action error: error end |
#should_prevent_controller_action? ⇒ Boolean
112 113 114 115 |
# File 'lib/turbo_reflex/runner.rb', line 112 def should_prevent_controller_action? return false unless reflex_performed? reflex_instance.should_prevent_controller_action? reflex_method_name end |
#turbo_stream ⇒ Object
162 163 164 |
# File 'lib/turbo_reflex/runner.rb', line 162 def turbo_stream @turbo_stream ||= Turbo::Streams::TagBuilder.new(view_context) end |
#update_response ⇒ Object
145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/turbo_reflex/runner.rb', line 145 def update_response return if controller_action_prevented? return if @update_response_performed @update_response_performed = true # 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 reflex_succeeded? rescue => error Rails.logger.error "TurboReflex::Runner failed to update the response! #{error.}" end |