Rails 5 server side error handling - ruby-on-rails

Lets say I have some code in my controller action and I am expecting params[:name] to be a string not empty. My user interface notifies the user that hea can't have empty string, but let's say someone uses an app like postman, can they cause the server to crash by sending an empty string that can cause errors because of methods being called on nil class?

The server would not "crash" in that scenario. In any case it will just raise an error and respond with a 500, but it will not "crash" as in making it unusable to process other requests

Related

Remove specific error message from Rails Devise

In Devise, when confirmation instructions are resent and the email doesn't exist in the database, we get the error
Email not found
However, due to security, I want to remove this specific error.
I'm using custom controllers but the confirmation#create method is just invoking super.
Under that, I've removed the email field from the errors using
resource.errors.delete('email')
Printing out the errors (in the controller) after the fact shows nothing for email. However, when the request goes through and I print the resource.errors object in the shared errors partial, the error is still there.
Is there any way to remove this error completely? I'm assuming some other action is happening after the #create method that's injecting the error again.
Full method
def create
super
resource.errors.delete('email')
end
Confirmation of deletion:
Confirmation that error persists after redirect:

How do I log request details for ActionController::RoutingErrors?

I have a custom logger that extracts various headers (notably REMOTE_ADDR and HTTP_X_FORWARDED_FOR) from the ActiveSupport::Notifications event. This works fine for controller events, but when there's a RoutingError, we never hit the controller, and all the logger gets is the exception backtrace as a string. Is there another event I can subscribe to? How can I get access to the request object for requests fail before hitting a controller?
I guess you need to implement some kind of middleware to catch errors that happen before reaching a controller action.
https://guides.rubyonrails.org/rails_on_rack.html
Maybe you can borrow some code from https://github.com/smartinez87/exception_notification or use it implementing a custom notifier https://github.com/smartinez87/exception_notification#notifiers that uses your logger.

Handling Ruby Errors with multiple methods that must be executed if one fails

I've inherited a codebase where they have a call method to send out a document via multiple channels - FTP, SMS, and an Email service.
The way its currently set up is that if the email distribution fails, it will exit out of the method and ensure the other channels run. There currently seems to be very basic error handling and thats about it.
I need it to log an error then move on to the following methods -- without hopefully rewriting all the existing code
How can I go about doing this? Will the following work?
the main call method:
def call
add_customers_to_statement_distribution
statement.final!
copy_generated_pdf_to_final_version
copy_detailed_csv_to_final_version
copy_png_thumbnails_with_days_key_to_public_storage
copy_statement_to_public_storage
disribute_statement_by_email
DistributeToFTP.call(statement)
NotifyCustomersBySms.call(statement)
end
The method with my possible rescue statement added in:
def distribute_statement_by_email
DistributeStatementByEmail.call(statement_distribution,
SENDER_EMAIL,
final_customers_with_csv,
with_csv: true)
DistributeStatementByEmail.call(statement_distribution,
SENDER_EMAIL,
final_customers_without_csv,
with_csv: false)
rescue StandardDistributionError => error
error.new("Statement distributed by email has raised an issue: "\
"#{error.message}")
end
I want to make sure I handle the error in a graceful way.
Thanks!

How to avoid rails from crashing on wrong content type

I am using rails 3.2.8 on Ubuntu 12.04
I am building a web service with json only support. Now if someone sends me data that is not json but sets content-type to application/json the rails application raises an exception and returns 500 (internal server error).
This exception happens within rails before the controller action is called as rails is trying to create the params structure and parse the incoming data as JSON.
I am not sure this is right behaviour. I would have prefered if it rescued the exception and let me know in some special handler or within my action with some variable set. I would want to indicate 415 (unsupported media type) or 422 (unprocessable entity). My guess is 422 is more appropriate in this case.
Any ideas on how this can be accomplished?
Guess you need to change middleware a bit. Either create custom middleware and insert it before ParamsParser, or override the ParamsParser.
Take a look at this request, there is a sample of ParamsParser overriding.
Creating custom middlevare has another advantage: if data is json but content-type is not application/json, you can fix it here (example).

Rails how to handle error and exceptions in model

So I'm parsing data from twitter api in rails using the twitter library, and sometimes the response from api might be like this:
{
error: "Invalid parameter"
}
And the model will raise an exception, right now I'm silently catch it and put the error.message into the log, how do I pass this exception to the controller so I can display it on the view? Thanks.
UPDATE:
The error is likely to happen because I'm allowing my customer to build queries, and they might put advanced queries like "https://search.twitter.com/search.json?since_id=1&&q=near:NYC%20within:15mi" which is supported by the twitter webpage but not by it's API. So I want to catch these kinda of error and display a flash message so the user can have some feedback.
I guess you could an attr_accessor. Something like twitter_errors.
In your model:
attr_accessor :twitter_errors
begin
#your twitter code here
rescue
self.twitter_errors = "whatever"
end
And in your controller, set the flash if #model.twitter_errors isn't empty.
The typical way is to use ActiveModel::Errors.
ActiveRecord uses this mixin extensively for validations. So in an ActiveRecord object you have access to errors.add(:base, TwitterError.to_s). You can use this to set the error when it is caught. And then you should be able to access it via the controller/view using ar_object.errors.
(There are already some helpers for displaying errors like this the docs have much more info)

Resources