I think you meant the show, since the index is valid for lists / collections. And you should get .first from where, otherwise you just have a relationship, right? Then use .first! to increase the error, because the Rails Rack middleware in Rails 4 public_exceptions will be processed mainly, for example,
def show
You can also use @bar = Bar.find(params[:id]) , but this is deprecated and will be removed in Rails 4.1, after which you will need to add the gem 'activerecord-deprecated_finders' to your Gemfile to use.
For the index, you probably need @bars = Bar.all . If for some reason you want to filter and do not want to have visibility, etc., you can use @bars = Bar.where(...).to_a or similar.
Rails 4: Basic Rack Exception Handling Automatic
While the request is triggering an error, Rails 4 should be able to return part of the error message for any supported format where to_(format) can be caused by a hash (e.g. json, xml, etc.).
To find out why, look at the Rails Rack public_exceptions middleware.
If it is html, it will try to read in the linked file from the shared directory in Rails for the status code (e.g. 500.html for server / HTTP error 500).
If this is some other format, it will try to make to_(the format) in the hash: { :status => status, :error => exception.message } to_(the format) { :status => status, :error => exception.message } . To find out how it works, go to the Rails console:
$ rails c ... 1.9.3p392 :001 > {status: 500, error: "herro shraggy!"}.to_xml => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<hash>\n <status type=\"integer\">500</status>\n <error>herro shraggy!</error>\n</hash>\n" 1.9.3p392 :002 > {status: 500, error: "herro shraggy!"}.to_json => "{\"status\":500,\"error\":\"herro shraggy!\"}"
In the middleware, you will see the X-Cascade header in the code and in various places related to handling Rails exceptions in Rack. Per this answer , the X-Cascade header is set to pass to tell Rack to try other routes to find the resource.
Rails 3.2.x: can handle rack exceptions
In Rails 3.2.x, this code is for to_(format) for the response body, etc. not located in public_exceptions.rb . It only processes the html format.
Perhaps you could try replacing the old middleware with a newer version using a patch.
If you prefer Rack to handle your error in a more specific way without a patch, see No. 3 in a post by Josรฉ Valim, " My five favorites are" hidden "features in Rails 3.2 ."
In this and as another answer is also mentioned, you can use config.exceptions_app = self.routes . Then, using routes that point to the user controller, you can handle errors from any controller, like any other request. Note the bit about config.consider_all_requests_local = false in config/environments/development.rb .
You do not need to use routes to use exceptions_app . Although this can be a little intimidating, it's just proc / lambda that takes a hash and returns an array whose format is [http_status_code_number, {headers hash...}, ['the response body']] . For example, you should be able to do this in your Rails 3.2.x configuration to make it handle errors like Rails 4.0 (this last public_exceptions middleware is minimized):
config.exceptions_app = lambda do |env| exception = env["action_dispatch.exception"] status = env["PATH_INFO"][1..-1] request = ActionDispatch::Request.new(env) content_type = request.formats.first body = { :status => status, :error => exception.message } format = content_type && "to_#{content_type.to_sym}" if format && body.respond_to?(format) formatted_body = body.public_send(format) [status, {'Content-Type' => "#{content_type}; charset=#{ActionDispatch::Response.default_charset}", 'Content-Length' => body.bytesize.to_s}, [formatted_body]] else found = false path = "#{public_path}/#{status}.#{I18n.locale}.html" if I18n.locale path = "#{public_path}/#{status}.html" unless path && (found = File.exist?(path)) if found || File.exist?(path) [status, {'Content-Type' => "text/html; charset=#{ActionDispatch::Response.default_charset}", 'Content-Length' => body.bytesize.to_s}, [File.read(path)]] else [404, { "X-Cascade" => "pass" }, []] end end end
Note. For any problem with this processing, the fail-safe implementation is in ActionDispatch::ShowExceptions here .
Rails 3 and 4: Handling Some Exceptions in the Rails Controller
If you prefer rendering errors in the controller itself, you can do:
def show respond_with @bar = Bar.where(:foo_id => params[:id].to_s).first! rescue ActiveRecord::RecordNotFound => e respond_to do |format| format.json => { :error => e.message }, :status => 404 end end
But you do not need to make mistakes. You can also do:
def show @bar = Bar.where(:foo_id => params[:id].to_s).first if @bar respond_with @bar else respond_to do |format| format.json => { :error => "Couldn't find Bar with id=#{params[:id]}" }, :status => 404 end end end
You can also use rescue_from , for example. in your controller or ApplicationController etc:
rescue_from ActiveRecord::RecordNotFound, with: :not_found def not_found(exception) respond_to do |format| format.json => { :error => e.message }, :status => 404 end end
or
rescue_from ActiveRecord::RecordNotFound do |exception| respond_to do |format| format.json => { :error => e.message }, :status => 404 end end
Although some common errors can be handled in the controller, if you made a mistake regarding missing routes, etc. formatted in json, etc., they need to be handled in the Rack middleware.