How can I use exception handling in Rails? Currently I have done following.
In each controller method I have added
begin
<myCode>
rescue
<exception handler>
But I think with Rails I should be able to define an exception handler method in Application controller and catch all the exceptions from there, without handling them from each method.
I have used 'rescue_action_in_public' in my application controller, but when I given a wrong database name in config/database.yml and load the application, it doesn't catch those exceptions.
My questions are
1 - Is it a recompilation practice to have one exception handler in the application controller and catch the exceptions ? If not, what is the standard way ?
2 - How can I handle the Exceptions like Databse not found, doesn't have permission to view table fields, etc kind of low level exceptions
I'm riding on Rails 3 and I have some projects in Rails 2.3.8 as well
With according to Advanced Rails Recipes book by PragProg, the general exception handling is the good approach.
rescue_action (all environments), and rescue_action_in_public (production) are using to caught any exceptions in abstract controller class. So you do it right way.
Boot application happens before the controllers are loaded, so you can't handle database.yml over there. If you still need to do it, put an initializer ruby file to check that the file exist and a valid, then initialize AR::Base connection to perform DESC table for instance.
For Rails 3 you can use rescue_from in your ApplicationController. If the exceptions you want to catch are at a lower level then you can configure a Rack Middleware layer will allow you to catch exceptions that the controller does not have access to. This is how Hoptoad works. I recently released a rails 3 gem that will catch common exceptions using rescue_from and provide well defined http status codes and error responses for html, json and xml. This may or may not fit your needs. https://github.com/voomify/egregious
Related
I am logging the errors of a rails application using exception_logger (https://github.com/ryancheung/exception_logger) and it is working file. But it is logging the backtrace which I don't want to be logged.
Is there any way to stop logging backtrace?
Side note: why would you want that? Backtraces are very valuable as they tell you exactly where a problem (exception) occurs in your code.
Anyway, it seems that logging exceptions backtrace is not configurable in the exception_logger gem. So your only option would be to monkey-patch some of its code. I'd try to patch the setter for the backtrace in the LoggedException model.
Put this into an initializer under lib/initializers:
# lib/initializers/logged_exception_patch.rb
module ExceptionLogger
class LoggedException < ActiveRecord::Base
def backtrace=(trace)
write_attribute :backtrace, ""
end
end
end
This code will make the model just ignore back traces when saving the logged exceptions and save a blank string to the backtrace column instead.
But let me say again - I think that if you are logging real exceptions on a real site, sooner or later you will regret not logging the back traces because you will get an exception with an unclear origin...
I have a fairly complex service that creates and saves a lot of domain instances, and because of the logic, I need to create different instances at different times, and in the middle check for certain conditions, that are not only that each instance is valid, but for example I need to check if certain files exist in the file system, etc.
I'm testing the incorrect cases, where the service throws an exception, and I need to test that no instances where persisted if an exception is thrown.
One specific test case was failing, even if the expected exception was thrown, a domain instance was saved to the DB. Then I read that because the integration test was transactional itself, the rollback really occurs at the end of the test, instead of after using the service, so I can check conditions on the "then" section of the spock test case.
So if the rollback occurs after I can test it, I can't test it :(
Then I read that making the integration test not transaction might help, so I added:
static transactional = false
After this, all my other tests started to fail!
My question is: what is the right way of testing services that should rollback when an exception is thrown? I just need to verify that after an exception occurs, there are no alterations to the database (since this is a healthcare application, data consistency is key)
FYI:
This is the service I need to test: https://github.com/ppazos/cabolabs-ehrserver/blob/master/grails-app/services/com/cabolabs/ehrserver/parsers/XmlService.groovy
This is my current test: https://github.com/ppazos/cabolabs-ehrserver/blob/master/test/integration/com/cabolabs/ehrserver/parsers/XmlServiceIntegrationSpec.groovy
Thanks!
If you can modify your code to rely on the framework, then you don't need to test the framework.
Grails uses Spring and the Spring transaction manager rolls back automatically for RuntimeExceptions but not for checked exceptions. If you throw a RuntimeException for your various validation scenarios then Spring will handle it for you. If you rely on those facts, your test could then stop at verifying that a RuntimeException is thrown.
If you want to use a checked exception (such as javax.xml.bind.ValidationException ) then you can use an annotation to ensure it causes a rollback:
#Transactional(rollbackFor = ValidationException.class)
def processCommit( ....
and then your test need only check
def ex = thrown(ValidationException)
See http://docs.spring.io/spring/docs/current/spring-framework-reference/html/transaction.html#transaction-declarative-attransactional-settings for more information.
My app is just a typical Rails with a Postgresql (actually, Postgres app on OS X). I would like to add exception handling when my Rails app cannot connect to the database and show plain text of connection error for now, instead of a Rails error page (or may be static HTML error page later on).
I've tried adding exception below to the application_controller.rb.
# from app/controllers/application_controllers.rb
-------------------------------------------------
rescue_from PG::ConnectionBad, with: :database_connection_error
def :database_connection_error
render plain: "Could not connect to the Database"
end
(code ommited)
but it's not rendering plain text. (I also use this exception snippet on the other controllers. It's working but it's handling a different exception, e.g. I use it to handling ActiveRecord::RecordNotFound error)
Is there any way to handle a PG::ConnectionBad or point out what I am doing wrong here?
Thanks in advance.
Where can I register a handler in Rails 3 that can catch view errors? There is a class of error that Rails raises that we wish to handle and silence instead of logging as FATAL.
(These are not errors in our code, rather errors caused by the client closing the connection before the page has finished rendering, and Rails/unicorn attempting to write to a broken pipe.)
Will rescue_from work for you? http://api.rubyonrails.org/classes/ActiveSupport/Rescuable/ClassMethods.html
You can conceivably rescue (and silence) your particular subclass of ActionView::TemplateError
I created a webpage and a XML REST service.
0.
I would like to know how errors are handled in Rails (general).
1.
Let say that a controller does not exists and I would like to redirect a user to a default "Page not found" address (website) or show a default error status code (REST).
2.
What is a best practice for handling controller action errors e.g. when saving but a record is not saved or some param[] field does not exists or else. Usually I use rescue command and I repeat this in every create or update action (would be cool to have some kind of general error handling for that case).
Thank you!
Rails handles 404 and 500 errors out-of-the-box. In development mode you will see detailed error messages. However, in production Rails will use the 404.html and 500.html pages in the public directory.
If the route is not recognised, Rails will return a 404 error.
I generally don't handle errors at the controller level unless they are expected - so I don't wrap everything in begin...rescue. Rails will return the 500 error page if something fatal has occurred. If I expect a particular set of parameters I validate before proceeding and in this case have a redirection or return result to indicate the incomplete parameters.