Dealing with hotlinking and old references after rebuild in rails - ruby-on-rails

I just launched a completely rebuilt in rails website and am using New Relic for error monitoring. I've been getting a lot of errors and alerts for what I'm guessing is people using bookmarks for pages/paths that no longer exist and possibly some hot linking.
What is the best way to resolve this situation so that I stop getting the alerts?

How about ignoring those errors?
ignore_errors - A comma separated list of Exception classes which will
be ignored
In addition, the error collector can be customized programmatically
for more control over filtering. In your application initialization,
you can register a block with the Agent to be called when an error is
detected. The block should return the error to record, or nil if the
error is to be ignored. For example:
config.after_initialize do
::NewRelic::Agent.ignore_error_filter do |error|
if error.message =~ /gateway down/
nil
elsif
error.class.name == "InvalidLicenseException"
StandardError.new "We should never see this..."
else
error
end
end
end
(source)

Related

How can I prevent any ActiveRecord::PreparedStatementCacheExpired errors immediately after running `rake db:migrate`?

I am working on a Rails 5.x application, and I use Postgres as my database.
I often run rake db:migrate on my production servers. Sometimes the migration will add a new column to the database, and this causes some controller actions to crash with the following error:
ActiveRecord::PreparedStatementCacheExpired: ERROR: cached plan must not change result type
This is happening in a critical controller action that needs to have zero downtime, so I need to find a way to prevent this crash from ever happening.
Should I catch the ActiveRecord::PreparedStatementCacheExpired error and retry the save? Or should I add some locking to this particular controller action, so that I don't start serving any new requests while a database migration is running?
What would be the best way to prevent this crash from ever happening again?
I was able to fix this issue in some places by using this retry_on_expired_cache helper:
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
class << self
# Retry automatically on ActiveRecord::PreparedStatementCacheExpired.
# (Do not use this for transactions with side-effects unless it is acceptable
# for these side-effects to occasionally happen twice.)
def retry_on_expired_cache(*_args)
retried ||= false
yield
rescue ActiveRecord::PreparedStatementCacheExpired
raise if retried
retried = true
retry
end
end
end
I would use it like this:
MyModel.retry_on_expired_cache do
#my_model.save
end
Unfortunately this was like playing "whack-a-mole", because this crash just kept happening all over my application during my rolling deploys (I'm not able to restart all the Rails processes at the same time.)
I finally learned that I can turn off prepared_statements to completely avoid this issue. (See this other question and answers on StackOverflow.)
I was worried about the performance penalty, but I found many reports from people who had set prepared_statements: false, and they hadn't noticed any problems. e.g. https://news.ycombinator.com/item?id=7264171
I created a file at config/initializers/disable_prepared_statements.rb:
db_configuration = ActiveRecord::Base.configurations[Rails.env]
db_configuration.merge!('prepared_statements' => false)
ActiveRecord::Base.establish_connection(db_configuration)
This allows me to continue setting the database configuration from the DATABASE_URL env variable, and 'prepared_statements' => false will be injected into the configuration.
This completely solves the ActiveRecord::PreparedStatementCacheExpired errors and makes it much easier to achieve high-availability for my service while still being able to modify the database.

Ruby unable to catch Selenium::WebDriver::Error::StaleElementReferenceError

I have created a method that is called for each web element accessed by the scripts, as to avoid the "StaleElementReferenceError" thrown by selenium. This is how the code looks:
def reach_element(page,element)
begin
element.wait_until_present
rescue Selenium::WebDriver::Error::StaleElementReferenceError
puts '* retrying to reach element'
page.refresh
retry
end
end
It appears that the StaleElementReferenceError is ignored and the tests keep failing with this error.
Am I doing something wrong?
CORRECTIONS:
This error shouldn't appear at all for it to be rescued by ruby.
The main cause was the old version of watir-webdriver gem. If you still encounter this error, a simple gem update should do the trick.
We mostly got rid of stale element issues for when you take an action on an element in watir-webdriver last year. This is the code: https://github.com/watir/watir-webdriver/blob/master/lib/watir-webdriver/elements/element.rb#L597
When an action is taken on the element, but it is stale, it will re-look it up with the selector provided. It will fail for not existing if it isn't there.
Are you seeing your element go stale between when you locate it, but before it becomes visible? That's an interesting use case that I have plans to fix. If that is your issue, refreshing the page will force the element to go stale, so that will just repeat your issue. Remove the refresh, and it should keep relocating the stale element until it is present.
If that isn't the issue or that doesn't work, provide a stack trace of what you are seeing.

How to properly handle errors for "PG::ConnectionBad could not connect to server"?

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.

Rails full error page not showing for view errors

I have a view named new.html.erb with the following code:
<%= some_non_existent_thing.imaginary_method %>
Now, I only see one simple 500 error page, like that:
500 Internal Server Error
If you are the administrator of this website, then please read this web application's log file and/or the web server's log file to find out what went wrong.
Shouldn't I see a pretty formatted page with some information about the exception?
I'm not sure I miss something here, but I believe rails used to show the full error page in development environment when there is something wrong in the view.
Are you sure that you are running the development environment? Check that RAILS_ENV=development or that you are running rails server -e development.
Then check your development.rb file, you should have the following line in it
config.consider_all_requests_local = true
If you happen to have an exception inside an exception, Rails has a middleware that catches it and returns a FAILSAFE_RESPONSE with the following copy:
500 Internal Server Error
If you are the administrator of this website, then please read this web application's log file and/or the web server's log file to find out what went wrong.
A nice way to troubleshoot this is to compare your custom error code with the sample code provided in the Rails 4.2.0 guides.
I'm pointing to that particular version because that whole section was removed in the Rails 5.0.0 guides.
Ideally, you should keep your error views, layout, and controller as free of logic as possible, to avoid running into this issue.
Firstly, as Anton mentions in the answer below, confirm that your config/environments/development.rb has:
config.consider_all_requests_local = true
and that you are running the server in development mode.
I had ensured the above and still observed the error.
This happened in my case, because my logger had some errors. I was using a custom log formatter, which used the String#% method to format the log. % seems to be very buggy and leads to all these weird errors. I figured this one out by adding a debugger line to the controller method and stepping through into the implicit render function call. It hit the bug and reported it as a malformed format string error.
This was the log formatter I was using before, which caused the bugs [I had added it to an initializer file]:
class Logger::SimpleFormatter
def call(severity, time, progname, msg)
"%-7s #{msg}\n" % severity
end
end
These modifications fixed the bug:
class Logger::SimpleFormatter
def call(severity, time, progname, msg)
severity_prefix = "[#{severity}]".ljust(7)
"#{severity_prefix} #{msg}\n"
end
end
This happens if the code is not compilable, for example if you have an if statement missing an end.

Rails error messages and redirections

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.

Resources