{"id":13484038,"url":"https://github.com/richpeck/exception_handler","last_synced_at":"2025-04-07T21:12:06.467Z","repository":{"id":17415619,"uuid":"20188534","full_name":"richpeck/exception_handler","owner":"richpeck","description":"Ruby on Rails Custom Error Pages","archived":false,"fork":false,"pushed_at":"2021-07-31T10:40:47.000Z","size":97963,"stargazers_count":510,"open_issues_count":28,"forks_count":70,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-03-31T20:07:29.295Z","etag":null,"topics":["email-notification","exception-handler","http","http-error-pages","http-errors","middleware","rails","rails-exceptions","rails-gem","ruby"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/richpeck.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-05-26T14:23:21.000Z","updated_at":"2025-03-22T15:25:21.000Z","dependencies_parsed_at":"2022-07-12T15:14:38.413Z","dependency_job_id":null,"html_url":"https://github.com/richpeck/exception_handler","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/richpeck%2Fexception_handler","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/richpeck%2Fexception_handler/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/richpeck%2Fexception_handler/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/richpeck%2Fexception_handler/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/richpeck","download_url":"https://codeload.github.com/richpeck/exception_handler/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247730068,"owners_count":20986404,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["email-notification","exception-handler","http","http-error-pages","http-errors","middleware","rails","rails-exceptions","rails-gem","ruby"],"created_at":"2024-07-31T17:01:18.439Z","updated_at":"2025-04-07T21:12:06.442Z","avatar_url":"https://github.com/richpeck.png","language":"Ruby","readme":"![Exception Handler](readme/title.jpg \"Exception Handler Logo\")\n\n\u003c!-- Intro --\u003e\n\u003cdiv id=\"intro\"\u003e\n  \u003ch4 align=\"center\"\u003e\u003ccode\u003e\u003cstrong\u003e\u003ca href=\"https://www.github.com/richpeck/exception_handler\"\u003eExceptionHandler\u003c/a\u003e\u003c/strong\u003e\u003c/code\u003e is presently the MOST POPULAR exceptions gem for \u003ca href=\"https://medium.com/ruby-on-rails-web-application-development/custom-400-500-error-pages-in-ruby-on-rails-exception-handler-3a04975e4677\"\u003eCUSTOM Rails error pages\u003c/a\u003e.\u003c/h4\u003e\n  \u003cp align=\"center\"\u003e\n    With \u003cstrong\u003e290,000+ downloads\u003c/strong\u003e, it is the *only* gem to provide \u003cstrong\u003ecustom 400/500 exception pages for Rails 5 \u0026 6\u003c/strong\u003e\n  \u003c/p\u003e\n  \u003cp\u003e\u003cimg src=\"./readme/dev.png\" /\u003e\u003c/p\u003e\n  \u003ch4 align=\"center\"\u003eCurrent \u003ca href=\"https://github.com/richpeck/exception_handler/releases\"\u003e\u003cu\u003e0.8.0.0\u003c/u\u003e\u003c/a\u003e (August 2018)\u003c/h4\u003e\n\u003c/div\u003e\n\n\u003c!-- Badges --\u003e\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"http://badge.fury.io/rb/exception_handler\"\u003e\u003cimg src=\"https://badge.fury.io/rb/exception_handler.svg\" align=\"absmiddle\"\u003e\u003c/a\u003e\n  \u003ca href=\"http://rubygems.org/gems/exception_handler\"\u003e\u003cimg src=\"http://ruby-gem-downloads-badge.herokuapp.com/exception_handler/0.5.1?type=total\u0026color=brightgreen\" align=\"absmiddle\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://codeclimate.com/github/richpeck/exception_handler\"\u003e\u003cimg src=\"https://codeclimate.com/github/richpeck/exception_handler/badges/gpa.svg\" align=\"absmiddle\"/\u003e\u003c/a\u003e\n  \u003ca href='https://coveralls.io/github/richpeck/exception_handler?branch=master'\u003e\u003cimg src='https://coveralls.io/repos/github/richpeck/exception_handler/badge.svg?branch=master' alt='Coverage Status' align=\"absmiddle\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://travis-ci.org/richpeck/exception_handler\"\u003e\u003cimg src=\"https://travis-ci.org/richpeck/exception_handler.svg?branch=master\" align=\"absmiddle\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003c!-- Navigation --\u003e\n\u003cdiv id=\"navigation\"\u003e\n  \u003cp align=\"center\"\u003e\u003cimg src=\"https://cdn-images-1.medium.com/max/800/1*CKyKxRXLovcrUOB-s8_jCw.png\" width=\"100%\" /\u003e\u003c/p\u003e\n  \u003cp align=\"center\"\u003e\n    \u003cstrong\u003e\n      📝 \u003ca href=\"#introduction\"\u003eIntroduction\u003c/a\u003e -\n      ⚠️ \u003ca href=\"#installation\"\u003eInstallation\u003c/a\u003e -\n      🔧 \u003ca href=\"#configuration\"\u003eConfiguration\u003c/a\u003e -\n      ☎️ \u003ca href=\"#support\"\u003eSupport\u003c/a\u003e -\n      ⭐ \u003ca href=\"#changelog\"\u003eChangelog\u003c/a\u003e\n    \u003c/strong\u003e\n  \u003c/p\u003e\n  \u003cp align=\"center\"\u003e\u003cimg src=\"https://cdn-images-1.medium.com/max/800/1*CKyKxRXLovcrUOB-s8_jCw.png\" width=\"100%\" /\u003e\u003c/p\u003e\n\u003c/div\u003e\n\n\u003c!-- Introduction --\u003e\n\u003cdiv id=\"introduction\"\u003e\n  \u003ch4\u003e📝 Introduction\u003c/h4\u003e\n\u003c/div\u003e\n\n---\n\u003cdiv\u003e\n  \u003cp\u003e\u003cb\u003e\u003ccode\u003eExceptionHandler\u003c/b\u003e\u003c/code\u003e replaces Rails' default error pages with \u003cstrong\u003edynamic views\u003c/strong\u003e.\u003c/p\u003e\n  \u003cp\u003eIt does this by injecting \u003ca href=\"https://guides.rubyonrails.org/configuring.html#rails-general-configuration\"\u003e\u003ccode\u003econfig.exceptions_app\u003c/code\u003e\u003c/a\u003e with our controller - allowing us to populate erroneous responses with our own HTML. To understand how this works, you need to appreciate how Rails handles errors:\u003c/p\u003e\n  \u003cp align=\"center\"\u003e\u003ca href=\"https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/middleware/show_exceptions.rb#L44\"\u003e\u003cimg src=\"readme/show_exceptions.png\" width=\"550\"\u003e\u003c/a\u003e\u003c/p\u003e\n  \u003cp\u003eRails uses \u003ca href=\"https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/middleware/show_exceptions.rb\"\u003e\u003ccode\u003e\u003cstrong\u003eActionDispatch::ShowExceptions\u003c/strong\u003e\u003c/code\u003e\u003c/a\u003e (above) to generate error responses.\u003c/p\u003e\n  \u003cp\u003eBecause web browsers (Rails is a web framework) can only interpret \u003ca href=\"https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Response_message\"\u003eHTTP responses\u003c/a\u003e, Ruby/Rails exceptions have to be translated into something a browser can read. This is done by calling the above middleware.\u003c/p\u003e\n  \u003cp\u003e--\u003c/p\u003e\n  \u003cp\u003eAs highlighted, an HTTP response is built independent of the Rails stack. This includes assigning an HTTP status code and HTML response body. It's the response body which \u003ccode\u003e\u003cstrong\u003eExceptionHandler\u003c/strong\u003e\u003c/code\u003e is designed to override.\u003c/p\u003e\n\u003c/div\u003e\n\n\u003c!-- Sep --\u003e\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://cdn-images-1.medium.com/max/800/1*CKyKxRXLovcrUOB-s8_jCw.png\" width=\"100%\" /\u003e\n\u003c/p\u003e\n\n\u003c!-- Installation --\u003e\n\u003cdiv id=\"installation\"\u003e\n  \u003ch4\u003e⚠️ Installation\u003c/h4\u003e\n\u003c/div\u003e\n\n---\n\n\u003cdiv\u003e\n  \u003cp\u003e\n    💎 \u003cu\u003e\u003ca href=\"https://rubygems.org/gems/exception_handler\"\u003eRubyGems\u003c/a\u003e\u003c/u\u003e (Code) |\n    💻 \u003cu\u003e\u003ca href=\"https://medium.com/ruby-on-rails-web-application-development/custom-400-500-error-pages-in-ruby-on-rails-exception-handler-3a04975e4677\"\u003eMedium\u003c/a\u003e\u003c/u\u003e (Tutorial)\n  \u003c/p\u003e\n  \u003cpre\u003e\u003ccode\u003e# Gemfile\ngem 'exception_handler', '~\u003e 0.8.0.0'\u003c/code\u003e\u003c/pre\u003e\n  \u003cp\u003eBecause \u003cb\u003eExceptionHandler\u003c/b\u003e is built around a Rails engine, there is \u003cb\u003enothing\u003c/b\u003e to be done to get it working in production. Installing the Gem \u003cb\u003e\u003ci\u003eshould\u003c/i\u003e\u003c/b\u003e translate your production 4xx/5xx error pages into dynamic views.\u003c/p\u003e\n  \u003cp\u003eEnvironments \u003cu\u003eother\u003c/u\u003e than production (development/staging) required the \u003ca href=\"#dev\"\u003e\u003ccode\u003edev\u003c/code\u003e\u003c/a\u003e variable to be \u003ccode\u003etrue\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\n\u003c!-- Sep --\u003e\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://cdn-images-1.medium.com/max/800/1*CKyKxRXLovcrUOB-s8_jCw.png\" width=\"100%\" /\u003e\n\u003c/p\u003e\n\n\u003c!-- configuration --\u003e\n\u003cdiv id=\"configuration\"\u003e\n  \u003ch4\u003e🔧 Configuration\u003c/h4\u003e\n\u003c/div\u003e\n\n---\n\n\u003cp align=\"center\"\u003e\n   \u003cg-emoji class=\"g-emoji\" alias=\"file_folder\" fallback-src=\"https://github.githubassets.com/images/icons/emoji/unicode/1f4c1.png\"\u003e📁\u003c/g-emoji\u003e \u003ca href=\"#config\"\u003eConfig\u003c/a\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cg-emoji class=\"g-emoji\" alias=\"computer\" fallback-src=\"https://github.githubassets.com/images/icons/emoji/unicode/1f4bb.png\"\u003e💻\u003c/g-emoji\u003e \u003ca href=\"#dev\" title=\"Dev Mode\"\u003eDev\u003c/a\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cg-emoji class=\"g-emoji\" alias=\"floppy_disk\" fallback-src=\"https://github.githubassets.com/images/icons/emoji/unicode/1f4be.png\"\u003e💾\u003c/g-emoji\u003e \u003ca href=\"#db\"\u003eDatabase\u003c/a\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cg-emoji class=\"g-emoji\" alias=\"email\" fallback-src=\"https://github.githubassets.com/images/icons/emoji/unicode/2709.png\"\u003e✉️\u003c/g-emoji\u003e   \u003ca href=\"#email\"\u003eEmail\u003c/a\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cg-emoji class=\"g-emoji\" alias=\"eyeglasses\" fallback-src=\"https://github.githubassets.com/images/icons/emoji/unicode/1f453.png\"\u003e👓\u003c/g-emoji\u003e \u003ca href=\"#views\"\u003eViews\u003c/a\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cg-emoji class=\"g-emoji\" alias=\"speech_balloon\" fallback-src=\"https://github.githubassets.com/images/icons/emoji/unicode/1f4ac.png\"\u003e💬\u003c/g-emoji\u003e \u003ca href=\"#locales\"\u003eLocales\u003c/a\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cg-emoji class=\"g-emoji\" alias=\"clipboard\" fallback-src=\"https://github.githubassets.com/images/icons/emoji/unicode/1f4cb.png\"\u003e📋\u003c/g-emoji\u003e \u003ca href=\"#layouts\"\u003eLayouts\u003c/a\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cg-emoji class=\"g-emoji\" alias=\"no_entry\" fallback-src=\"https://github.githubassets.com/images/icons/emoji/unicode/26d4.png\"\u003e⛔️\u003c/g-emoji\u003e \u003ca href=\"#custom-exceptions\"\u003eCustom Exceptions\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n\u003c!-- Config --\u003e\n\u003ca name=\"config\"\u003e\u003c/a\u003e\n\nThe **ONLY** thing you need to manage `ExceptionHandler` is its [`config`](https://github.com/richpeck/exception_handler/blob/master/lib/exception_handler/config.rb) settings.\n\nWhilst the gem **works out of the box** (without any configuration), if you want to manage the [`layouts`](#layouts), [`email`](#email), [`dev`](#dev) or the [`database`](#db), you'll need to set the appropriate values in the config hash.\n\nThis is done in `config/application.rb` or `config/environments/[env].rb` ↴\n\n```rb\n# config/application.rb\n\nmodule YourApp\n  class Application \u003c Rails::Application\n\n    # =\u003e This is an example of ALL available config options\n    # =\u003e You're able to see exactly how it works here:\n    # =\u003e https://github.com/richpeck/exception_handler/blob/master/lib/exception_handler/config.rb\n\n    # =\u003e Config hash (no initializer required)\n    config.exception_handler = {\n      dev:        nil, # allows you to turn ExceptionHandler \"on\" in development\n      db:         nil, # allocates a \"table name\" into which exceptions are saved (defaults to nil)\n      email:      nil, # sends exception emails to a listed email (string // \"you@email.com\")\n\n      # Custom Exceptions\n      custom_exceptions: {\n        #'ActionController::RoutingError' =\u003e :not_found # =\u003e example\n      },\n\n      # On default 5xx error page, social media links included\n      social: {        \n        facebook: nil, # Facebook page name   \n        twitter:  nil, # Twitter handle  \n        youtube:  nil, # Youtube channel name / ID\n        linkedin: nil, # LinkedIn name\n        fusion:   nil  # FL Fusion handle\n      },  \n\n      # This is an entirely NEW structure for the \"layouts\" area\n      # You're able to define layouts, notifications etc ↴\n\n      # All keys interpolated as strings, so you can use symbols, strings or integers where necessary\n      exceptions: {\n\n        :all =\u003e {\n          layout: \"exception\", # define layout\n          notification: true, # (false by default)\n          deliver: #something here to control the type of response\n        },\n        :4xx =\u003e {\n          layout: nil, # define layout\n          notification: true, # (false by default)\n          deliver: #something here to control the type of response    \n        },    \n        :5xx =\u003e {\n          layout: \"exception\", # define layout\n          notification: true, # (false by default)\n          deliver: #something here to control the type of response    \n        },\n        500 =\u003e {\n          layout: \"exception\", # define layout\n          notification: true, # (false by default)\n          deliver: #something here to control the type of response    \n        },\n\n        # This is the old structure\n        # Still works but will be deprecated in future versions\n\n        501 =\u003e \"exception\",\n        502 =\u003e \"exception\",\n        503 =\u003e \"exception\",\n        504 =\u003e \"exception\",\n        505 =\u003e \"exception\",\n        507 =\u003e \"exception\",\n        510 =\u003e \"exception\"\n\n      }\n    }\n  end\nend\n```  \n\nFor a full retinue of the available options, you'll be best looking at the [`config`](https://github.com/richpeck/exception_handler/blob/master/lib/exception_handler/config.rb) file itself.\n\n--\n\nIf using an [`engine`](http://guides.rubyonrails.org/engines.html), you **DON'T need an `initializer`**:\n```rb\n# lib/engine.rb\nmodule YourModule\n  class Engine \u003c Rails::Engine\n\n    # =\u003e ExceptionHandler\n    # =\u003e Works in and out of an initializer\n    config.exception_handler = {\n      dev: nil, # =\u003e this will not load the gem in development\n      db:  true # =\u003e this will use the :errors table to store exceptions\n    }\n  end\nend\n```\n\nThe best thing about using a `config` options block is that you are able to only define the options that you require.\n\nIf you have particular options you *only* wish to run in `staging`, or have single options for `production` etc, this setup gives you the ability to manage it properly...\n\n---\n\n\u003c!-- Dev --\u003e\n\u003cdiv id=\"dev\"\u003e\n  \u003ch5\u003e💻 Dev\u003c/h5\u003e\n\u003c/div\u003e\n\nAs explained, `ExceptionHandler` does *not* work in `development` by default.\n\nThis is because it overrides the `exceptions_app` middleware hook - which is *only* invoked in `production` or `staging`.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./readme/dev.png\" /\u003e\n\u003c/p\u003e\n\nTo get it working in `development`, you need to override the [`config.consider_all_requests_local`](http://guides.rubyonrails.org/configuring.html#rails-general-configuration) setting (a standard component of Rails) - setting it to \"false\" ↴\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./readme/local_requests.jpg\" /\u003e\n\u003c/p\u003e\n\nThis is normally done by changing the setting in your Rails config files. However, to make the process simpler for `ExceptionHandler`- we've added a `dev` option which allows you to override the hook through the context of the gem...\n\n```rb\n# config/application.rb\nconfig.exception_handler = { dev: true }\n```\n\nThis disables [`config.consider_all_requests_local`](http://guides.rubyonrails.org/configuring.html#rails-general-configuration), making Rails behave as it would in production.\n\nWhilst simple, it's not recommended for extended use. Very good for testing new ideas etc.\n\n---\n\n\u003c!-- DB --\u003e\n\u003cdiv id=\"db\"\u003e\n  \u003ch5\u003e💾 DB\u003c/h5\u003e\n\u003c/div\u003e\n\nTo save exceptions to your database, you're able to set the `db` option.\n\nBecause we use a `controller` to manage the underlying way the system works, we're able to invoke the likes of a [`model`](https://github.com/richpeck/exception_handler/blob/master/app/models/exception_handler/exception.rb) with other functionality.\n\nThs is done automatically with the latest version of `ExceptionHandler`.\n\nTo do this, once you've populated the option with either `true` or a `string`, run `rails db:migrate` from your console.\n\nOur new [`migration system`](https://github.com/richpeck/exception_handler/tree/readme#migrations) will automatically run the migration.\n\n```rb\n# config/application.rb\nconfig.exception_handler = { db: true }\n```\n\nThis enables `ActiveRecord::Base` on the [`Exception`](app/models/exception_handler/exception.rb) class, allowing us to save to the database.\n\nIn order for this to work, your db needs the correct table.\n\n---\n\n\u003c!-- Email --\u003e\n\u003cdiv id=\"email\"\u003e\n  \u003ch5\u003e✉️ Email\u003c/h5\u003e\n\u003c/div\u003e\n\n`ExceptionHandler` also sends **email notifications**.\n\nIf you want to receive emails whenever your application raises an error, you can do so by adding your email to the config:\n\n```rb\n# config/application.rb\nconfig.exception_handler = {\n  email: \"your@email.com\"\n}\n```\n\n\u003e **Please Note** this requires [`ActionMailer`](http://guides.rubyonrails.org/action_mailer_basics.html). If you don't have any outbound SMTP server, [`SendGrid`](http://sendgrid.com) is free.\n\nFrom version [`0.8.0.0`](https://github.com/richpeck/exception_handler/releases/tag/v0.8.0.0), you're able to define whether email notifications are sent on a per-error basis:\n\n```rb\n# config/application.rb\nconfig.exception_handlder = {\n\n  # This has to be present for any \"notification\" declarations to work\n  # Defaults to 'false'\n  email: \"test@test.com\",\n\n  # Each status code in the new \"exceptions\" block allows us to define whether email notifications are sent\n  exceptions: {\n    :all =\u003e { notification: true },\n    :50x =\u003e { notification: false },\n    500 =\u003e  { notification: false }\n  }\n}\n```\n---\n\n\u003c!-- Views --\u003e\n\u003cdiv id=\"views\"\u003e\n  \u003ch5\u003e👓 Views\u003c/h5\u003e\n\u003c/div\u003e\n\nWhat *most* people want out of the view is to change the way it ***looks***. This can be done without changing the \"view\" itself.\n\nTo better explain, if [`ExceptionsController`](https://github.com/richpeck/exception_handler/blob/master/app/controllers/exception_handler/exceptions_controller.rb) is invoked (by `exceptions_app`), it has **ONE** method ([`show`](https://github.com/richpeck/exception_handler/blob/master/app/controllers/exception_handler/exceptions_controller.rb#L42)).\n\nThis method calls the [`show` view](https://github.com/richpeck/exception_handler/blob/master/app/views/exception_handler/exceptions/show.html.erb), which is *entirely* dependent on the locales for content \u0026 the layout for the look.\n\nThis means that if you wish to change how the view \"looks\" - you're *either* going to want to change your [layout][layouts] or the [*locales*](#locales). There is NO reason to change the `show` view itself - it's succinct and entirely modular. Whilst you're definitely at liberty to change it, you'll just be making the issue more complicated than it needs to be.\n\n--\n\nWe've also included a number of routes which shows in [`dev`](dev) mode (allowing you to test):\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./readme/routes.jpg\" /\u003e\n\u003c/p\u003e\n\n---\n\n\u003c!-- Locales --\u003e\n\u003cdiv id=\"locales\"\u003e\n  \u003ch5\u003e💬 Locales\u003c/h5\u003e\n\u003c/div\u003e\n\n[Locales](https://github.com/richpeck/exception_handler/blob/Readme/config/locales/exception_handler.en.yml) are used to create interchangeable text (translations/internationalization).\n\n--\n\nIn `ExceptionHandler`, it provides the wording for each type of error code.\n\nBy default, the English name of the error is used (`\"404\"` will appear as `\"Not Found\"`) - if you want to create custom messages, you're able to do so by referencing the error's [\"status_code\"](https://github.com/rack/rack/blob/master/lib/rack/utils.rb#L492) within your locales file:\n\n```yml\n# config/locales/en.yml\nen:\n  exception_handler:\n    not_found:              \"Your message here\" # -\u003e 404 page\n    unauthorized:           \"You need to login to continue\"\n    internal_server_error:  \"This is a test to show the %{status} of the error\"\n```\n\nYou get access to [`%{message}` and `%{status}`](https://github.com/richpeck/exception_handler/blob/master/app/views/exception_handler/exceptions/show.html.erb#L1), both inferring from an [`@exception`](https://github.com/richpeck/exception_handler/blob/master/app/controllers/exception_handler/exceptions_controller.rb#L20) object we invoke in the controller...\n\n - `%{message}` is the error's actual message (\"XYZ file could not be shown\")\n - `%{status}` is the error's status code (\"Internal Server Error\")\n\n--\n\nBy default, only `internal_server_error` is customized by the gem:\n\n```yml\n# config/locales/en.yml\nen:\n  exception_handler:\n    internal_server_error: \"\u003cstrong\u003e%{status} Error\u003c/strong\u003e %{message}\"\n```\n---\n\n\u003c!-- Layouts --\u003e\n\u003cdiv id=\"layouts\"\u003e\n  \u003ch5\u003e📋 Layouts\u003c/h5\u003e\n\u003c/div\u003e\n\nThe most attractive feature of `ExceptionHandler` (for most) is its ability to manage [`layouts`](https://guides.rubyonrails.org/layouts_and_rendering.html#structuring-layouts) for HTTP status.\n\n--\n\nThe reason for this is due to the way in which Rails works → the \"layout\" is a \"wrapper\" for the returned HTML (the \"styling\" of a page). If you have no layout, it will render the \"view\" HTML and nothing else.\n\nThis means if you want to change the \"look\" of a Rails action, you simply have to be able to change the `layout`. You should not change the view at all.\n\nTo this end, `ExceptionHandler` has been designed around providing a [SINGLE VIEW](app/controllers/exception_handler/exceptions_controller.rb#L44) for exceptions. This view does not need to change (although you're welcome to use a [`generator`][generators] to do so) - the key is the `layout` that's assigned...\n\n- [`4xx`](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#4xx_Client_errors) errors are given a `nil` layout (by default) (inherits from `ApplicationController` in your main app)\n- [`5xx`](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#5xx_Server_errors) errors are assigned our own [`exception`](app/views/layouts/exception.html.erb) layout:\n\n```rb\n# config/application.rb\nconfig.exception_handler = {\n\n  # The new syntax allows us to assign different values to each HTTP status code\n  # At the moment, only 'layout' \u0026 'notification' are supported\n  # We plan to include several more in the future...\n\n  exceptions: {\n    all: { layout: nil } # -\u003e this will inherit from ApplicationController's layout\n  }\n}\n```\n\nThe `layout` system has changed between [`0.7.7.0`](releases/tag/v0.7.7.0) and [`0.8.0.0`](releases/tag/v0.8.0.0).\n\nBuilding on the former's adoption of HTTP status-centric layouts, it is now the case that we have the `all`, `5xx` and `4xx` options - allowing us to manage the layouts for blocks of HTTP errors respectively:\n\n```rb\n# config/application.rb\nconfig.exception_handler = {\n\n  # Old (still works)\n  # No \"all\" / \"4xx\"/\"5xx\" options\n  layouts: {\n    500 =\u003e 'exception',\n    501 =\u003e 'exception'\n  },\n\n  # New\n  exceptions: {\n    :all =\u003e { layout: 'exception' },\n    :4xx =\u003e { layout: 'exception' },\n    :5xx =\u003e { layout: 'exception' }, # -\u003e this overrides the :all declaration\n    500  =\u003e { layout: nil } # -\u003e this overrides the 5xx declaration\n  }\n}\n```\n\nWe've bundled the [`exception`](app/views/layouts/exception.html.erb) layout for `5xx` errors because since these denote internal server errors, it's best to isolate the view system as much as possible. Whilst you're at liberty to change it, we've found it sufficient for most use-cases.\n\n---\n\n\u003c!-- Custom Exceptions --\u003e\n\u003cdiv id=\"custom-exceptions\"\u003e\n  \u003ch5\u003e⛔️ Custom Exceptions\u003c/h5\u003e\n\u003c/div\u003e\n\nAs mentioned, Rails' primary role is to convert Ruby exceptions into HTTP errors.\n\nPart of this process involves mapping Ruby/Rails exceptions to the equivalent HTTP status code.\n\nThis is done with [`config.action_dispatch.rescue_responses`](https://github.com/rack/rack/blob/master/lib/rack/utils.rb#L492).\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./readme/custom_exceptions.png\" /\u003e\n\u003c/p\u003e\n\nWhilst this works well, it may be the case that you want to map your own classes to an HTTP status code (default is `Internal Server Error`).\n\nIf you wanted to keep this functionality inside `ExceptionHandler`, you're able to do it as follows:\n\n```rb\n# config/application.rb\nconfig.exception_handler = {\n  custom_exceptions: {\n    'CustomClass::Exception' =\u003e :not_found\n  }\n}\n```\n\nAlternatively, you're able to still do it with the default Rails behaviour:\n\n```rb\n# config/application.rb\nconfig.action_dispatch.rescue_responses = { 'CustomClass::Exception' =\u003e :not_found }\n```\n---\n\n\u003c!-- Generators --\u003e\n\u003cdiv id=\"generators\"\u003e\n  \u003ch5\u003e💼 Generators\u003c/h5\u003e\n\u003c/div\u003e\n\nIf you want to edit the `controller`, `views`, `model` or `assets`, you're able to invoke them in your own application.\n\nThis is done - as with other gems - with a single [`generator`](https://github.com/richpeck/exception_handler/blob/master/lib/generators/exception_handler/views_generator.rb) which takes a series of arguments:\n\n    rails g exception_handler:views\n    rails g exception_handler:views -v views\n    rails g exception_handler:views -v controllers\n    rails g exception_handler:views -v models\n    rails g exception_handler:views -v assets\n    rails g exception_handler:views -v views controllers models assets\n\nIf you don't include any switches, this will copy **all** `ExceptionHandler`'s folders put into your app.\n\nEach switch defines which folders you want (EG `-v views` will only copy `views` dir).\n\n---\n\n\u003c!-- Migrations --\u003e\n\u003cdiv id=\"migrations\"\u003e\n  \u003ch5\u003e✔️ Migrations\u003c/h5\u003e\n\u003c/div\u003e\n\nYou **DON'T** need to generate a migration anymore.\n\nFrom [`0.7.5`](https://github.com/richpeck/exception_handler/releases/tag/0.7.5), the `migration` generator has been removed in favour of our own [migration system](lib/exception_handler/engine.rb#L58).\n\nThe reason we did this was so not to pollute your migrations folder with a worthless file. Our migration doesn't need to be changed - we only have to get it into the database and the gem takes care of the rest...\n\n\u003e If you set the [`db`][db] option in config, run `rails db:migrate` and the migration will be run.\n\nTo rollback, use the following:\n\n    rails db:migrate:down VERSION=000000\n\nThe drawback to this is that if you remove `ExceptionHandler` before you rollback the migration, it won't exist anymore.\n\nYou can **only** fire the `rollback` when you have `ExceptionHandler` installed.\n\n\u003c!-- Sep --\u003e\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://cdn-images-1.medium.com/max/800/1*CKyKxRXLovcrUOB-s8_jCw.png\" width=\"100%\" /\u003e\n\u003c/p\u003e\n\n\u003c!-- Support--\u003e\n\u003cdiv id=\"support\"\u003e\n  \u003ch4\u003e☎️ Support\u003c/h4\u003e\n\u003c/div\u003e\n\n---\n\n\u003cdiv\u003e\n  \u003cp\u003eYou're welcome to contact me directly at \u003cu\u003e\u003ca href=\"mailto:rpeck@frontlineutilities.co.uk\"\u003e\u003c/a\u003e\u003ca href=\"mailto:rpeck@frontlineutilities.co.uk\" ref=\"nofollow\"\u003erpeck@frontlineutilities.co.uk\u003c/a\u003e\u003c/u\u003e.\u003c/p\u003e\n  \u003cp\u003eAlternatively, you may wish to post on our \u003cu\u003e\u003ca href=\"https://github.com/richpeck/exception_handler/issues\"\u003eGitHub Issues\u003c/a\u003e\u003c/u\u003e, or \u003cu\u003e\u003ca href=\"https://stackoverflow.com/questions/tagged/ruby-on-rails+exceptionhandler\" rel=\"nofollow\"\u003eStackOverflow\u003c/a\u003e\u003c/u\u003e.\u003c/p\u003e\n  \u003cp\u003e--\u003c/p\u003e\n  \u003cp\u003e\u003ca href=\"https://medium.com/ruby-on-rails-web-application-development/custom-400-500-error-pages-in-ruby-on-rails-exception-handler-3a04975e4677\" rel=\"nofollow\"\u003e\u003cimg src=\"readme/medium.png\" target=\"_blank\" alt=\"Medium\" style=\"max-width:100%;\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003c/div\u003e\n\n\u003c!-- Sep --\u003e\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://cdn-images-1.medium.com/max/800/1*CKyKxRXLovcrUOB-s8_jCw.png\" width=\"100%\" /\u003e\n\u003c/p\u003e\n\n\u003c!-- Changelog --\u003e\n\u003cdiv id=\"changelog\"\u003e\n  \u003ch4\u003e⭐ Changelog\u003c/h4\u003e\n\u003c/div\u003e\n\n---\n\n[**1.0.0.0**](https://github.com/richpeck/exception_handler/releases/tag/v1.0.0.0)\n  - [ ] TBA\n\n[**0.8.0.0**](https://github.com/richpeck/exception_handler/releases/tag/v0.8.0.0)\n - [x] [README](https://github.com/richpeck/exception_handler/issues/52) (focus on utility)\n - [x] Introduction of `4xx`,`5xx`,`:all` for layouts config\n - [x] Changed `layouts` to `exceptions` in config    \n - [x] Email improvement\n - [x] Streamlined migration\n - [x] Updated model\n\n[**0.7.7.0**](https://github.com/richpeck/exception_handler/releases/tag/v0.7.7.0)\n - [x] [HTTP status layouts](#layouts)\n\n**0.7.0.0**\n - [x] Wildcard mime types\n - [x] [Custom exceptions](#custom_exceptions)\n - [x] Test suite integration\n - [x] [Model backend](#database)\n - [x] Sprockets 4+\n - [x] New layout\n - [x] Readme / wiki overhaul\n\n**0.6.5.0**\n - [x] Streamlined interface\n - [x] ActiveRecord / Middleware overhaul\n - [x] Supports Sprockets 4+ ([`manifest.js`](http://eileencodes.com/posts/the-sprockets-4-manifest/))\n - [x] Email integration\n - [x] Asset overhaul \u0026 improvement\n - [x] Removed dependencies\n\n**0.5.0.0**\n - [x] Locales\n - [x] Email notifications\n - [x] Full test suite\n - [x] Rails 4.2 \u0026 Rails 5.0 native ([`request.env`](https://github.com/rails/rails/commit/05934d24aff62d66fc62621aa38dae6456e276be) fix)\n - [x] Controller fixed\n - [x] `DB` fixed\n - [x] Legacy initializer support ([more](https://github.com/richpeck/exception_handler/wiki/1-Setup))\n - [x] Rails asset management improvement\n - [x] Reduced gem file size\n\n**0.4.7.0**\n - [x] New config system\n - [x] Fixed controller layout issues\n - [x] Streamlined middleware\n - [x] New layout \u0026 interface\n\n \u003c!-- Sep --\u003e\n \u003cp align=\"center\"\u003e\n   \u003cimg src=\"https://cdn-images-1.medium.com/max/800/1*CKyKxRXLovcrUOB-s8_jCw.png\" width=\"100%\" /\u003e\n \u003c/p\u003e\n\n [![404 + 500 Errors][banner]][rubygems]\n\n \u003cp align=\"center\"\u003e\n   \u003cstrong\u003e\u003ca href=\"https://rubygems.org/gems/exception_handler\"\u003e\u003ccode\u003eExceptionHandler\u003c/code\u003e\u003c/a\u003e provides custom error pages gem for Rails 5+\u003c/strong\u003e\n   \u003cbr /\u003e\n   No other gem is as simple or effective at providing branded exception pages in production\n \u003c/p\u003e\n\n \u003cp align=\"center\"\u003e\n   \u003ca href=\"http://badge.fury.io/rb/exception_handler\"\u003e\u003cimg src=\"https://badge.fury.io/rb/exception_handler.svg\" align=\"absmiddle\"\u003e\u003c/a\u003e\n   \u003ca href=\"http://rubygems.org/gems/exception_handler\"\u003e\u003cimg src=\"http://ruby-gem-downloads-badge.herokuapp.com/exception_handler/0.5.1?type=total\u0026color=brightgreen\" align=\"absmiddle\" /\u003e\u003c/a\u003e\n   \u003ca href=\"https://codeclimate.com/github/richpeck/exception_handler\"\u003e\u003cimg src=\"https://codeclimate.com/github/richpeck/exception_handler/badges/gpa.svg\" align=\"absmiddle\"/\u003e\u003c/a\u003e\n   \u003ca href='https://coveralls.io/github/richpeck/exception_handler?branch=master'\u003e\u003cimg src='https://coveralls.io/repos/github/richpeck/exception_handler/badge.svg?branch=master' alt='Coverage Status' align=\"absmiddle\" /\u003e\u003c/a\u003e\n   \u003ca href=\"https://travis-ci.org/richpeck/exception_handler\"\u003e\u003cimg src=\"https://travis-ci.org/richpeck/exception_handler.svg?branch=master\" align=\"absmiddle\"\u003e\u003c/a\u003e\n \u003c/p\u003e\n\n \u003cp align=\"center\"\u003e\n   \u003cstrong\u003e➡️ \u003ca href=\"https://rubygems.org/gems/exception_handler\"\u003eDownload \u0026 Info\u003c/a\u003e ⬅️\u003c/strong\u003e\n \u003c/p\u003e\n\n \u003c!-- Sep --\u003e\n \u003cp align=\"center\"\u003e\n   \u003cimg src=\"https://cdn-images-1.medium.com/max/800/1*CKyKxRXLovcrUOB-s8_jCw.png\" width=\"100%\" /\u003e\n \u003c/p\u003e\n\n:copyright: \u003ca href=\"http://www.fl.co.uk\" align=\"absmiddle\" \u003e\u003cimg src=\"readme/fl.jpg\" height=\"22\" align=\"absmiddle\" /\u003e\u003c/a\u003e \u003ca href=\"http://stackoverflow.com/users/1143732/richard-peck?tab=profile\" align=\"absmiddle\" \u003e\u003cimg src=\"https://avatars0.githubusercontent.com/u/1104431\" height=\"22\" align=\"absmiddle\" /\u003e\u003c/a\u003e \u003ca href=\"https://github.com/joehilton\" align=\"absmiddle\" \u003e\u003cimg src=\"https://avatars2.githubusercontent.com/u/5063592?s=460\u0026v=4\" height=\"22\" align=\"absmiddle\" /\u003e\u003c/a\u003e \u003ca href=\"https://github.com/toymachiner62\" align=\"absmiddle\" \u003e\u003cimg src=\"https://avatars3.githubusercontent.com/u/485782\" height=\"22\" align=\"absmiddle\" /\u003e\u003c/a\u003e \u003ca href=\"https://github.com/andrewclink\" align=\"absmiddle\" \u003e\u003cimg src=\"https://avatars0.githubusercontent.com/u/688916\" height=\"22\" align=\"absmiddle\" /\u003e\u003c/a\u003e \u003ca href=\"https://github.com/Startouf\" align=\"absmiddle\" \u003e\u003cimg src=\"https://avatars2.githubusercontent.com/u/7388889\" height=\"22\" align=\"absmiddle\" /\u003e\u003c/a\u003e \u003ca href=\"https://github.com/Tonkonozhenko\" align=\"absmiddle\" \u003e\u003cimg src=\"https://avatars0.githubusercontent.com/u/1307646\" height=\"22\" align=\"absmiddle\" /\u003e\u003c/a\u003e \u003ca href=\"https://github.com/mabako\" align=\"absmiddle\" \u003e\u003cimg src=\"https://avatars3.githubusercontent.com/u/125113\" height=\"22\" align=\"absmiddle\" /\u003e\u003c/a\u003e \u003ca href=\"https://github.com/frankzhao\" align=\"absmiddle\" \u003e\u003cimg src=\"https://avatars3.githubusercontent.com/u/555499\" height=\"22\" align=\"absmiddle\" /\u003e\u003c/a\u003e\n\n\n\u003c!-- ################################### --\u003e\n\u003c!-- ################################### --\u003e\n\n\u003c!-- Refs --\u003e\n\u003c!-- Comments http://stackoverflow.com/a/20885980/1143732 --\u003e\n\u003c!-- Images   https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#images --\u003e\n\n\u003c!-- Images --\u003e\n[banner]:readme/banner.jpg\n\n\u003c!-- Links --\u003e\n[rubygems]: http://rubygems.org/gems/exception_handler\n\n[10x]: https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#1xx_Informational_responses\n[20x]: https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#2xx_Success\n[30x]: https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#3xx_Redirection\n[40x]: https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#4xx_Client_errors\n[50x]: https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#5xx_Server_errors\n\n\u003c!-- Local Links --\u003e\n[db]: #db\n[email]: #email\n[dev]: #dev\n[layouts]: #layouts\n[locales]: #locales\n[configuration]: #configuration\n[generators]: #generators\n[custom-exceptions]: #custom-exceptions\n\n\u003c!-- ################################### --\u003e\n\u003c!-- ################################### --\u003e\n","funding_links":[],"categories":["Error Handling","Ruby"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frichpeck%2Fexception_handler","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frichpeck%2Fexception_handler","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frichpeck%2Fexception_handler/lists"}