The Rails error reporter provides a standard way to collect exceptions and report them to any preferred service or location. This makes it very easy to capture and report errors. However, there are some errors that are not exceptions, but are still important to report. For example, if a method is called with an unexpected argument, it is not an exception, but it is still important to report it.
Now, a precondition violation refers to a situation where the conditions or requirements that need to be met before executing a certain action or function are not satisfied. A precondition violation occurs when these assumptions are not met, which can lead to unexpected or incorrect behavior.
Let’s take an example of a blog application where a user should not be able to edit an article that is already published. If for some reason the user is able to edit a published article, it is a precondition violation.
Though this is not an error or an exception, it is still important to report it. Before Rails 7.2, the only way to report this was to raise an exception or manually call the error reporter.
It might look something like this:
This isn’t ideal because sometimes for unexpected or rare issues, it is better to handle such conditions gracefully in production but raise in other environments. This is a common pattern for situations where something isn’t supposed to happen, but if it does, one should be able to recover from it.
In such situations, the violation shouldn’t be hidden in development or test, as it’s likely a bug, but it’s not an exception, so it shouldn’t be raised in production either.
In other words, it should behave like
#record in development and test environments but like
#raise in production.
After this PR Rails introduces
ErrorReporter#unexpected for reporting precondition violations.
Now, the above example can be written as:
This will raise an error in development and test, but only report the error in production.
The behavior is controlled by the
Rails.error.debug_mode configuration. When it is set to true, an error is raised:
However, when it is set to false, the error is reported and the method returns nil.