-
-
Notifications
You must be signed in to change notification settings - Fork 4
Open
Labels
enhancementNew feature or requestNew feature or request
Description
Is your feature request related to a problem? Please describe.
Splode injects a handful of fields that, when used, result in potentially confusing warnings/errors.
Example adapted from the Getting Started guide (note the :path field in MyApp.Errors.InvalidPath):
Mix.install([
:splode
])
defmodule MyApp.Errors do
use Splode,
error_classes: [
invalid: MyApp.Errors.Invalid,
unknown: MyApp.Errors.Unknown
],
unknown_error: MyApp.Errors.Unknown.Unknown
end
# Error classes are splode errors with an `errors` key.
defmodule MyApp.Errors.Invalid do
use Splode.Error, fields: [:errors], class: :invalid
def splode_message(%{errors: errors}) do
Splode.ErrorClass.error_messages(errors)
end
end
# You will want to define an unknown error class,
# otherwise splode will use its own
defmodule MyApp.Errors.Unknown do
use Splode.Error, fields: [:errors], class: :unknown
def splode_message(%{errors: errors}) do
Splode.ErrorClass.error_messages(errors)
end
end
# This fallback exception will be used for unknown errors
defmodule MyApp.Errors.Unknown.Unknown do
use Splode.Error, fields: [:error], class: :unknown
# your unknown message should have an `error` key
def splode_message(%{error: error}) do
if is_binary(error) do
to_string(error)
else
inspect(error)
end
end
end
# Finally, you can create your own error classes
defmodule MyApp.Errors.InvalidPath do
use Splode.Error, fields: [:name, :path], class: :invalid
def splode_message(%{name: name, path: path}) do
"Invalid path #{name}: #{path}"
end
end
defmodule Example do
def main do
errors = [MyApp.Errors.InvalidPath.exception(path: "path")]
raise MyApp.Errors.to_class(errors)
end
end
Example.main()$ elixir splode1.exs
warning: duplicate key :path found in struct
│
50 │ use Splode.Error, fields: [:name, :path], class: :invalid
│ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
│
└─ splode1.exs:50: MyApp.Errors.InvalidPath (module)
** (MyApp.Errors.Invalid) got Protocol.UndefinedError with message "protocol Enumerable not implemented for \"path\" of type BitString. This protocol is implemented for the following type(s): Date.Range, File.Stream, Function, GenEvent.Stream, HashDict, HashSet, IO.Stream, List, Map, MapSet, Range, Stream" while retrieving Exception.message/1 for %MyApp.Errors.Invalid{errors: [%MyApp.Errors.InvalidPath{name: nil, path: "path", bread_crumbs: [], vars: [], path: "path", stacktrace: #Splode.Stacktrace<>, class: :invalid}], bread_crumbs: [], vars: [], path: [], stacktrace: #Splode.Stacktrace<>, class: :invalid}. Stacktrace:
(elixir 1.16.2) lib/enum.ex:1: Enumerable.impl_for!/1
(elixir 1.16.2) lib/enum.ex:166: Enumerable.reduce/3
(elixir 1.16.2) lib/enum.ex:4396: Enum.map_intersperse/3
(elixir 1.16.2) lib/enum.ex:1801: Enum.map_join/3
(splode 0.1.1) lib/splode/error_class.ex:54: Splode.ErrorClass.path/1
(splode 0.1.1) lib/splode/error_class.ex:23: anonymous fn/1 in Splode.ErrorClass.error_messages/2
(elixir 1.16.2) lib/enum.ex:1801: anonymous fn/2 in Enum.map_join/3
(elixir 1.16.2) lib/enum.ex:4378: Enum.map_intersperse_list/3
splode1.exs:60: Example.main/0
splode1.exs:64: (file)
Describe the solution you'd like
- Splode could raise an exception at compile-time if a reserved field is used.
- If the reserved fields aren't a part of any public API for Splode, it could additionally format them as
:__path__etc. to decrease the likelihood of collision.
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request