Skip to content

Commit

Permalink
Setup server-side abort and error handler hooks for commands
Browse files Browse the repository at this point in the history
  • Loading branch information
hopsoft committed Jan 3, 2024
1 parent eb2f5cd commit b292404
Show file tree
Hide file tree
Showing 10 changed files with 44 additions and 17 deletions.
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM ruby:3.2.2-slim-bullseye
FROM ruby:3.0.3-slim-bullseye

RUN apt-get -y update && \
apt-get -y --no-install-recommends install \
Expand All @@ -8,7 +8,7 @@ libjemalloc2 \
sqlite3 \
tzdata

RUN curl -fsSL https://deb.nodesource.com/setup_16.x | bash -
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
RUN apt-get -y --no-install-recommends install nodejs && \
npm install -g npm@latest yarn

Expand Down
4 changes: 2 additions & 2 deletions lib/turbo_boost/commands/attribute_set.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ def initialize(attributes = {}, prefix: nil)
value = value.to_i if value.is_a?(String) && value.match?(/\A-?\d+\z/)
value = value == "true" if value.is_a?(String) && value.match?(/\A(true|false)\z/i)

instance_variable_set "@#{name}", value
instance_variable_set :"@#{name}", value

next if orig_respond_to_missing?(name, false)

self.class.define_method(name) { instance_variable_get :"@#{name}" }
self.class.define_method("#{name}?") { public_send(name).present? }
self.class.define_method(:"#{name}?") { public_send(name).present? }
end
end

Expand Down
6 changes: 3 additions & 3 deletions lib/turbo_boost/commands/command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -121,13 +121,13 @@ def render(options = {}, locals = {}, &block)
options = options.symbolize_keys

ivars = options[:assigns]&.each_with_object({}) do |(key, value), memo|
memo[key] = controller.instance_variable_get("@#{key}")
controller.instance_variable_set "@#{key}", value
memo[key] = controller.instance_variable_get(:"@#{key}")
controller.instance_variable_set :"@#{key}", value
end

controller.view_context.render(options.except(:assigns), locals, &block)
ensure
ivars&.each { |key, value| controller.instance_variable_set "@#{key}", value }
ivars&.each { |key, value| controller.instance_variable_set :"@#{key}", value }
end

def turbo_stream
Expand Down
34 changes: 31 additions & 3 deletions lib/turbo_boost/commands/command_callbacks.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,26 @@ module TurboBoost::Commands::CommandCallbacks
NAME = :perform_command

module ClassMethods
# Configure an abort handler
#
# @yield [TurboBoost::Commands::Command, StandardError] The block to execute if the command is aborted
# @yieldparam command [TurboBoost::Commands::Command] The command instance
# @yieldparam error [StandardError] The error that was raised in a `before_command` callback
def on_abort(&block)
@on_abort = block
end

# Configure an error handler
#
# @yield [TurboBoost::Commands::Command, StandardError] The block to execute if the command raises an error during execution
# @yieldparam command [TurboBoost::Commands::Command] The command instance
# @yieldparam error [StandardError] The error that was raised
def on_error(&block)
@on_error = block
end

[:before, :after, :around].each do |type|
define_method "#{type}_command" do |*method_names, &blk|
define_method :"#{type}_command" do |*method_names, &blk|
options = callback_options(method_names.extract_options!)

# convert only to if
Expand All @@ -29,7 +47,7 @@ module ClassMethods
method_names.each { |method_name| set_callback NAME, type, method_name, options }
end

define_method "skip_#{type}_command" do |*method_names, &blk|
define_method :"skip_#{type}_command" do |*method_names, &blk|
options = callback_options(method_names.extract_options!)

# convert only to if
Expand Down Expand Up @@ -66,7 +84,7 @@ def callback_options(options)
callback.call
false # everything is ok
rescue => error
command.send :aborted!, error
command.public_send :aborted!, error
true # halt the callback chain
end
}
Expand Down Expand Up @@ -106,14 +124,24 @@ def succeeded?

private

def abort_handler
self.class.instance_variable_get(:@on_abort) || ->(*_) {}
end

def aborted!(error)
changed @aborted = true
notify_observers :aborted, error: error
abort_handler.call self, error
end

def error_handler
self.class.instance_variable_get(:@on_error) || ->(*_) {}
end

def errored!(error)
changed @errored = true
notify_observers :errored, error: error
error_handler.call self, error
end

def performed!
Expand Down
4 changes: 2 additions & 2 deletions lib/turbo_boost/commands/runner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -182,9 +182,9 @@ def handle_command_event(*args)
options = args.extract_options!
case event
when :aborted
prevent_controller_action error: error
prevent_controller_action error: options[:error]
append_streams_to_response_body
when :errored then prevent_controller_action(**options)
when :errored then prevent_controller_action error: options[:error]
when :performed then prevent_controller_action if should_prevent_controller_action?
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/turbo_boost/commands/sanitizer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class TurboBoost::Commands::Sanitizer
attr_reader :scrubber

def sanitize(value)
super value, scrubber: scrubber
super(value, scrubber: scrubber)
end

private
Expand Down
2 changes: 1 addition & 1 deletion test/dummy/app/assets/builds/tailwind.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion test/dummy/app/helpers/tailwind_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ module TailwindHelper
def tailwind_defaults
@tailwind_defaults ||= self.class.instance_variable_get(:@tailwind_defaults)
@tailwind_defaults ||= begin
defaults = YAML.safe_load(File.read(Rails.root.join("app/views/components/_tailwind.yml.erb")))
defaults = YAML.safe_load_file(Rails.root.join("app/views/components/_tailwind.yml.erb"))
self.class.instance_variable_set(:@tailwind_defaults, defaults) unless Rails.env.development?
defaults
end
Expand Down
1 change: 0 additions & 1 deletion test/dummy/db/structure.sql
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,3 @@ CREATE TABLE sqlite_sequence(name,seq);
INSERT INTO "schema_migrations" (version) VALUES
('20221230164522');


2 changes: 1 addition & 1 deletion turbo_boost-commands.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Gem::Specification.new do |s|

s.files = Dir["{app,lib}/**/*", "MIT-LICENSE", "README.md"]

s.required_ruby_version = ">= 2.7.3"
s.required_ruby_version = ">= 2.7.5"
s.add_dependency "rails", ">= 6.1"
s.add_dependency "turbo-rails", ">= 1.1"
s.add_dependency "turbo_boost-streams", ">= 0.0.8"
Expand Down

0 comments on commit b292404

Please sign in to comment.