Handling Routing Exception in Ruby on Rails - ruby-on-rails

I am studying ruby on rails now and got stuck in exception handling. I just try to handle routing exceptions. I followed the following article
https://coderwall.com/p/whjmra/handling-exceptions-in-your-rails-application
In the code, id din't got the method 'render_exception(404, "Routing Error", exception)' . Please help me for this. I need to show my 404 page which is in the errors\404 in the view folder

When you handle exception try:
render :file => 'errors/404.html', :status => :not_found, :layout => false

Related

How can I handle generic errors with a JSON response in a hybrid (JSON API + HTML) Rails 5 app?

I spent one day trying several approaches, but still haven't quite got there so decided to ask now...
I have a Rails 5 app which is mainly a JSON API (using the actual JSON API specs), but also a "normal" Rails app with transactional emails and account related pages (reset password, etc).
What I'd like to achieve is that Rails always returns a JSON response with some meaningful error response to all API calls, rather than the default HTML error page or a header only 400 error.
The main cases I'm trying to handle are JSON parsing issues and Ruby exceptions (500 errors).
I tried:
using rescue_from on the ActionController level – seems the framework handles these exceptions before they would reach the controller
Handling them on the Rack level with a middleware – this worked in test but not in dev despite setting consider_all_requests_local to false in both
Registering a new Mime-type and a parser as JSON API Resources gem does it – looked promising, but the parser code is never hit
I'm really at my wit's end, something which sounded so simple ended up being deceptively complicated with me trying to hunt down where are these exceptions get handled in the framework without much success...
Well I managed to work it out in the end, so thought I should share what worked.
What I missed before is that I had to fiddle a bit with MIME types so that Rails would understand and properly use JSON API:
config/initializers/mime_types.rb
JSON_API_MIME_TYPES = %w[
application/vnd.api+json
text/x-json
application/json
].freeze
Mime::Type.unregister :json
Mime::Type.register 'application/json', :json, JSON_API_MIME_TYPES
Mime::Type.register_alias 'application/json', :json, %i[json_api jsonapi]
After this I could finally handle 500 errors in the base controller:
rescue_from StandardError,
with: :render_standard_error
def render_standard_error
render json: {
status: 500,
error: 'Unhandled error',
message: 'An unexpected error occurred.'
}, status: :internal_server_error
end
Then for handling JSON parse errors, this was the solution:
app/middleware/catch_json_parse_errors
class CatchJsonParseErrors
def initialize(app)
#app = app
end
def call(env)
#app.call(env)
rescue ActionDispatch::Http::Parameters::ParseError => error
if JSON_API_MIME_TYPES.include?(env['CONTENT_TYPE']) ||
JSON_API_MIME_TYPES.include?(env['HTTP_ACCEPT'])
return [
400, { 'Content-Type' => 'application/json' },
[{
status: 400,
error: 'JSON parse error',
message: "There was a problem in the JSON you submitted: #{error}"
}.to_json]
]
else
raise error
end
end
end
config/application.rb
require './app/middleware/catch_json_parse_errors'
...
config.middleware.use CatchJsonParseErrors

Create issue on production but not on localhost

On my rails application, I am receiving an error on production(heroku) but not on my localhost. All of my migrations are done and I can add it through the console, but I cannot get this to work in the controller.
So the area where the error is occuring is here:
respond_to do |format|
if #registration.save
EventMailer.new_registration_notification(#registration, #current_event).deliver
Recipient.create :first_name => #registration.first_name, :last_name => #registration.last_name, :email => #registration.email, :netID => #registration.netID, :event_id => #registration.event_id, :mailing_id => nil
format.html { redirect_to event_path(#current_event), notice: 'Registration was successful' }
Again, I am not getting an error in my development local environment but I am in production. They are both using Postgres. So my registrations ARE saving but Recipient is never created and I get an error. I've checked the heroku logs by running:
herkou logs
but there are no errors shown. On the front end, you see an error that says "Something went wrong. If you're the application owner please check your logs".
Fixed my problem, the problem was with sending the mailer. I did not notice that the mailer wasn't sending and just assumed it was an issue creating the Recipient. I needed to fix some configurations in the production.rb file to use the SMTP server. After fixing that the issue went away

Unable to catch Mysql2::Error in Rails

Currently testing the following code:
def db_check
begin
schema_call = ActiveRecord::Base.establish_connection(
:adapter => 'mysql2',
:host => 'localhost',
:database => 'dev_db',
:username => 'dev_user',
:password => 'dev_pw').connection.execute("SELECT * FROM schema_migrations LIMIT 1")
if schema_call
render :status => 200, :file => "public/success.html"
else
render :status => 500, :file => "public/query_fail.html"
end
rescue Exception => e
puts "#{e.class} ;; #{e.message}"
logger.debug "#{e.class}"
render :status => 500, :file => "public/500.html"
end
end
The eventual goal is to have a call to a MySQL server to see if 1) the server is still up and 2) if the database is available. If the connection doesn't work, an Error is thrown, so I put the code in a rescue block. Unfortunately, even when I use rescue Exception, which I understand to be advised against, I still get a Mysql2::Error message in the browser (I also tried rescue Mysql2:Error, which had no effect).
The duplication of error logging in the rescue is extra attempts to get additional information to work with, but nothing has worked so far. Anyone know how to catch this error?
UPDATE: also, for additional context, testing the code with MySQL not running currently (condition if the DB server is down), get back the following:
Mysql2::Error
Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)
which makes partial sense, given the server is off, but I still don't understand why it isn't rescuing the error.
The reason the rescue isn't catching the Mysql2::Error is that the error isn't coming from the ActiveRecord::Base code, but rather is Rails throwing an error because it can't connect to the MySQL server that it expects (which I had turned off to test the above code).

Why Ajax renders 2 views in rails 3.1 app

When entering log in our rails 3.1 app, ajax is used to render the input screen below. Here is the link for log:
<%= link_to 'Log', new_part_out_log_path(#part, :format => :js), :remote => true, :id => 'new_log_link' %>
And the new.js.erb as this:
$("<%= escape_javascript render(:file => 'out_logs/new.html.erb') %>").insertAfter('#new_log_link');
$('#new_log_link').hide();
$('#close').hide();
the problem is that after clicking 'Log', instead of one view, 2 identical views of out_logs/new.html.erb were rendered. What may be wrong with our code? thank so much.
The problem is related to upgrade to ruby 1.9.3 which causes webrick server (for development) warning message and also rendering the .js.erb file twice on screen. The twice rendering problem disappears on our production server which is running nginx. The following link may help to understand the problem:
http://theresa.multimediatechnology.at/webrick-warnings-in-ruby-1-9-3/
What does "WARN Could not determine content-length of response body." mean and how to I get rid of it?

how to render rails static 404, 500 error pages without site layout?

I'm using rails 3. In production rails nicely handles exceptions and loads my static 404.html, 500.html etc files from my public directory. However, it loads these files into my layouts/application.html.erb file. I am looking for a way to instruct rails to load these files WITHOUT using my application layout - e.g. just serve the static html file and nothing else. What is the best way to accomplish this?
thanks!
render :file => 'public/404.html', :status => :not_found, :layout => false
For an advanced approach working within the Rails framework. Update your routes file:
get "/404", to: "errors#error_404"
get "/500", to: "errors#error_500"
Add an ErrorsController with:
layout false
def error_404
render status: 404
end
def error_500
render status: 500
end
Then within the app/views/errors/ add your error_404.erb and error_500.erb files along with a snazy image and a search bar.
More info here.

Resources