goalie 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Helder Ribeiro
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
File without changes
data/Rakefile ADDED
@@ -0,0 +1,23 @@
1
+ require File.dirname(__FILE__) + "/lib/goalie/version.rb"
2
+
3
+ begin
4
+ require 'jeweler'
5
+
6
+ Jeweler::Tasks.new do |gemspec|
7
+ gemspec.version = Goalie::VERSION
8
+ gemspec.name = "goalie"
9
+ gemspec.summary = "Custom error pages for Rails"
10
+
11
+ gemspec.description = "Middleware to catch exceptions and " <<
12
+ "Rails Engine to render them. Error-handling views and " <<
13
+ "controllers can be easily overriden."
14
+
15
+ gemspec.email = "helder@gmail.com"
16
+ gemspec.homepage = "http://github.com/obvio171/goalie"
17
+ gemspec.authors = ["Helder Ribeiro"]
18
+ end
19
+
20
+ Jeweler::GemcutterTasks.new
21
+ rescue LoadError
22
+ puts "Jeweler not available. Install it with: gem install jeweler"
23
+ end
@@ -0,0 +1,30 @@
1
+ class LocalErrorsController < ActionController::Base
2
+ self.append_view_path "#{File.dirname(__FILE__)}/../views"
3
+
4
+ before_filter :set_error_instance_variables
5
+
6
+ def routing_error
7
+ end
8
+
9
+ def template_error
10
+ end
11
+
12
+ def missing_template
13
+ end
14
+
15
+ def unknown_action
16
+ end
17
+
18
+ def diagnostics
19
+ end
20
+
21
+ private
22
+ def set_error_instance_variables
23
+ error_params = env['goalie.error_params']
24
+
25
+ error_params.each do |name, value|
26
+ instance_variable_set("@#{name}", value)
27
+ end
28
+ end
29
+
30
+ end
@@ -0,0 +1,25 @@
1
+ class PublicErrorsController < ActionController::Base
2
+ self.append_view_path "#{File.dirname(__FILE__)}/../views"
3
+
4
+ def internal_server_error
5
+ end
6
+
7
+ def not_found
8
+ end
9
+
10
+ def unprocessable_entity
11
+ end
12
+
13
+ def conflict
14
+ render :action => 'internal_server_error'
15
+ end
16
+
17
+ def method_not_allowed
18
+ render :action => 'internal_server_error'
19
+ end
20
+
21
+ def not_implemented
22
+ render :action => 'internal_server_error'
23
+ end
24
+
25
+ end
@@ -0,0 +1,29 @@
1
+ <html xmlns="http://www.w3.org/1999/xhtml">
2
+ <head>
3
+ <title>Action Controller: Exception caught</title>
4
+ <style>
5
+ body { background-color: #fff; color: #333; }
6
+
7
+ body, p, ol, ul, td {
8
+ font-family: verdana, arial, helvetica, sans-serif;
9
+ font-size: 13px;
10
+ line-height: 18px;
11
+ }
12
+
13
+ pre {
14
+ background-color: #eee;
15
+ padding: 10px;
16
+ font-size: 11px;
17
+ }
18
+
19
+ a { color: #000; }
20
+ a:visited { color: #666; }
21
+ a:hover { color: #fff; background-color:#000; }
22
+ </style>
23
+ </head>
24
+ <body>
25
+
26
+ <%= yield %>
27
+
28
+ </body>
29
+ </html>
@@ -0,0 +1,31 @@
1
+ <% unless @exception.blamed_files.blank? %>
2
+ <% if (hide = @exception.blamed_files.length > 8) %>
3
+ <a href="#" onclick="document.getElementById('blame_trace').style.display='block'; return false;">Show blamed files</a>
4
+ <% end %>
5
+ <pre id="blame_trace" <%='style="display:none"' if hide %>><code><%=h @exception.describe_blame %></code></pre>
6
+ <% end %>
7
+
8
+ <%
9
+ clean_params = @request.filtered_parameters.clone
10
+ clean_params.delete("action")
11
+ clean_params.delete("controller")
12
+
13
+ request_dump = clean_params.empty? ? 'None' : clean_params.inspect.gsub(',', ",\n")
14
+
15
+ def debug_hash(hash)
16
+ hash.sort_by { |k, v| k.to_s }.map { |k, v| "#{k}: #{v.inspect rescue $!.message}" }.join("\n")
17
+ end
18
+ %>
19
+
20
+ <h2 style="margin-top: 30px">Request</h2>
21
+ <p><b>Parameters</b>: <pre><%=h request_dump %></pre></p>
22
+
23
+ <p><a href="#" onclick="document.getElementById('session_dump').style.display='block'; return false;">Show session dump</a></p>
24
+ <div id="session_dump" style="display:none"><pre><%= debug_hash @request.session %></pre></div>
25
+
26
+ <p><a href="#" onclick="document.getElementById('env_dump').style.display='block'; return false;">Show env dump</a></p>
27
+ <div id="env_dump" style="display:none"><pre><%= debug_hash @request.env %></pre></div>
28
+
29
+
30
+ <h2 style="margin-top: 30px">Response</h2>
31
+ <p><b>Headers</b>: <pre><%=h @response ? @response.headers.inspect.gsub(',', ",\n") : 'None' %></pre></p>
@@ -0,0 +1,26 @@
1
+ <%
2
+ traces = [
3
+ ["Application Trace", @application_trace],
4
+ ["Framework Trace", @framework_trace],
5
+ ["Full Trace", @full_trace]
6
+ ]
7
+ names = traces.collect {|name, trace| name}
8
+ %>
9
+
10
+ <p><code>Rails.root: <%= defined?(Rails) && Rails.respond_to?(:root) ? Rails.root : "unset" %></code></p>
11
+
12
+ <div id="traces">
13
+ <% names.each do |name| %>
14
+ <%
15
+ show = "document.getElementById('#{name.gsub /\s/, '-'}').style.display='block';"
16
+ hide = (names - [name]).collect {|hide_name| "document.getElementById('#{hide_name.gsub /\s/, '-'}').style.display='none';"}
17
+ %>
18
+ <a href="#" onclick="<%= hide.join %><%= show %>; return false;"><%= name %></a> <%= '|' unless names.last == name %>
19
+ <% end %>
20
+
21
+ <% traces.each do |name, trace| %>
22
+ <div id="<%= name.gsub /\s/, '-' %>" style="display: <%= name == "Application Trace" ? 'block' : 'none' %>;">
23
+ <pre><code><%=h trace.join "\n" %></code></pre>
24
+ </div>
25
+ <% end %>
26
+ </div>
@@ -0,0 +1,10 @@
1
+ <h1>
2
+ <%=h @exception.class.to_s %>
3
+ <% if @request.parameters['controller'] %>
4
+ in <%=h @request.parameters['controller'].humanize %>Controller<% if @request.parameters['action'] %>#<%=h @request.parameters['action'] %><% end %>
5
+ <% end %>
6
+ </h1>
7
+ <pre><%=h @exception.message %></pre>
8
+
9
+ <%= render :partial => 'trace' %>
10
+ <%= render :partial => 'request_and_response.erb' %>
@@ -0,0 +1,2 @@
1
+ <h1>Template is missing</h1>
2
+ <p><%=h @exception.message %></p>
@@ -0,0 +1,10 @@
1
+ <h1>Routing Error</h1>
2
+ <p><pre><%=h @exception.message %></pre></p>
3
+ <% unless @exception.failures.empty? %><p>
4
+ <h2>Failure reasons:</h2>
5
+ <ol>
6
+ <% @exception.failures.each do |route, reason| %>
7
+ <li><code><%=h route.inspect.gsub('\\', '') %></code> failed because <%=h reason.downcase %></li>
8
+ <% end %>
9
+ </ol>
10
+ </p><% end %>
@@ -0,0 +1,21 @@
1
+ <h1>
2
+ <%=h @exception.original_exception.class.to_s %> in
3
+ <%=h @request.parameters["controller"].capitalize if @request.parameters["controller"]%>#<%=h @request.parameters["action"] %>
4
+ </h1>
5
+
6
+ <p>
7
+ Showing <i><%=h @exception.file_name %></i> where line <b>#<%=h @exception.line_number %></b> raised:
8
+ <pre><code><%=h @exception.message %></code></pre>
9
+ </p>
10
+
11
+ <p>Extracted source (around line <b>#<%=h @exception.line_number %></b>):
12
+ <pre><code><%=h @exception.source_extract %></code></pre></p>
13
+
14
+ <p><%=h @exception.sub_template_message %></p>
15
+
16
+ <% @real_exception = @exception
17
+ @exception = @exception.original_exception || @exception %>
18
+ <%= render :partial => 'trace.erb' %>
19
+ <% @exception = @real_exception %>
20
+
21
+ <%= render :partial => 'request_and_response' %>
@@ -0,0 +1,2 @@
1
+ <h1>Unknown action</h1>
2
+ <p><%=h @exception.message %></p>
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>We're sorry, but something went wrong (500)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/500.html -->
21
+ <div class="dialog">
22
+ <h1>We're sorry, but something went wrong.</h1>
23
+ <p>We've been notified about this issue and we'll take a look at it shortly.</p>
24
+ </div>
25
+ </body>
26
+ </html>
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The page you were looking for doesn't exist (404)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/404.html -->
21
+ <div class="dialog">
22
+ <h1>The page you were looking for doesn't exist.</h1>
23
+ <p>You may have mistyped the address or the page may have moved.</p>
24
+ </div>
25
+ </body>
26
+ </html>
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The change you wanted was rejected (422)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/422.html -->
21
+ <div class="dialog">
22
+ <h1>The change you wanted was rejected.</h1>
23
+ <p>Maybe you tried to change something you didn't have access to.</p>
24
+ </div>
25
+ </body>
26
+ </html>
@@ -0,0 +1,10 @@
1
+ module Goalie
2
+ class Engine < Rails::Engine
3
+
4
+ initializer "goalie.add_middleware" do |app|
5
+ app.middleware.delete 'ShowExceptions'
6
+ app.middleware.use Goalie::CustomErrorPages
7
+ end
8
+
9
+ end
10
+ end
@@ -0,0 +1,3 @@
1
+ module Goalie
2
+ VERSION = "0.0.0".freeze
3
+ end
data/lib/goalie.rb ADDED
@@ -0,0 +1,169 @@
1
+ require 'active_support/core_ext/exception'
2
+ require 'active_support/notifications'
3
+ require 'action_dispatch/http/request'
4
+
5
+ module Goalie
6
+ # This middleware rescues any exception returned by the application
7
+ # and renders nice exception pages.
8
+ class CustomErrorPages
9
+ LOCALHOST = [/^127\.0\.0\.\d{1,3}$/, "::1", /^0:0:0:0:0:0:0:1(%.*)?$/].freeze
10
+
11
+ cattr_accessor :rescue_responses
12
+ @@rescue_responses = Hash.new(:internal_server_error)
13
+ @@rescue_responses.update({
14
+ 'ActionController::RoutingError' => :not_found,
15
+ 'AbstractController::ActionNotFound' => :not_found,
16
+ 'ActiveRecord::RecordNotFound' => :not_found,
17
+ 'ActiveRecord::StaleObjectError' => :conflict,
18
+ 'ActiveRecord::RecordInvalid' => :unprocessable_entity,
19
+ 'ActiveRecord::RecordNotSaved' => :unprocessable_entity,
20
+ 'ActionController::MethodNotAllowed' => :method_not_allowed,
21
+ 'ActionController::NotImplemented' => :not_implemented,
22
+ 'ActionController::InvalidAuthenticityToken' => :unprocessable_entity
23
+ })
24
+
25
+ FAILSAFE_RESPONSE = [
26
+ 500,
27
+ {'Content-Type' => 'text/html'},
28
+ ["<html><body><h1>500 Internal Server Error</h1>" <<
29
+ "If you are the administrator of this website, then please read " <<
30
+ "this web application's log file and/or the web server's log " <<
31
+ "file to find out what went wrong.</body></html>"]
32
+ ]
33
+
34
+ def initialize(app, consider_all_requests_local = false)
35
+ @app = app
36
+ @consider_all_requests_local = consider_all_requests_local
37
+ end
38
+
39
+ def call(env)
40
+ status, headers, body = @app.call(env)
41
+
42
+ # Only this middleware cares about RoutingError. So, let's just
43
+ # raise it here.
44
+ # TODO: refactor this middleware to handle the X-Cascade scenario
45
+ # without having to raise an exception.
46
+ if headers['X-Cascade'] == 'pass'
47
+ raise(ActionController::RoutingError,
48
+ "No route matches #{env['PATH_INFO'].inspect}")
49
+ end
50
+
51
+ [status, headers, body]
52
+ rescue Exception => exception
53
+ render_exception(env, exception)
54
+ end
55
+
56
+ private
57
+ def render_exception(env, exception)
58
+ log_error(exception)
59
+
60
+ request = ActionDispatch::Request.new(env)
61
+ if @consider_all_requests_local || local_request?(request)
62
+ rescue_action_locally(request, exception)
63
+ else
64
+ rescue_action_in_public(request, exception)
65
+ end
66
+ rescue Exception => failsafe_error
67
+ $stderr.puts("Error during failsafe response: #{failsafe_error}\n" <<
68
+ "#{failsafe_error.backtrace * "\n "}")
69
+ FAILSAFE_RESPONSE
70
+ end
71
+
72
+ # Render detailed diagnostics for unhandled exceptions rescued from
73
+ # a controller action.
74
+ def rescue_action_locally(request, exception)
75
+ # TODO this should probably move to the controller, that is, have
76
+ # http error codes map directly to controller actions, then let
77
+ # controller handle different exception classes however it wants
78
+ rescue_actions = Hash.new('diagnostics')
79
+ rescue_actions.update({
80
+ 'ActionView::MissingTemplate' => 'missing_template',
81
+ 'ActionController::RoutingError' => 'routing_error',
82
+ 'AbstractController::ActionNotFound' => 'unknown_action',
83
+ 'ActionView::Template::Error' => 'template_error'
84
+ })
85
+
86
+ error_params = {
87
+ :request => request, :exception => exception,
88
+ :application_trace => application_trace(exception),
89
+ :framework_trace => framework_trace(exception),
90
+ :full_trace => full_trace(exception)
91
+ }
92
+ request.env['goalie.error_params'] = error_params
93
+ action = rescue_actions[exception.class.name]
94
+ response = LocalErrorsController.action(action).call(request.env).last
95
+ render(status_code(exception), response.body)
96
+ end
97
+
98
+ def rescue_action_in_public(request, exception)
99
+ error_params = {
100
+ :request => request, :exception => exception,
101
+ :application_trace => application_trace(exception),
102
+ :framework_trace => framework_trace(exception),
103
+ :full_trace => full_trace(exception)
104
+ }
105
+ request.env['custom_error_pages.error_params'] = error_params
106
+ action = @@rescue_responses[exception.class.name]
107
+ response = PublicErrorsController.action(action).call(request.env).last
108
+ render(status_code(exception), response.body)
109
+ end
110
+
111
+ # True if the request came from localhost, 127.0.0.1.
112
+ def local_request?(request)
113
+ LOCALHOST.any? { |local_ip|
114
+ local_ip === request.remote_addr && local_ip === request.remote_ip
115
+ }
116
+ end
117
+
118
+ def status_code(exception)
119
+ Rack::Utils.status_code(@@rescue_responses[exception.class.name])
120
+ end
121
+
122
+ def render(status, body)
123
+ [status,
124
+ {'Content-Type' => 'text/html', 'Content-Length' => body.bytesize.to_s},
125
+ [body]]
126
+ end
127
+
128
+ def public_path
129
+ defined?(Rails.public_path) ? Rails.public_path : 'public_path'
130
+ end
131
+
132
+ def log_error(exception)
133
+ return unless logger
134
+
135
+ ActiveSupport::Deprecation.silence do
136
+ message = "\n#{exception.class} (#{exception.message}):\n"
137
+
138
+ if exception.respond_to?(:annoted_source_code)
139
+ message << exception.annoted_source_code
140
+ end
141
+
142
+ message << " " << application_trace(exception).join("\n ")
143
+ logger.fatal("#{message}\n\n")
144
+ end
145
+ end
146
+
147
+ def application_trace(exception)
148
+ clean_backtrace(exception, :silent)
149
+ end
150
+
151
+ def framework_trace(exception)
152
+ clean_backtrace(exception, :noise)
153
+ end
154
+
155
+ def full_trace(exception)
156
+ clean_backtrace(exception, :all)
157
+ end
158
+
159
+ def clean_backtrace(exception, *args)
160
+ defined?(Rails) && Rails.respond_to?(:backtrace_cleaner) ?
161
+ Rails.backtrace_cleaner.clean(exception.backtrace, *args) :
162
+ exception.backtrace
163
+ end
164
+
165
+ def logger
166
+ defined?(Rails.logger) ? Rails.logger : Logger.new($stderr)
167
+ end
168
+ end
169
+ end
@@ -0,0 +1,118 @@
1
+ require 'abstract_unit'
2
+
3
+ module ActionDispatch
4
+ class ShowExceptions
5
+ private
6
+ def public_path
7
+ "#{FIXTURE_LOAD_PATH}/public"
8
+ end
9
+
10
+ # Silence logger
11
+ def logger
12
+ nil
13
+ end
14
+ end
15
+ end
16
+
17
+ class ShowExceptionsTest < ActionController::IntegrationTest
18
+ Boomer = lambda do |env|
19
+ req = ActionDispatch::Request.new(env)
20
+ case req.path
21
+ when "/not_found"
22
+ raise ActionController::UnknownAction
23
+ when "/method_not_allowed"
24
+ raise ActionController::MethodNotAllowed
25
+ when "/not_implemented"
26
+ raise ActionController::NotImplemented
27
+ when "/unprocessable_entity"
28
+ raise ActionController::InvalidAuthenticityToken
29
+ else
30
+ raise "puke!"
31
+ end
32
+ end
33
+
34
+ ProductionApp = ActionDispatch::ShowExceptions.new(Boomer, false)
35
+ DevelopmentApp = ActionDispatch::ShowExceptions.new(Boomer, true)
36
+
37
+ test "rescue in public from a remote ip" do
38
+ @app = ProductionApp
39
+ self.remote_addr = '208.77.188.166'
40
+
41
+ get "/", {}, {'action_dispatch.show_exceptions' => true}
42
+ assert_response 500
43
+ assert_equal "500 error fixture\n", body
44
+
45
+ get "/not_found", {}, {'action_dispatch.show_exceptions' => true}
46
+ assert_response 404
47
+ assert_equal "404 error fixture\n", body
48
+
49
+ get "/method_not_allowed", {}, {'action_dispatch.show_exceptions' => true}
50
+ assert_response 405
51
+ assert_equal "", body
52
+ end
53
+
54
+ test "rescue locally from a local request" do
55
+ @app = ProductionApp
56
+ ['127.0.0.1', '127.0.0.127', '::1', '0:0:0:0:0:0:0:1', '0:0:0:0:0:0:0:1%0'].each do |ip_address|
57
+ self.remote_addr = ip_address
58
+
59
+ get "/", {}, {'action_dispatch.show_exceptions' => true}
60
+ assert_response 500
61
+ assert_match /puke/, body
62
+
63
+ get "/not_found", {}, {'action_dispatch.show_exceptions' => true}
64
+ assert_response 404
65
+ assert_match /#{ActionController::UnknownAction.name}/, body
66
+
67
+ get "/method_not_allowed", {}, {'action_dispatch.show_exceptions' => true}
68
+ assert_response 405
69
+ assert_match /ActionController::MethodNotAllowed/, body
70
+ end
71
+ end
72
+
73
+ test "localize public rescue message" do
74
+ # Change locale
75
+ old_locale, I18n.locale = I18n.locale, :da
76
+
77
+ begin
78
+ @app = ProductionApp
79
+ self.remote_addr = '208.77.188.166'
80
+
81
+ get "/", {}, {'action_dispatch.show_exceptions' => true}
82
+ assert_response 500
83
+ assert_equal "500 localized error fixture\n", body
84
+
85
+ get "/not_found", {}, {'action_dispatch.show_exceptions' => true}
86
+ assert_response 404
87
+ assert_equal "404 error fixture\n", body
88
+ ensure
89
+ I18n.locale = old_locale
90
+ end
91
+ end
92
+
93
+ test "always rescue locally in development mode" do
94
+ @app = DevelopmentApp
95
+ self.remote_addr = '208.77.188.166'
96
+
97
+ get "/", {}, {'action_dispatch.show_exceptions' => true}
98
+ assert_response 500
99
+ assert_match /puke/, body
100
+
101
+ get "/not_found", {}, {'action_dispatch.show_exceptions' => true}
102
+ assert_response 404
103
+ assert_match /#{ActionController::UnknownAction.name}/, body
104
+
105
+ get "/method_not_allowed", {}, {'action_dispatch.show_exceptions' => true}
106
+ assert_response 405
107
+ assert_match /ActionController::MethodNotAllowed/, body
108
+ end
109
+
110
+ test "does not show filtered parameters" do
111
+ @app = DevelopmentApp
112
+
113
+ get "/", {"foo"=>"bar"}, {'action_dispatch.show_exceptions' => true,
114
+ 'action_dispatch.parameter_filter' => [:foo]}
115
+ assert_response 500
116
+ assert_match "&quot;foo&quot;=&gt;&quot;[FILTERED]&quot;", body
117
+ end
118
+ end
data/todo.org ADDED
@@ -0,0 +1,8 @@
1
+
2
+ * Make views overridable from inside app
3
+ * Make controllers overridable from inside app
4
+ * Give proper credit to author of Rails' ShowExceptions
5
+ * Give proper credit ao author of Rails' exception_notification
6
+ * Give proper credit to Rails' default error pages that were copied
7
+ * Turn into a gem
8
+ * Create Railtie
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: goalie
3
+ version: !ruby/object:Gem::Version
4
+ hash: 31
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 0
10
+ version: 0.0.0
11
+ platform: ruby
12
+ authors:
13
+ - Helder Ribeiro
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-08-09 00:00:00 -03:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: Middleware to catch exceptions and Rails Engine to render them. Error-handling views and controllers can be easily overriden.
23
+ email: helder@gmail.com
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files:
29
+ - README
30
+ files:
31
+ - MIT-LICENSE
32
+ - README
33
+ - Rakefile
34
+ - app/controllers/local_errors_controller.rb
35
+ - app/controllers/public_errors_controller.rb
36
+ - app/views/layouts/local_errors.html.erb
37
+ - app/views/local_errors/_request_and_response.html.erb
38
+ - app/views/local_errors/_trace.html.erb
39
+ - app/views/local_errors/diagnostics.html.erb
40
+ - app/views/local_errors/missing_template.html.erb
41
+ - app/views/local_errors/routing_error.html.erb
42
+ - app/views/local_errors/template_error.html.erb
43
+ - app/views/local_errors/unknown_action.html.erb
44
+ - app/views/public_errors/internal_server_error.html
45
+ - app/views/public_errors/not_found.html
46
+ - app/views/public_errors/unprocessable_entity.html
47
+ - lib/goalie.rb
48
+ - lib/goalie/rails.rb
49
+ - lib/goalie/version.rb
50
+ - test/custom_error_pages_test.rb
51
+ - todo.org
52
+ has_rdoc: true
53
+ homepage: http://github.com/obvio171/goalie
54
+ licenses: []
55
+
56
+ post_install_message:
57
+ rdoc_options:
58
+ - --charset=UTF-8
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ hash: 3
67
+ segments:
68
+ - 0
69
+ version: "0"
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ hash: 3
76
+ segments:
77
+ - 0
78
+ version: "0"
79
+ requirements: []
80
+
81
+ rubyforge_project:
82
+ rubygems_version: 1.3.7
83
+ signing_key:
84
+ specification_version: 3
85
+ summary: Custom error pages for Rails
86
+ test_files:
87
+ - test/custom_error_pages_test.rb