2018-12-25 09:35:15 -05:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
module ActiveSupport
|
|
|
|
# Actionable errors let's you define actions to resolve an error.
|
|
|
|
#
|
|
|
|
# To make an error actionable, include the <tt>ActiveSupport::ActionableError</tt>
|
2019-01-01 05:13:53 -05:00
|
|
|
# module and invoke the +action+ class macro to define the action. An action
|
|
|
|
# needs a name and a block to execute.
|
2018-12-25 09:35:15 -05:00
|
|
|
module ActionableError
|
|
|
|
extend Concern
|
|
|
|
|
2019-04-19 00:49:56 -04:00
|
|
|
class NonActionable < StandardError; end
|
2018-12-25 09:35:15 -05:00
|
|
|
|
2018-12-29 10:27:33 -05:00
|
|
|
included do
|
2019-04-19 00:49:56 -04:00
|
|
|
class_attribute :_actions, default: {}
|
2018-12-25 09:35:15 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def self.actions(error) # :nodoc:
|
2018-12-29 10:27:33 -05:00
|
|
|
case error
|
|
|
|
when ActionableError, -> it { Class === it && it < ActionableError }
|
|
|
|
error._actions
|
|
|
|
else
|
2019-04-19 00:49:56 -04:00
|
|
|
{}
|
2018-12-29 10:27:33 -05:00
|
|
|
end
|
2018-12-25 09:35:15 -05:00
|
|
|
end
|
|
|
|
|
2019-01-01 05:07:20 -05:00
|
|
|
def self.dispatch(error, name) # :nodoc:
|
2019-04-19 00:49:56 -04:00
|
|
|
actions(error).fetch(name).call
|
|
|
|
rescue KeyError
|
|
|
|
raise NonActionable, "Cannot find action \"#{name}\""
|
2018-12-25 09:35:15 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
module ClassMethods
|
|
|
|
# Defines an action that can resolve the error.
|
|
|
|
#
|
|
|
|
# class PendingMigrationError < MigrationError
|
|
|
|
# include ActiveSupport::ActionableError
|
|
|
|
#
|
|
|
|
# action "Run pending migrations" do
|
|
|
|
# ActiveRecord::Tasks::DatabaseTasks.migrate
|
|
|
|
# end
|
|
|
|
# end
|
2019-01-01 05:07:20 -05:00
|
|
|
def action(name, &block)
|
|
|
|
_actions[name] = block
|
2018-12-25 09:35:15 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|