Rails 3 - development errors in production mode
Im using Rails, Passenger (both are 3.0.5) and Nginx on my production server. As I heard, Rails should show public/404.html
or public/500.html
instead of development errors like ActiveRecord::RecordNotFound
or Unknown action
but that doesn't happen. I've tried to delete config.ru file and set rack_env or rails_env in nginx.conf but nothing helped.
Here is my nginx.conf:
worker_processes 1;
events {
worker_connections 1024;
}
http {
passenger_root /home/makk/.rvm/gems/ruby-1.9.2-p0/gems/passenger-3.0.5;
passenger_ruby /home/makk/.rvm/bin/passenger_ruby;
#passenger_ruby /home/makk/.rvm/wrappers/ruby-1.9.2-p0/ruby;
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root /home/makk/projects/1server/deploy/current/public;
index index.html index.htm;
passenger_enabled on;
rack_env production;
recursive_error_pages on;
if (-f /home/makk/projects/1server/maintenance.html) {
return 503;
}
error_page 404 /404.html;
error_page 500 502 504 /500.html;
error_page 503 @503;
}
location @503 {
error_page 405 = /maintenance.html;
# Serve static assets if found.
if (-f $request_filename) {
break;
}
rewrite ^(.*)$ /maintenance.html break;
}
location ~ ^(\/phpmyadmin\/)(.*)$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_split_path_info ^(\/phpmyadmin\/)(.*)$;
fastcgi_param SCRIPT_FILENAME /usr/share/phpmyadmin/$fastcgi_path_info;
include fastcgi_params;
}
}
}
It seems that this question duplicates this one but there are no working suggestions.
UPD: I have both development and production apps on same PC. In production Rails ignores config.consider_al开发者_如何学编程l_requests_local = false
(in /config/environments/production.rb) due to local_request?
method. So one of possible solutions is listed below (taken from here):
# config/initializers/local_request_override.rb
module CustomRescue
def local_request?
return false if Rails.env.production? || Rails.env.staging?
super
end
end
ActionController::Base.class_eval do
include CustomRescue
end
Or for Rails 3:
class ActionDispatch::Request
def local?
false
end
end
To get this working in Rails 3 you'll have to do the following:
First, create your 404 and 500 error pages. I put mine in app/views/errors/404.html.erb
and app/views/errors/500.html.erb
.
Second, add the following to application_controller.rb:
unless Rails.application.config.consider_all_requests_local
rescue_from Exception, :with => :render_error
rescue_from ActiveRecord::RecordNotFound, :with => :render_not_found
rescue_from AbstractController::ActionNotFound, :with => :render_not_found
rescue_from ActionController::RoutingError, :with => :render_not_found
rescue_from ActionController::UnknownController, :with => :render_not_found
rescue_from ActionController::UnknownAction, :with => :render_not_found
end
def render_error exception
Rails.logger.error(exception)
render :template => "/errors/500.haml", :status => 500
end
def render_not_found exception
Rails.logger.error(exception)
render :template => "/errors/404.haml", :status => 404
end
Finally, make your production.rb not consider all requests local:
config.consider_all_requests_local = false
P.S: Keep in mind that when a complete routing error happens - i.e when there is absolutely no route match, not just an ActiveRecord NotFound error, the public/404.html will get displayed, so it's good to have that in place. I usually just re-direct it to my errors_controller, which ensures that any 404 errors not caught by the latter mentioned exceptions are still properly redirected to ErrorsController.
<script type="text/javascript">
<!--
window.location = "<%= request.host_with_port %>/errors/404"
//-->
</script>
To get errors only in certain controllers
class AdminController < ApplicationController
rescue_from Exception, :with => :render_simple_error if Rails.env.production?
def render_simple_error(e)
render :text => "#{e.message} -- #{e.class}<br/>#{e.backtrace.join("<br/>")}"
end
end
Move your root
declaration up to the "server" block so the server can use the Rails app defined error handling pages when it receives a 5XX, 4XX error.
Or add error_page
directives to the location block where passenger is being used so the error handlers can resolve the public/5xx.html
in the Rails app public directory when needed.
If your app is not serving up the page and nginx has no visibility to the static page then it can't serve the page you want.
On apache passenger I used the apache configuration option
PassengerFriendlyErrorPages
off.
精彩评论