gaffe-1.2.0/ 0000755 0001750 0001751 00000000000 14124547074 011407 5 ustar rmb571 rmb571 gaffe-1.2.0/.travis.yml 0000644 0001750 0001751 00000001476 14124547074 013530 0 ustar rmb571 rmb571 language: ruby rvm: - 2.3.0 - 2.1 - 2.0 sudo: false gemfile: - gemfiles/Gemfile.rails-4.2 - gemfiles/Gemfile.rails-4.0 - gemfiles/Gemfile.rails-5.0 script: - 'echo "Checking code style" && bundle exec phare' - 'echo "Running specs" && bundle exec rake spec' matrix: exclude: - rvm: 2.0 gemfile: gemfiles/Gemfile.rails-5.0 - rvm: 2.1 gemfile: gemfiles/Gemfile.rails-5.0 notifications: hipchat: rooms: secure: HwIKOZp8SIVCnPseNTJqZgrUBr7/7z5RGczqX7lGWOXK/S6Zwm/YyglC5ueN+HW2Tsc9nQkVLmLb7fH4kctdeanKea3TTfYS1+GmUOZPhFie4nFnywIgz7os//LfNONIF42Ix94HsmuhsQ6yVPMOU+mYnN9L/ZrWML5NH03mIOw= template: - '%{repository}#%{build_number} (%{branch} - %{commit} : %{author}): %{message} (Build/Changes)' format: 'html' gaffe-1.2.0/spec/ 0000755 0001750 0001751 00000000000 14124547074 012341 5 ustar rmb571 rmb571 gaffe-1.2.0/spec/gaffe/ 0000755 0001750 0001751 00000000000 14124547074 013411 5 ustar rmb571 rmb571 gaffe-1.2.0/spec/gaffe/errors_controller_resolver_spec.rb 0000644 0001750 0001751 00000003464 14124547074 022457 0 ustar rmb571 rmb571 require 'spec_helper' describe Gaffe::ErrorsControllerResolver do describe :resolved_controller do let(:resolver) { Gaffe::ErrorsControllerResolver.new(env) } let(:controller) { resolver.resolved_controller } let(:request) { test_request } let(:env) { request.env } context 'with custom-defined controller' do before do Gaffe.configure do |config| config.errors_controller = :foo end end it { expect(controller).to eql :foo } end context 'with custom-defined controller that respond to `#constantize`' do before do Gaffe.configure do |config| config.errors_controller = 'String' end end it { expect(controller).to eql String } end context 'with multiple custom-defined controllers' do before do Gaffe.configure do |config| config.errors_controller = { %r{^/web/} => :web_controller, %r{^/api/} => :api_controller, %r{^www.com} => :host_specific_controller } end end context 'with error coming from matching URL' do let(:env) { request.env.merge 'REQUEST_URI' => '/api/users' } it { expect(controller).to eql :api_controller } end context 'with error coming from matching HTTP_HOST' do let(:env) { request.env.merge('HTTP_HOST' => 'www.com', 'REQUEST_URI' => '/') } it { expect(controller).to eql :host_specific_controller } end context 'with errors coming from non-matching URL' do let(:env) { request.env.merge 'REQUEST_URI' => '/what' } it { expect(controller).to eql Gaffe::ErrorsController } end end context 'without custom-defined controller' do it { expect(controller).to eql Gaffe::ErrorsController } end end end gaffe-1.2.0/spec/gaffe/gaffe_spec.rb 0000644 0001750 0001751 00000002141 14124547074 016016 0 ustar rmb571 rmb571 require 'spec_helper' describe Gaffe do describe :ClassMethods do describe :configure do let(:configuration) { Gaffe.configuration } before do Gaffe.configure do |config| config.foo = :bar config.bar = :foo end end it { expect(configuration.foo).to eql :bar } it { expect(configuration.bar).to eql :foo } end describe :enable! do let(:env) { test_request.env } let(:action_double) { double(call: proc { [400, {}, 'SOMETHING WENT WRONG.'] }) } before { Gaffe.enable! } specify do expect(Gaffe).to receive(:errors_controller_for_request).with(env).and_call_original expect(Gaffe::ErrorsController).to receive(:action).with(:show).and_return(action_double) expect(action_double).to receive(:call).with(env) # This is the line Rails itself calls # https://github.com/rails/rails/blob/fee49a10492efc99409c03f7096d5bd3377b0bbc/actionpack/lib/action_dispatch/middleware/show_exceptions.rb#L43 Rails.application.config.exceptions_app.call(env) end end end end gaffe-1.2.0/spec/gaffe/errors_spec.rb 0000644 0001750 0001751 00000002217 14124547074 016266 0 ustar rmb571 rmb571 require 'spec_helper' describe Gaffe::Errors do describe :Actions do describe :show do let(:request) { test_request } let(:env) { request.env.merge 'action_dispatch.exception' => exception } let(:status) { response.first } let(:body) { response.last.body } let(:response) do Gaffe.errors_controller_for_request(env).action(:show).call(env) end context 'with builtin exception' do let(:exception) { ActionController::RoutingError.new(:foo) } it { expect(status).to eql 404 } it { expect(body).to match(/Not Found/) } end context 'with custom exception and missing view' do before { ActionDispatch::ExceptionWrapper.rescue_responses.merge! exception_class.name => 'my_custom_error' } let(:exception_class) do Object.instance_eval { remove_const :MyCustomError } if Object.const_defined?(:MyCustomError) MyCustomError = Class.new(StandardError) end let(:exception) { exception_class.new } it { expect(status).to eql 500 } it { expect(body).to match(/Internal Server Error/) } end end end end gaffe-1.2.0/spec/application_controller_helper.rb 0000644 0001750 0001751 00000000226 14124547074 020773 0 ustar rmb571 rmb571 # We need a fake "ApplicationController" because Gaffe's default controller inherits from it class ApplicationController < ActionController::Base end gaffe-1.2.0/spec/spec_helper.rb 0000644 0001750 0001751 00000002057 14124547074 015163 0 ustar rmb571 rmb571 $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__) require 'rspec' require 'action_controller/railtie' require 'gaffe' require_relative './application_controller_helper' require 'gaffe/errors_controller' RSpec.configure do |config| # Disable `should` syntax config.expect_with :rspec do |c| c.syntax = :expect end config.before(:each) do # Fake Rails.root allow(Rails).to receive(:root).and_return(RAILS_ROOT) # Fake Rails.application application = double('Rails Application', config: OpenStruct.new, env_config: {}) allow(Rails).to receive(:application).and_return(application) # Make sure we clear memoized variables before each test [:@configuration].each do |variable| Gaffe.send :remove_instance_variable, variable if Gaffe.instance_variable_defined?(variable) end end end def test_request if Rails::VERSION::MAJOR >= 5 ActionDispatch::TestRequest.create else ActionDispatch::TestRequest.new end end # We need Rails.root RAILS_ROOT = Pathname.new(File.expand_path('../../', __FILE__)) gaffe-1.2.0/.rubocop.yml 0000644 0001750 0001751 00000001023 14124547074 013655 0 ustar rmb571 rmb571 AllCops: Include: - Gemfile - Rakefile Exclude: - vendor/*/** Documentation: Enabled: false Encoding: Enabled: false LineLength: Max: 200 AccessModifierIndentation: EnforcedStyle: outdent IfUnlessModifier: Enabled: false CaseIndentation: IndentWhenRelativeTo: case IndentOneStep: true MethodLength: CountComments: false Max: 20 SignalException: Enabled: false ColonMethodCall: Enabled: false AsciiComments: Enabled: false Lambda: Enabled: false RegexpLiteral: Enabled: false gaffe-1.2.0/.phare.yml 0000644 0001750 0001751 00000000022 14124547074 013301 0 ustar rmb571 rmb571 only: - rubocop gaffe-1.2.0/lib/ 0000755 0001750 0001751 00000000000 14124547074 012155 5 ustar rmb571 rmb571 gaffe-1.2.0/lib/gaffe/ 0000755 0001750 0001751 00000000000 14124547074 013225 5 ustar rmb571 rmb571 gaffe-1.2.0/lib/gaffe/version.rb 0000644 0001750 0001751 00000000054 14124547074 015236 0 ustar rmb571 rmb571 module Gaffe VERSION = '1.2.0'.freeze end gaffe-1.2.0/lib/gaffe/errors_controller_resolver.rb 0000644 0001750 0001751 00000002140 14124547074 021247 0 ustar rmb571 rmb571 module Gaffe class ErrorsControllerResolver # Accessors attr_reader :controller # Constants BUILTIN_CONTROLLER = lambda do require 'gaffe/errors_controller' Gaffe::ErrorsController end def initialize(env) @env = env end def resolved_controller # Use the configured controller first controller = Gaffe.configuration.errors_controller # Parse the request if multiple controllers are configured controller = request_controller(controller) if controller.is_a?(Hash) # Fall back on the builtin errors controller controller ||= BUILTIN_CONTROLLER.call # Make sure we return a Class controller.respond_to?(:constantize) ? controller.constantize : controller end private def request_controller(controllers) matched_controllers = controllers.find do |pattern, _| relative_url = @env['REQUEST_URI'] absolute_url = @env['HTTP_HOST'] + relative_url [relative_url, absolute_url].any? { |url| (url =~ pattern).present? } end matched_controllers.try(:last) end end end gaffe-1.2.0/lib/gaffe/errors_controller.rb 0000644 0001750 0001751 00000000135 14124547074 017330 0 ustar rmb571 rmb571 module Gaffe class ErrorsController < ::ApplicationController include Errors end end gaffe-1.2.0/lib/gaffe/errors.rb 0000644 0001750 0001751 00000001426 14124547074 015071 0 ustar rmb571 rmb571 module Gaffe module Errors extend ActiveSupport::Concern included do before_action :fetch_exception, only: %w(show) before_action :append_view_paths layout 'error' end def show render "errors/#{@rescue_response}", status: @status_code rescue ActionView::MissingTemplate render 'errors/internal_server_error', status: 500 end protected def fetch_exception @exception = request.env['action_dispatch.exception'] @status_code = ActionDispatch::ExceptionWrapper.new(request.env, @exception).status_code @rescue_response = ActionDispatch::ExceptionWrapper.rescue_responses[@exception.class.name] end private def append_view_paths append_view_path Gaffe.root.join('app/views') end end end gaffe-1.2.0/lib/gaffe.rb 0000644 0001750 0001751 00000001632 14124547074 013554 0 ustar rmb571 rmb571 require 'gaffe/version' require 'ostruct' require 'pathname' require 'gaffe/errors' require 'gaffe/errors_controller_resolver' module Gaffe # Yield a block to populate @configuration def self.configure yield configuration end # Return the configuration settings def self.configuration @configuration ||= OpenStruct.new end # Configure Rails to use our code when encountering exceptions def self.enable! Rails.application.config.exceptions_app = lambda do |env| Gaffe.errors_controller_for_request(env).action(:show).call(env) end end # Return the right errors controller to use for the request that # triggered the error def self.errors_controller_for_request(env) resolver = ErrorsControllerResolver.new(env) resolver.resolved_controller end # Return the root path of the gem def self.root Pathname.new(File.expand_path('../../', __FILE__)) end end gaffe-1.2.0/LICENSE.md 0000644 0001750 0001751 00000002705 14124547074 013017 0 ustar rmb571 rmb571 Copyright (c) 2013-2016, Mirego All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the Mirego nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. gaffe-1.2.0/.gitignore 0000644 0001750 0001751 00000000232 14124547074 013374 0 ustar rmb571 rmb571 *.gem *.rbc .bundle .config .yardoc Gemfile.lock InstalledFiles _yardoc coverage doc/ lib/bundler/man pkg rdoc spec/reports test/tmp test/version_tmp tmp gaffe-1.2.0/gemfiles/ 0000755 0001750 0001751 00000000000 14124547074 013202 5 ustar rmb571 rmb571 gaffe-1.2.0/gemfiles/Gemfile.rails-4.0 0000644 0001750 0001751 00000000114 14124547074 016101 0 ustar rmb571 rmb571 source 'https://rubygems.org' gemspec path: '../' gem 'rails', '~> 4.0.0' gaffe-1.2.0/gemfiles/Gemfile.rails-5.0 0000644 0001750 0001751 00000000133 14124547074 016103 0 ustar rmb571 rmb571 source 'https://rubygems.org' gemspec path: '../' gem 'rails', '>= 5.0.0.beta2', '< 5.1' gaffe-1.2.0/gemfiles/Gemfile.rails-4.2 0000644 0001750 0001751 00000000114 14124547074 016103 0 ustar rmb571 rmb571 source 'https://rubygems.org' gemspec path: '../' gem 'rails', '~> 4.2.0' gaffe-1.2.0/Rakefile 0000644 0001750 0001751 00000000333 14124547074 013053 0 ustar rmb571 rmb571 require 'bundler' require 'rake' require 'bundler/gem_tasks' require 'rspec/core/rake_task' task default: :spec desc 'Run all specs' RSpec::Core::RakeTask.new(:spec) do |task| task.pattern = 'spec/**/*_spec.rb' end gaffe-1.2.0/Gemfile 0000644 0001750 0001751 00000000077 14124547074 012706 0 ustar rmb571 rmb571 source 'https://rubygems.org' gemspec gem 'rails', '~> 4.0.0' gaffe-1.2.0/README.md 0000644 0001750 0001751 00000015543 14124547074 012676 0 ustar rmb571 rmb571
Gaffe makes having customized error pages in Rails applications an easy thing.
It takes advantage of a feature present in Rails 3.2 (and 4.0+, obviously) called exceptions_app
.
This page does not exist.
``` ### Custom exceptions If your application is raising custom exceptions (through gems or your code) and you want to render specific views when it happens, you can map them to specific rescue responses. ```ruby # config/application.rb config.action_dispatch.rescue_responses.merge! 'CanCan::AccessDenied' => :forbidden config.action_dispatch.rescue_responses.merge! 'MyCustomException' => :not_acceptable ``` ### Rails development environment Rails prefers to render its own debug-friendly errors in the `development` environment, which is totally understandable. However, if you want to test Gaffe’s behavior in development you’ll have to edit the `config/environments/development.rb` file. ```ruby # Make Rails use `exceptions_app` in development config.consider_all_requests_local = false ``` ### Rails test environment You also have to configure Rails’ `test` environment so it lets Gaffe handle exceptions in request tests. You’ll have to edit the `config/environments/test.rb` file. ```ruby # Make Rails use `exceptions_app` in tests config.consider_all_requests_local = false # Render exceptions instead of raising them config.action_dispatch.show_exceptions = true ``` Unfortunately, controller tests (called *functional tests* in Rails) do not work with Gaffe, since they only test method calls in the controller class — they do not go through the entire Rack stack to simulate a real HTTP request. To test responses sent by Gaffe, you must use *request tests*. ## Contributors * [@remiprev](https://github.com/remiprev) * [@simonprev](https://github.com/simonprev) * [@jmuheim](https://github.com/jmuheim) ## License `Gaffe` is © 2013-2016 [Mirego](http://www.mirego.com) and may be freely distributed under the [New BSD license](http://opensource.org/licenses/BSD-3-Clause). See the [`LICENSE.md`](https://github.com/mirego/gaffe/blob/master/LICENSE.md) file. The mushroom cloud logo is based on [this lovely icon](http://thenounproject.com/noun/mushroom-cloud/#icon-No18596) by [Gokce Ozan](http://thenounproject.com/occultsearcher), from The Noun Project. Used under a [Creative Commons BY 3.0](http://creativecommons.org/licenses/by/3.0/) license. ## About Mirego [Mirego](http://mirego.com) is a team of passionate people who believe that work is a place where you can innovate and have fun. We're a team of [talented people](http://life.mirego.com) who imagine and build beautiful Web and mobile applications. We come together to share ideas and [change the world](http://mirego.org). We also [love open-source software](http://open.mirego.com) and we try to give back to the community as much as we can. gaffe-1.2.0/gaffe.gemspec 0000644 0001750 0001751 00000002121 14124547074 014020 0 ustar rmb571 rmb571 # coding: utf-8 lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'gaffe/version' Gem::Specification.new do |spec| spec.name = 'gaffe' spec.version = Gaffe::VERSION spec.authors = ['Rémi Prévost', 'Simon Prévost'] spec.email = ['rprevost@mirego.com', 'sprevost@mirego.com'] spec.description = 'Gaffe handles Rails error pages in a clean, simple way.' spec.summary = spec.description spec.homepage = 'https://github.com/mirego/gaffe' spec.license = "BSD 3-Clause" spec.files = `git ls-files`.split($/) spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ['lib'] spec.add_development_dependency 'bundler', '~> 1.3' spec.add_development_dependency 'rake' spec.add_development_dependency 'rspec', '~> 3.1.0' spec.add_development_dependency 'rubocop', '>= 0.21' spec.add_development_dependency 'phare' spec.add_dependency 'rails', '>= 4.0.0' end gaffe-1.2.0/app/ 0000755 0001750 0001751 00000000000 14124547074 012167 5 ustar rmb571 rmb571 gaffe-1.2.0/app/assets/ 0000755 0001750 0001751 00000000000 14124547074 013471 5 ustar rmb571 rmb571 gaffe-1.2.0/app/assets/stylesheets/ 0000755 0001750 0001751 00000000000 14124547074 016045 5 ustar rmb571 rmb571 gaffe-1.2.0/app/assets/stylesheets/errors.css 0000644 0001750 0001751 00000002166 14124547074 020100 0 ustar rmb571 rmb571 html { font-size: 62.5%; } * { margin: 0; padding: 0; font-size: 100%; -moz-box-sizing: border-box; box-sizing: border-box; } body { padding: 60px; background: #fafafa; font-size: 150%; font-family: Helvetica, Arial, sans-serif; font-weight: 300; line-height: 1.5; } #wrap { width: 100%; max-width: 700px; margin: 0 auto; padding: 30px; background: #fff; box-shadow: 0 0 20px rgba(0, 0, 0, 0.2); border-radius: 3px; border-top: 3px solid #b00f08; } hr { display: none; } p { margin: 0 0 15px; } a { color: #731217; } a:hover { color: #b00f08; } h1 { margin: 0 0 15px; font-size: 240%; font-weight: 300; color: #731217; } .content { padding: 15px; margin: 15px 0; background: #eee; border: 1px solid rgba(0, 0, 0, 0.1); font-weight: bold; color: #666; } pre { overflow: auto; padding: 15px; background: #fafafa; border: 1px solid rgba(0, 0, 0, 0.1); line-height: 1.8; color: rgba(0, 0, 0, 0.8); } pre.exception { background-color: #ffeded; } pre em { font-style: normal; color: rgba(0, 0, 0, 0.5); border-bottom: 1px dotted; cursor: help; } gaffe-1.2.0/app/views/ 0000755 0001750 0001751 00000000000 14124547074 013324 5 ustar rmb571 rmb571 gaffe-1.2.0/app/views/layouts/ 0000755 0001750 0001751 00000000000 14124547074 015024 5 ustar rmb571 rmb571 gaffe-1.2.0/app/views/layouts/error.html.erb 0000644 0001750 0001751 00000002272 14124547074 017615 0 ustar rmb571 rmb571This is an error page brought to you by Gaffe.
Original exception (only displayed in development and test environment):
<%= @exception.inspect %>
<% end %>
You can overwrite this page by creating these files:
<% handlers = ActionView::Template::Handlers.extensions.map(&:to_s).join(', ') %><%= Rails.root.join('app', 'views', 'layouts', "error.html.handler").to_s.html_safe %>
<%= Rails.root.join('app', 'views', 'errors', "#{@rescue_response.to_s}.html.handler").to_s.html_safe %>