All Versions
9
Latest Version
Avg Release Cycle
15 days
Latest Release
2669 days ago

Changelog History

  • v2.1.0 Changes

    December 28, 2016

    โž• Added ensure!/1 and def!/2

    ensure is essentially an alias for foo >>> fn x -> x end.()

    ensure!([1, 2, 3])#=\> [1, 2, 3]%ArgumentError{message: "raise me"} |\> ensure!#=\> \*\* (ArgumentError) raise me
    

    ๐Ÿ‘ป def! foo(...) helps define a def foo(...) plus def foo!(...) variant that raises any final exception from foo

    defmodule Foo douse Exceptional def! foo(a), do: aendFoo.foo([1, 2, 3])#=\> [1, 2, 3]Foo.foo(%ArgumentError{message: "raise me"})#=\> %ArgumentError{message: "raise me"}Foo.foo!([1, 2, 3])#=\> [1, 2, 3]Foo.foo!(%ArgumentError{message: "raise me"})#=\> \*\* (ArgumentError) raise me
    
  • v2.0.0 Changes

    December 20, 2016

    Phoenix/Exceptional helpers now live here

  • v1.5.0 Changes

    December 18, 2016

    Phoenix Error View Helpers

    ๐Ÿ‘ป Automated rendering of error views based on the message field on exception structs.
    ๐Ÿš€ This is often sufficient for simple JSON cases and pre-release HTML. It is recommended to write custom error views before production to give your users as much detail as possible in the user friendliest way that their content type allows.

    # /web/views/error\_view.exdefrender :error, for: 401, do: "Not authorized"defrender :error, for: 404, only: [:json], do: "Data not found"defrender :error, for: 422, except: [:html] do: "Unprocessible entity"defrender :error, for: 500, do: "Server internal error"# Example JSON Error Response404 %{error: "Data not found", reason: "Photo deleted"}# Example HTML Error Response500 "Server internal error"
    
  • v1.4.0 Changes

    December 18, 2016

    A long-requested feature. I'm finally caving and writing it ๐Ÿ˜œ

    normalize(42)#=\> 42normalize(%Enum.OutOfBoundsError{message: "out of bounds error"})#=\> %Enum.OutOfBoundsError{message: "out of bounds error"}normalize(:error)#=\> %ErlangError{original: nil}normalize({:error, "boom"})#=\> %ErlangError{original: "boom"}normalize({:error, {1, 2, 3}})#=\> %ErlangError{original: {1, 2, 3}}normalize({:error, "boom with stacktrace", ["trace"]})#=\> %ErlangError{original: "boom with stacktrace"}normalize({:good, "tuple", ["value"]})#=\> {:good, "tuple", ["value"]}
    

    Something similar was suggested back in #2. I still believe that you should pattern match as much as possible, making normalize superfluous... but this pipes well enough in most situations.

    This isn't a complete solution for all tagged tuples. In fact, it is emphatically not that. For example:

    normalize({:my\_special, "tuple", ["value"]})#=\> {:my\_special, "tuple", ["value"]}
    

    ๐Ÿฑ โ˜๏ธ You'll still need to handle those cases in pattern matches yourself (unless you do want the tuple value, which is a common case). To do this, you may pass an additional converting function. Example:

    {:oh\_no, {"something bad happened", %{bad: :thing}}}|\> normalize(fn {:oh\_no, {message, \_}} -\> %File.Error{reason: message}) # This case {:bang, message -\> %File.CopyError{reason: message}) otherwise -\> otherwiseend)#=\> %File.Error{message: msg}{:oh\_yes, {1, 2, 3}}|\> normalize(fn {:oh\_no, {message, \_}} -\> %File.Error{reason: message}) {:bang, message -\> %File.CopyError{reason: message}) otherwise -\> otherwise # This caseend)#=\> {:oh\_yes, {1, 2, 3}}
    

    ๐Ÿฑ The advantage for all of the common patterns is that we have a single struct representation for pattern matching (unless the error tuple is not one of the most common cases). Hopefully including this function doesn't cause any confusion ๐Ÿ˜จ Time will tell...

  • v1.3.0 Changes

    December 18, 2016

    safe/1 & safe/2 (plus pun aliases: lower/1 and lower/2 make functions that raise exceptions return those exceptions instead.

    Does not catch throws, because that causes all sorts of odd behaviour (REPL errors returned as tuples or (structs if normalized), then they get piped into functions... all sorts of mess).

    toothless\_fetch = safe(&Enum.fetch!/2) [1,2,3] |\> toothless\_fetch.(1)#=\> 2toothless = safe(&Enum.fetch!/2) [1,2,3] |\> toothless.(999)#=\> %Enum.OutOfBoundsError{message: "out of bounds error"}safe(&Enum.fetch!/2).([1,2,3], 999)#=\> %Enum.OutOfBoundsError{message: "out of bounds error"}
    
  • v1.2.1 Changes

    August 31, 2016

    ~~~

    โž• Added a unary ~~~ operator for converting back to a tagged status.

    More uses

    # Defaultuse Exceptional# Only operators use Exceptional, only: :operators#Only named functions use Exceptional, only: :named\_functions# If you like to live extremely dangerously. This is \_not recommended\_. # Please be certain that you want to override the standard lib before using.use Exceptional, include: :overload\_pipe
    
  • v1.1.0 Changes

    August 28, 2016

    โž• Added if_exception, which has the ability to take the familiar forms:

    if\_exception [1,2,3], do: fn %{message: msg} -\> msg end.(), else: Quark.id if\_exception [1,2,3] dofn %{message: msg} -\> msg end.()elseQuark.idend
    
  • v1.0.4 Changes

    August 28, 2016

    ๐Ÿฑ Minor fixes ๐Ÿ”ง

    • ๐Ÿ‘Œ Improve README
    • ๐Ÿ›  Fix use Exceptional typo
  • v1.0.0 Changes

    August 28, 2016

    ๐Ÿฑ First full version ๐ŸŽ‰๐ŸŽ‰๐ŸŽ‰

    ๐Ÿ“ฆ Package allows you to delay raiseing exceptions as long as possible, delegating control to the caller. Also provides a nice alternative to the {:tag, "message"} pattern, with much more possible information, given that Exception can be implemented for any struct.