ruby on rails - RoR 4.x approach for managing transactions best practices -
first of - sorry perhaps stupid questions i'm beginner in ror world , need basic clarity on how database transactions work within models / controllers. come java world things done in way , when working ror naturally compare java web frameworks hence confusion if looks radically different :-)
in 1 of controller actions, need modify , save multiple of models, let's say: order, invoice, payment.
from understand, standard "save" method on each model executes in it's own transaction therefore if write:
payment.save order.save invoice.save
this create 3 independent db transactions , each model saved in it's own transactions - not want since i'd make sure either or none of these models saved.
i found article: http://markdaggett.com/blog/2011/12/01/transactions-in-rails/ demonstrates how wrap multiple "saves" single transaction. it's old hope still valid (correct me if i'm wrong).
one thing don't need manage these transactions explicitly in each controller action need it. prefer happen "behind scenes" "open session in view" pattern known java world db transaction started in filter before db query executed , transaction committed in filter after controller actions have finished.
i thinking using similar approach in ror application, found blog post demonstrating how it: http://blog.endpoint.com/2011/10/rails-controllers-and-transactions.html i'm not sure whether "best practice" since other article (http://markdaggett.com/blog/2011/12/01/transactions-in-rails/) says "use of transactions in controller common anti-pattern avoid" (not sure why though).
would able direct me "right" approach?
thank you,
michal
transactions model-layer concern. don't think belong in controller, although work. it's not hard rule.
one thing consider code need run outside context of controller? example in background job? or rake task? in case consolidating logic model layer make easier reuse.
to accomplish in model layer, "rails way" make use of callbacks. *_save/create/update
callbacks automatically executed within current database transaction, means desired transaction behavior "for free" without explicitly writing transaction code.
if models have clear parent-child relationship, can register callbacks on "top level" model, e.g.:
class order < activerecord::base has_one :invoice has_one :payment after_create :save_child_records private def save_child_records invoice.save! payment.save! end end order.save # triggers invoice.save! , payment.save! # in 1 transaction
alternatively, create brand new model not backed database table, serves orchestrate multiple models. called "service object" or "operation object".
for recommend active_type gem, lets use standard activerecord callbacks, therefore gives same desirable transaction behavior:
class processpayment < activetype::object attr_accessor :order, :invoice, :payment # can declare activerecord validations here # or register other before_save callbacks business logic before_save :save_records private def save_records order.save! invoice.save! payment.save! end end process_payment.save # order, invoice, payment saved in single transaction
Comments
Post a Comment