Is there any way to _update_ a parent and child object in a single transaction without having to explicitly demarcate that transaction? I''ve got the following two objects: class CostItem < ActiveRecord::Base has_one :cost :dependent => :destroy validates_associated :cost end class Cost < ActiveRecord::Base belongs_to :cost_item validates_numericality_of :amount end In my controller, I''ve got the following: def create @cost_item = CostItem.new(params[:cost_item]) @cost_item.build_cost(params[:cost]) if @cost_item.save ... else # Handle the error end end def update @cost_item = Item.find(params[:id]) if @cost_item.cost.update_attributes(params[:cost]) && @cost_item.update_attributes(params[:cost_item]) ... else # Handle the error end end The ''create'' method works transactionally - if either @cost_item or @cost is invalid, nothing gets saved. However, ''update'' is not transactional: if either @cost_item or @cost is invalid, then the valid one still gets saved. The only way I can see around this is to put a transaction around it and use methods that throw an exception to trigger the rollback: def update @cost_item = Item.find(params[:id]) begin CostItem.transaction do @cost_item.cost.update_attributes!(params[:cost]) @cost_item.update_attributes!(params[:cost_item]) ... end rescue ActiveRecord::RecordInvalid # Handle the error end end However this is a bit more verbose than I hoped. Is there any way to make the updates of related objects fully transactional - in the same manner as creation - without having to explicitly demarcate the transaction? Thanks, Ben --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Mark Reginald James
2008-Mar-17 15:58 UTC
Re: Updating parent-child objects in a single transaction
Ben Teese wrote:> Is there any way to _update_ a parent and child object in a single > transaction without having to explicitly demarcate that transaction? > I''ve got the following two objects: > > class CostItem < ActiveRecord::Base > has_one :cost :dependent => :destroy > validates_associated :cost > end > > class Cost < ActiveRecord::Base > belongs_to :cost_item > validates_numericality_of :amount > end > > In my controller, I''ve got the following: > > def create > @cost_item = CostItem.new(params[:cost_item]) > @cost_item.build_cost(params[:cost]) > if @cost_item.save > ... > else > # Handle the error > end > end > > def update > @cost_item = Item.find(params[:id]) > if @cost_item.cost.update_attributes(params[:cost]) && > @cost_item.update_attributes(params[:cost_item]) > ... > else > # Handle the error > end > enddef update @cost_item = Item.find(params[:id], :include => :cost) @cost_item.cost.attributes = params[:cost] if @cost_item.update_attributes(params[:cost_item]) @cost_item.cost.save! ... else # Handle the error end end If they''re always updated together you can move the save of cost to the model: class CostItem after_update ''cost.save!'' end You should still wrap the two saves in a transaction in case there are DB problems, but it''s best to avoid using transactions to recover from validation failures. -- We develop, watch us RoR, in numbers too big to ignore. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
I am trying to do something very similar and i''ve got update to work, however rails is failing on my create hierarchical xml. to use you example, I am sending something like: <cost_item> <name>blah</name> <description>blah</description> <cost> <amount>10</amount> </cost> </cost_item> what xml format do you post to get this to work? On Mar 16, 8:18 pm, Ben Teese <ben.te...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> Is there any way to _update_ a parent and child object in asingletransactionwithout having to explicitly demarcate thattransaction? > I''ve got the following twoobjects: > > class CostItem < ActiveRecord::Base > has_one :cost :dependent => :destroy > validates_associated :cost > end > > class Cost < ActiveRecord::Base > belongs_to :cost_item > validates_numericality_of :amount > end > > In my controller, I''ve got the following: > > def create > @cost_item = CostItem.new(params[:cost_item]) > @cost_item.build_cost(params[:cost]) > if @cost_item.save > ... > else > # Handle the error > end > end > > def update > @cost_item = Item.find(params[:id]) > if @cost_item.cost.update_attributes(params[:cost]) && > @cost_item.update_attributes(params[:cost_item]) > ... > else > # Handle the error > end > end > > The ''create'' method works transactionally - if either @cost_item or > @cost is invalid, nothing gets saved. However, ''update'' is not > transactional: if either @cost_item or @cost is invalid, then the > valid one still gets saved. > > The only way I can see around this is to put atransactionaround it > and use methods that throw an exception to trigger the rollback: > > def update > @cost_item = Item.find(params[:id]) > begin > CostItem.transactiondo > @cost_item.cost.update_attributes!(params[:cost]) > @cost_item.update_attributes!(params[:cost_item]) > ... > end > rescue ActiveRecord::RecordInvalid > # Handle the error > end > end > > However this is a bit more verbose than I hoped. Is there any way to > make the updates of relatedobjectsfully transactional - in the same > manner as creation - without having to explicitly demarcate thetransaction? > > Thanks, > > Ben--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Frederick Cheung
2008-May-05 09:34 UTC
Re: Updating parent-child objects in a single transaction
On 17 Mar 2008, at 15:58, Mark Reginald James wrote:> > If they''re always updated together you can move the save > of cost to the model: > > class CostItem > after_update ''cost.save!'' > end > > You should still wrap the two saves in a transaction in > case there are DB problems, but it''s best to avoid using > transactions to recover from validation failures.before_save, the actual save and after_save are wrapped in a transaction for you. Fred --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
I''m just using a HTTP POST with parameters, not XML. I''m not sure how it''d work with XML. Cheers, Ben On Mon, May 5, 2008 at 3:39 PM, coconut <Tomer.Doron-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> > I am trying to do something very similar and i''ve got update to work, > however rails is failing on my create hierarchical xml. to use you > example, I am sending something like: > > <cost_item> > <name>blah</name> > <description>blah</description> > <cost> > <amount>10</amount> > </cost> > </cost_item> > > what xml format do you post to get this to work? > > On Mar 16, 8:18 pm, Ben Teese <ben.te...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > Is there any way to _update_ a parent and child object in > asingletransactionwithout having to explicitly demarcate thattransaction? > > I''ve got the following twoobjects: > > > > class CostItem < ActiveRecord::Base > > has_one :cost :dependent => :destroy > > validates_associated :cost > > end > > > > class Cost < ActiveRecord::Base > > belongs_to :cost_item > > validates_numericality_of :amount > > end > > > > In my controller, I''ve got the following: > > > > def create > > @cost_item = CostItem.new(params[:cost_item]) > > @cost_item.build_cost(params[:cost]) > > if @cost_item.save > > ... > > else > > # Handle the error > > end > > end > > > > def update > > @cost_item = Item.find(params[:id]) > > if @cost_item.cost.update_attributes(params[:cost]) && > > @cost_item.update_attributes(params[:cost_item]) > > ... > > else > > # Handle the error > > end > > end > > > > The ''create'' method works transactionally - if either @cost_item or > > @cost is invalid, nothing gets saved. However, ''update'' is not > > transactional: if either @cost_item or @cost is invalid, then the > > valid one still gets saved. > > > > The only way I can see around this is to put atransactionaround it > > and use methods that throw an exception to trigger the rollback: > > > > def update > > @cost_item = Item.find(params[:id]) > > begin > > CostItem.transactiondo > > @cost_item.cost.update_attributes!(params[:cost]) > > @cost_item.update_attributes!(params[:cost_item]) > > ... > > end > > rescue ActiveRecord::RecordInvalid > > # Handle the error > > end > > end > > > > However this is a bit more verbose than I hoped. Is there any way to > > make the updates of relatedobjectsfully transactional - in the same > > manner as creation - without having to explicitly demarcate > thetransaction? > > > > Thanks, > > > > Ben > > > >-- iZepto: Timesheets Made Human http://izepto.com --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---