DEV Community

Cover image for How to use transactions to unclutter your Rails controllers

How to use transactions to unclutter your Rails controllers

Rémi Mercier on September 13, 2019

When your Rails app needs to handle multiple steps, your controllers' methods can become a mess. Don't despair, though. You can delegate sequentia...
Collapse
 
kdraypole profile image
Kobe Raypole

Cool article Rémi. I'm confused about why you would use dry-transactions when Rails already uses transactions in model callbacks.

For instance, you could do after_save :send_emails, and then put all of your logic within a private method you would end up with a similar situation. All of the logic would be wrapped and protected in the protective transaction cover.

Collapse
 
codenamev profile image
Valentino Stoll • Edited

I think the naming that the dry-transactions gem uses is definitely throwing people here (and I think missing the point Rémi is trying to make). This is less about wrapping code chunks in database transactions, and more about extracting business logic into processable steps to better align with how operators of the business perceive the flow of their clients (users).

I've used a couple other gems (namely trailblazer, and waterfall) which provide an entire framework for taking this idea a step further. Having worked with Trailblazer the most recent, I can say that simply having a rigid structure for processing data through chainable events (as is done in this great article) was an incredible dev experience that clearly defined a picture of what was happening and why.

Rails controllers are great for gathering data and directing it to the right pipeline, but I can't say I've come across anything remarkable in Rails that helps establish these pipelines.

Collapse
 
mercier_remi profile image
Rémi Mercier

I wouldn't have been able to explain this better. Thanks @codenamev for this great explanation and the kind words!

Collapse
 
mercier_remi profile image
Rémi Mercier

Hey Kobe, thanks for your question. To be honest, I wouldn't know how to answer this one.

Could I add several after_save and handle the return of each action?

Collapse
 
mememe profile image
mememe • Edited

I was going to post the same thing. This can be handled by rails without the need of an additional gem.

Lead.transaction do
   # do something
end

Maybe I am missing something.

Collapse
 
mercier_remi profile image
Rémi Mercier

I thought that Lead.transaction - to use your example - only allowed me to wrap database operations as a single unit. With the dry-transaction it's more about any kind of operations. But maybe I am missing something.

Collapse
 
eugzol profile image
Eugene Zolotarev

What if your sms service failed? You render 'new' action as if nothing has happened, meanwhile Lead is persisted in the database and in the remote system, right? Then user sends form once again, and you have one more Lead in the db and in remote system. Am I missing something?

Collapse
 
mercier_remi profile image
Rémi Mercier

In the transaction has it's written above, yes. This is what would happen.

I'd include a first step that checks if the new lead already exists in the DB and branch out if that's the case. This really depends on your business logic. :)