Rollback transactions without exceptions

16 views
Skip to first unread message

Mohammed Shirkavand

unread,
Jan 22, 2018, 7:02:30 PM1/22/18
to Ruby on Rails: Core
There is only one way to rollback a transaction in Rails: using an exception.

Although an exception may be used to rollback a transaction is OK in certain scenarios, i think it should not be used to rollback all of them. Making a nice differentiation between errors and exceptions makes the code more readable and easy to maintain (it looks awkward to write an exception to handle a name length validation that is not honored in order to rollback a transaction, when ther is already a `.valid?` method related to the model that handle that)

Basically i think it would be nice to honor the next two rules:

1. "Exceptions are not meant to be expected, that is why they are called exceptions" 
2. "Don't use exceptions for control flow"

Some benefits:

1. We will not have two different ways to handle the same model-validation: so we can use `.valid?` and model's `errors` array to handle model validations within (or not) a transaction

2. Good differentiation of what an error is (something that we expect to happen) and an exception (something that is not expected to happen) which is a perfect match for this proposed idea of having a proper `ActiveModel::Error` object which can be used within a transaction too, instead a Exception

4. Error handling within a Transaction will easier to write and read, for example, something around this:

```ruby
# In the model...
class Model < ApplicationRecord

def some_method(...)
...
Transaction do
rollback unless user.save && invite.save
end
# Althoug we roolbacked the transaction this gets executed because we
# did not use an Exception, just regular model valiation
user, invite
...
end

end

# In the controller
class SomeController < ApplicationController

def some_action
user, invite = Model.some_method(...)
If user && invite
# All OK, render json etc
else
# Something went wrong... render errors using ActiveRecord::Error related to user and/or invite models
end
...
end

end
```
Reply all
Reply to author
Forward
0 new messages