Present a more informative missing action error (#1232)
When a route contains a key for a missing action, raise a (renamed) `Hanami::Routes::MissingActionError` with a full message like the following: ``` Could not find action with key "actions.missing.action" in Admin::Slice To fix this, define the action class Admin::Actions::Missing::Action in /full/path/to/slices/admin/actions/missing/action.rb ``` Include the slice name being used to resolve the action, as well as the expected action class name and file so that the user can correct the error. Move these routing-related errors to the `Hanami::Routes` namespace too, since that namespace is already expected by the user, since it is the superclass of their routes definition files. Lastly, rename the error from UnknownActionError to MissingActionError, to make it clearer that we _know_ the action, but its component/source file is missing.
This commit is contained in:
parent
a502f82e5d
commit
70156569b2
|
@ -1,6 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require "hanami/slice/router"
|
||||
require_relative "constants"
|
||||
require_relative "slice/router"
|
||||
|
||||
module Hanami
|
||||
# App routes
|
||||
|
@ -25,6 +26,30 @@ module Hanami
|
|||
# @see Hanami::Slice::Router
|
||||
# @since 2.0.0
|
||||
class Routes
|
||||
# @since 2.0.0
|
||||
class MissingActionError < Error
|
||||
def initialize(action_key, slice)
|
||||
action_path = action_key.gsub(CONTAINER_KEY_DELIMITER, PATH_DELIMITER)
|
||||
action_constant = slice.inflector.camelize(
|
||||
"#{slice.inflector.underscore(slice.namespace.to_s)}#{PATH_DELIMITER}#{action_path}"
|
||||
)
|
||||
action_file = slice.root.join("#{action_path}#{RB_EXT}")
|
||||
|
||||
super(<<~MSG)
|
||||
Could not find action with key #{action_key.inspect} in #{slice}
|
||||
|
||||
To fix this, define the action class #{action_constant} in #{action_file}
|
||||
MSG
|
||||
end
|
||||
end
|
||||
|
||||
# @since 2.0.0
|
||||
class NotCallableEndpointError < Error
|
||||
def initialize(endpoint)
|
||||
super("#{endpoint.inspect} is not compatible with Rack. Please make sure it implements #call.")
|
||||
end
|
||||
end
|
||||
|
||||
# @api private
|
||||
def self.routes
|
||||
@routes ||= build_routes
|
||||
|
|
|
@ -1,22 +1,10 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative "../../routes"
|
||||
|
||||
module Hanami
|
||||
class Slice
|
||||
module Routing
|
||||
# @since 2.0.0
|
||||
class UnknownActionError < Hanami::Error
|
||||
def initialize(identifier)
|
||||
super("unknown action referenced in router: `#{identifier.inspect}'")
|
||||
end
|
||||
end
|
||||
|
||||
# @since 2.0.0
|
||||
class NotCallableEndpointError < StandardError
|
||||
def initialize(endpoint)
|
||||
super("#{endpoint.inspect} is not compatible with Rack. Please make sure it implements #call.")
|
||||
end
|
||||
end
|
||||
|
||||
# Hanami app router endpoint resolver
|
||||
#
|
||||
# @since 2.0.0
|
||||
|
@ -55,7 +43,7 @@ module Hanami
|
|||
end
|
||||
|
||||
unless endpoint.respond_to?(:call)
|
||||
raise NotCallableEndpointError.new(endpoint)
|
||||
raise Routes::NotCallableEndpointError.new(endpoint)
|
||||
end
|
||||
|
||||
endpoint
|
||||
|
@ -79,7 +67,7 @@ module Hanami
|
|||
# concerns (which may not be fully loaded at the time of reading the routes)
|
||||
-> (*args) {
|
||||
action = slice.resolve(action_key) do
|
||||
raise UnknownActionError.new(key)
|
||||
raise Routes::MissingActionError.new(action_key, slice)
|
||||
end
|
||||
|
||||
action.call(*args)
|
||||
|
@ -89,7 +77,7 @@ module Hanami
|
|||
def ensure_action_in_slice(key)
|
||||
return unless slice.booted?
|
||||
|
||||
raise UnknownActionError.new(key) unless slice.key?(key)
|
||||
raise Routes::MissingActionError.new(key, slice) unless slice.key?(key)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -373,8 +373,9 @@ RSpec.describe "Hanami web app", :app_integration do
|
|||
require "hanami/boot"
|
||||
|
||||
expect { Hanami.app.rack_app }.to raise_error do |exception|
|
||||
expect(exception).to be_kind_of(Hanami::Slice::Routing::UnknownActionError)
|
||||
expect(exception.message).to include("missing.action")
|
||||
expect(exception).to be_kind_of(Hanami::Routes::MissingActionError)
|
||||
expect(exception.message).to include("Could not find action with key \"actions.missing.action\" in TestApp::App")
|
||||
expect(exception.message).to match(%r{define the action class TestApp::Actions::Missing::Action.+actions/missing/action.rb})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -404,8 +405,9 @@ RSpec.describe "Hanami web app", :app_integration do
|
|||
require "hanami/boot"
|
||||
|
||||
expect { Hanami.app.rack_app }.to raise_error do |exception|
|
||||
expect(exception).to be_kind_of(Hanami::Slice::Routing::UnknownActionError)
|
||||
expect(exception.message).to include("missing.action")
|
||||
expect(exception).to be_kind_of(Hanami::Routes::MissingActionError)
|
||||
expect(exception.message).to include("Could not find action with key \"actions.missing.action\" in Admin::Slice")
|
||||
expect(exception.message).to match(%r{define the action class Admin::Actions::Missing::Action.+slices/admin/actions/missing/action.rb})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -434,8 +436,9 @@ RSpec.describe "Hanami web app", :app_integration do
|
|||
expect { Hanami.app.rack_app }.not_to raise_error
|
||||
|
||||
expect { get "/missing" }.to raise_error do |exception|
|
||||
expect(exception).to be_kind_of(Hanami::Slice::Routing::UnknownActionError)
|
||||
expect(exception.message).to include("missing.action")
|
||||
expect(exception).to be_kind_of(Hanami::Routes::MissingActionError)
|
||||
expect(exception.message).to include("Could not find action with key \"actions.missing.action\" in TestApp::App")
|
||||
expect(exception.message).to match(%r{define the action class TestApp::Actions::Missing::Action.+actions/missing/action.rb})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -467,8 +470,9 @@ RSpec.describe "Hanami web app", :app_integration do
|
|||
expect { Hanami.app.rack_app }.not_to raise_error
|
||||
|
||||
expect { get "/admin/missing" }.to raise_error do |exception|
|
||||
expect(exception).to be_kind_of(Hanami::Slice::Routing::UnknownActionError)
|
||||
expect(exception.message).to include("missing.action")
|
||||
expect(exception).to be_kind_of(Hanami::Routes::MissingActionError)
|
||||
expect(exception.message).to include("Could not find action with key \"actions.missing.action\" in Admin::Slice")
|
||||
expect(exception.message).to match(%r{define the action class Admin::Actions::Missing::Action.+slices/admin/actions/missing/action.rb})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue