Provide all ActiveRecord exceptions with a `record` attribute

Hey,

It would be useful to inspect the record in question every time an ActiveRecord exception is raised. This is currently possible with some (ActiveRecord::RecordNotSaved for instance), but not others. Any idea what the rationale for this selection is? I initially thought that you can query the exception for the record as long as it exists (or existed), but ActiveRecord::RecordNotSaved refutes that assumption, because you could be creating it for the first time.

The goal from such a proposal would be generic error collecting. For instance rescuing from all descendants of ActiveRecordError and passing the record id to Sentry, if it exists. But so far it won’t work with all of them

Not sure if it helps, but I was initially interested in the record associated with a StatementInvalid exception.

This seems tricky - many of the places where StatementInvalid (or its descendants) is raised don’t have any direct relationship with a particular record. For instance, an ActiveRecord::InvalidForeignKey could occur in an `update_all` call - or an ActiveRecord::PreparedStatementCacheExpired could happen on a query.

The children of ActiveRecordError that currently include a record are much more directly tied to the concept “the code specifically requested that X be done to *this* object but something went wrong” (RecordNotSaved, RecordNotDestroyed, StaleObjectError, UnknownAttributeError) than the situations that raise StatementInvalid.

—Matt Jones

Thanks for the response Matt. I agree about the StatementInvalid exception. In fact in my case it happened in a query on a collection, so exactly as you described.

However it can happen on a individual object as well. Correct it if I am wrong, but ActiveRecord::InvalidForeignKey will also be raised when attempting to create an individual record, and like RecordNotSaved, there is no reason not to have access to that record object.

So my thinking was, if it could, then we may as well set the record attribute. If it’s nil, you know this was raised from a non-individual-record specific source. A bit contrived but very helpful in the situation I described at the outset.