In Rails.
Exception can rescue in controller class but in model class can not.
How to rescue exception in model?
You can do exception handling anywhere in a rails application, as it's part of Ruby, not part of Rails. Wherever you want to catch errors, just wrap it as so:
begin
SomethingElse.doSomething(x, y)
rescue Exception
ErrorLogger.log(Time.now, "Something went wrong!")
end
Please note that you should always "rescue Exception" instead of just "rescue". Just using "rescue" will only catch StandardError, which is a subclass of Exception (meaning something might get through that you don't want to get through).
Also as usual, you can raise an exception by doing:
raise ArgumentError, "Illegal arguments!"
anywhere in your code, be it a model or controller.
Unless I'm mistaken you can use error handling anywhere in Ruby. What are you trying to do?
Related
Some background
PG::InFailedSqlTransaction appears when some PG exception is rescued and prevents the transaction from rollback. Simple example:
ActiveRecord::Base.transaction do
ActiveRecord::Base.connection.execute('SELECT nothing FROM nowhere') rescue nil
binding.pry # <- let's assume we're here
User.count # raises PG::InFailedSqlTransaction
end
The first line inside the transaction silently breaks the transaction and proceeds, any SQL statements after the first line will raise PG::InFailedSqlTransaction: ERROR: current transaction is aborted, commands ignored until end of transaction block.
The question
Assuming we're on the binding.pry breakpoint above, are there any ways to debug it and get the initial exception or any other data?
Not quite sure how it is implemented under the hood, but it seems quite possible for PG to cache some metadata about errors.
EDIT: the code above is just an example to demonstrate the general issue, the question is how to get the error in the situation when we cannot easily find the place that rescues the exception
Per #engineersmnky comment, it is possible to get the last error message from the PG::Connection instance with #error_message method, the instance can be obtained from the ActiveRecord connection: ActiveRecord::Base.connection.raw_connection.error_message.
If we run the above command from the pry breakpoint in the example from the question, it will return the following message:
ERROR: relation "nowhere" does not exist
LINE 1: SELECT nothing FROM nowhere
^
In the production environment configuration I can't seem to find a configuration parameter to tell the server that when an ActiveRecord Class.find() throws an exception, that it should really be an exception. In development mode, it throws an ActiveRecord::RecordNotFound exception, but in production it rescues it and renders a 404. I seem to remember this being something you could turn on/off? I would rather not monkey patch the 404 which is the only solution I have seen so far.
The .find(id) method should be used whenever you want an exception to be thrown if the id cannot be found as described in the documentation. If you don't want an exception to be thrown, you should use .find_by_id(id).
https://github.com/rails/rails/blob/4-0-stable/activerecord/lib/active_record/railtie.rb#L26
adds a mapping
'ActiveRecord::RecordNotFound' => :not_found
asking action_dispatch to rescue 'ActiveRecord::RecordNotFound' with :not_found response.
Doing -
YourAppName::Application.config.action_dispatch.rescue_responses.delete('ActiveRecord::RecordNotFound')
in your initializer might get what you're expecting.
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’m working on this issue: Rails exception notifier in rake tasks
My question: Is there any function/plugin/gem/whatever to setup a generic error/exception handler callback as in PHP with set_error_handler and set_exception_handler?
I need a way to register a callback function used as a catchall outside any begin .. rescue .. end block. For example:
def my_handler *args
# exception processing code here
end
some_magic_method my_handler
raise "An Exception" # this will be handled by my_handler
In PHP this could be achieved with the set_exception_handler function. Is there any such function in Ruby/Rails?
If such feature exists I could solve my previous issue in a simple way.
A Rails-only solution would be fine for my needs.
I don't believe Ruby provides a way to do this, either with exceptions or with throw/catch. In general, doing something this way is a code smell and something to avoid. It makes control flow extremely hard to figure out. I would try to find some other way to approach the problem if at all possible.
If you want to do this in the HTTP Request-handling cycle you may use an around filter in your application controller:
class ApplicationController < ActionController::Base
around_filter do |controller, action|
action.call
rescue ExceptionXPTO
# ... handle the exception ...
end
end
I found a partial solution to my issue which works for the simple case I mentioned in the question. However this can not catch the exception, but it can be useful if someone needs only exception logging or reporting.
#!/usr/bin/env ruby
at_exit do
if $!
puts "Program ended with an exception #{$!.message}"
puts $!.backtrace.join("\n")
# or log the exception here
end
end
loop do
value = rand(3)
puts "Value is #{value}"
break if value == 2
raise "An Exception" if value == 0
end
puts "Program ended normally"
I want to verify that an exception is being thrown in some function tests by calling get :methodname, :params. I had expected just making this call and then verifying the result is a 500 would be sufficient, but rails is failing the test as soon as the exception is reached in the get. While I figure I could go ahead and wrap the get in a rescue and verify the exception is thrown myself, and would hope there's a better method for doing this.
What's the best way to verify an exception is thrown when using a get in your tests?
You can do:
def test_sommat
assert_raises SomeException do
get :methodname, params
end
end