Panayotis Matsinopoulos
2012-Aug-20 08:16 UTC
A rollback is not issued when dependent object before_destroy callback returns false
Hi, I am wondering whether this is the designed behavior of ActiveRecord, when, to me, it is not the expected one. I have a simple model design with an Order having many Order Items and an Order Item belonging to an Order. The has_many association on Order has a :dependent => :destroy option. Also, the Order Item has a before_destroy function that would check the price of the Order Item. If the price is above 100, it returns false and does not allow the Order Item to be destroyed. The classes codes has as follows: class Order < ActiveRecord::Base attr_accessible :order_code has_many :order_items, :inverse_of => :order, :dependent => :destroy end class OrderItem < ActiveRecord::Base attr_accessible :price, :order_id belongs_to :order, :inverse_of => :order_items before_destroy :low_price protected def low_price if price <= 100 puts "I have low price...I can be deleted" true else puts "I have high price...I cannot be deleted" false end end end The problem is that when I am issuing a destroy on an instance of an order that has an order item that has price > 100, then the order item is not deleted, but the order does. Here are the console commands and output:> rails cLoading development environment (Rails 3.2.8) 1.9.3-p194 :001 > o = Order.new :order_code => ''first order'' => #<Order id: nil, order_code: "first order", created_at: nil, updated_at: nil> 1.9.3-p194 :002 > o.save! (0.1ms) BEGIN SQL (0.2ms) INSERT INTO `orders` (`created_at`, `order_code`, `updated_at`) VALUES (''2012-08-20 08:14:20'', ''first order'', ''2012-08-20 08:14:20'') (2.0ms) COMMIT => true 1.9.3-p194 :003 > o.order_items << OrderItem.new(:price => 110) (0.1ms) BEGIN SQL (0.3ms) INSERT INTO `order_items` (`created_at`, `order_id`, `price`, `updated_at`) VALUES (''2012-08-20 08:14:31'', 5, 110, ''2012-08-20 08:14:31'') (0.5ms) COMMIT OrderItem Load (0.3ms) SELECT `order_items`.* FROM `order_items` WHERE `order_items`.`order_id` = 5 => [#<OrderItem id: 4, order_id: 5, price: 110, created_at: "2012-08-20 08:14:31", updated_at: "2012-08-20 08:14:31">] 1.9.3-p194 :004 > o.destroy (0.2ms) BEGIN I have high price...I cannot be deleted SQL (1.0ms) DELETE FROM `orders` WHERE `orders`.`id` = 5 (1.8ms) COMMIT => #<Order id: 5, order_code: "first order", created_at: "2012-08-20 08:14:20", updated_at: "2012-08-20 08:14:20"> 1.9.3-p194 :005 > Can somebody explain to me, why the failure of the dependent object destroy method does not trigger a rollback? Thanks in advance Panayotis -- 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To view this discussion on the web visit https://groups.google.com/d/msg/rubyonrails-talk/-/tYWGJ6euWZQJ. For more options, visit https://groups.google.com/groups/opt_out.
Gintautas Šimkus
2012-Aug-21 04:34 UTC
Re: A rollback is not issued when dependent object before_destroy callback returns false
Why would you want to return false from a callback and still destroy it? I think you might try to squeeze two different concepts into a single method definition: if you want to check whether or not price is lower than something and actually USE that information somewhere else, then just create another method "low_price?", and you can use it in "low_price" callback: def low_price if low_price? # do something before the record is destroyed end true end def low_price? price <= 100 end 2012/8/20 Panayotis Matsinopoulos <panayotis-2qElkpaxrV4pvVtuE3Kueg@public.gmane.org>> Hi, > > I am wondering whether this is the designed behavior of ActiveRecord, > when, to me, it is not the expected one. > > I have a simple model design with an Order having many Order Items and an > Order Item belonging to an Order. The has_many association on Order has a > :dependent => :destroy option. > Also, the Order Item has a before_destroy function that would check the > price of the Order Item. If the price is above 100, it returns false and > does not allow the Order Item to be destroyed. > > The classes codes has as follows: > > class Order < ActiveRecord::Base > attr_accessible :order_code > has_many :order_items, :inverse_of => :order, :dependent => :destroy > end > > class OrderItem < ActiveRecord::Base > attr_accessible :price, :order_id > > belongs_to :order, :inverse_of => :order_items > > before_destroy :low_price > > protected > > def low_price > if price <= 100 > puts "I have low price...I can be deleted" > true > else > puts "I have high price...I cannot be deleted" > false > end > end > end > > The problem is that when I am issuing a destroy on an instance of an order > that has an order item that has price > 100, then the order item is not > deleted, but the order does. Here are the console commands and output: > > > rails c > Loading development environment (Rails 3.2.8) > 1.9.3-p194 :001 > o = Order.new :order_code => ''first order'' > => #<Order id: nil, order_code: "first order", created_at: nil, > updated_at: nil> > 1.9.3-p194 :002 > o.save! > (0.1ms) BEGIN > SQL (0.2ms) INSERT INTO `orders` (`created_at`, `order_code`, > `updated_at`) VALUES (''2012-08-20 08:14:20'', ''first order'', ''2012-08-20 > 08:14:20'') > (2.0ms) COMMIT > => true > 1.9.3-p194 :003 > o.order_items << OrderItem.new(:price => 110) > (0.1ms) BEGIN > SQL (0.3ms) INSERT INTO `order_items` (`created_at`, `order_id`, > `price`, `updated_at`) VALUES (''2012-08-20 08:14:31'', 5, 110, ''2012-08-20 > 08:14:31'') > (0.5ms) COMMIT > OrderItem Load (0.3ms) SELECT `order_items`.* FROM `order_items` WHERE > `order_items`.`order_id` = 5 > => [#<OrderItem id: 4, order_id: 5, price: 110, created_at: "2012-08-20 > 08:14:31", updated_at: "2012-08-20 08:14:31">] > 1.9.3-p194 :004 > o.destroy > (0.2ms) BEGIN > I have high price...I cannot be deleted > SQL (1.0ms) DELETE FROM `orders` WHERE `orders`.`id` = 5 > (1.8ms) COMMIT > => #<Order id: 5, order_code: "first order", created_at: "2012-08-20 > 08:14:20", updated_at: "2012-08-20 08:14:20"> > 1.9.3-p194 :005 > > > > Can somebody explain to me, why the failure of the dependent object > destroy method does not trigger a rollback? > > Thanks in advance > Panayotis > > -- > 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org > To unsubscribe from this group, send email to > rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org > To view this discussion on the web visit > https://groups.google.com/d/msg/rubyonrails-talk/-/tYWGJ6euWZQJ. > For more options, visit https://groups.google.com/groups/opt_out. > > >-- 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit https://groups.google.com/groups/opt_out.
Gintautas Šimkus
2012-Aug-21 04:37 UTC
Re: A rollback is not issued when dependent object before_destroy callback returns false
Sorry should read. 2012/8/21 Gintautas Šimkus <dihitales-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>> I think you might BE TRYING to squeeze two different concepts >-- 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
Panayotis Matsinopoulos
2012-Aug-21 06:16 UTC
Re: A rollback is not issued when dependent object before_destroy callback returns false
Thanks for your answer. See my comments below On Tuesday, August 21, 2012 7:34:34 AM UTC+3, Dihital wrote:> > Why would you want to return false from a callback and still destroy it?No. I do not want. I think you missed the point of my post. In the example that I have written the Order Item IS NOT CORRECTLY deleted, because it has high price. The PROBLEM is that the OWNING Order is deleted, when it shouldn''t. Please, consider this as an example of an owner (Order in the example) being deleted when it shouldn''t (because of the fact that the owned item (Order Item in the example) is not deleted). Do not stick too much on the business value of the example. There may not be much, if any. Panayotis> I think you might try to squeeze two different concepts into a single > method definition: if you want to check whether or not price is lower than > something and actually USE that information somewhere else, then just > create another method "low_price?", and you can use it in "low_price" > callback: > > def low_price > if low_price? > # do something before the record is destroyed > end > true > end > > def low_price? > price <= 100 > end > > 2012/8/20 Panayotis Matsinopoulos <pana...-2qElkpaxrV4pvVtuE3Kueg@public.gmane.org <javascript:>> > >> Hi, >> >> I am wondering whether this is the designed behavior of ActiveRecord, >> when, to me, it is not the expected one. >> >> I have a simple model design with an Order having many Order Items and an >> Order Item belonging to an Order. The has_many association on Order has a >> :dependent => :destroy option. >> Also, the Order Item has a before_destroy function that would check the >> price of the Order Item. If the price is above 100, it returns false and >> does not allow the Order Item to be destroyed. >> >> The classes codes has as follows: >> >> class Order < ActiveRecord::Base >> attr_accessible :order_code >> has_many :order_items, :inverse_of => :order, :dependent => :destroy >> end >> >> class OrderItem < ActiveRecord::Base >> attr_accessible :price, :order_id >> >> belongs_to :order, :inverse_of => :order_items >> >> before_destroy :low_price >> >> protected >> >> def low_price >> if price <= 100 >> puts "I have low price...I can be deleted" >> true >> else >> puts "I have high price...I cannot be deleted" >> false >> end >> end >> end >> >> The problem is that when I am issuing a destroy on an instance of an >> order that has an order item that has price > 100, then the order item is >> not deleted, but the order does. Here are the console commands and output: >> >> > rails c >> Loading development environment (Rails 3.2.8) >> 1.9.3-p194 :001 > o = Order.new :order_code => ''first order'' >> => #<Order id: nil, order_code: "first order", created_at: nil, >> updated_at: nil> >> 1.9.3-p194 :002 > o.save! >> (0.1ms) BEGIN >> SQL (0.2ms) INSERT INTO `orders` (`created_at`, `order_code`, >> `updated_at`) VALUES (''2012-08-20 08:14:20'', ''first order'', ''2012-08-20 >> 08:14:20'') >> (2.0ms) COMMIT >> => true >> 1.9.3-p194 :003 > o.order_items << OrderItem.new(:price => 110) >> (0.1ms) BEGIN >> SQL (0.3ms) INSERT INTO `order_items` (`created_at`, `order_id`, >> `price`, `updated_at`) VALUES (''2012-08-20 08:14:31'', 5, 110, ''2012-08-20 >> 08:14:31'') >> (0.5ms) COMMIT >> OrderItem Load (0.3ms) SELECT `order_items`.* FROM `order_items` WHERE >> `order_items`.`order_id` = 5 >> => [#<OrderItem id: 4, order_id: 5, price: 110, created_at: "2012-08-20 >> 08:14:31", updated_at: "2012-08-20 08:14:31">] >> 1.9.3-p194 :004 > o.destroy >> (0.2ms) BEGIN >> I have high price...I cannot be deleted >> SQL (1.0ms) DELETE FROM `orders` WHERE `orders`.`id` = 5 >> (1.8ms) COMMIT >> => #<Order id: 5, order_code: "first order", created_at: "2012-08-20 >> 08:14:20", updated_at: "2012-08-20 08:14:20"> >> 1.9.3-p194 :005 > >> >> >> Can somebody explain to me, why the failure of the dependent object >> destroy method does not trigger a rollback? >> >> Thanks in advance >> Panayotis >> >> -- >> 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 rubyonra...-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org<javascript:> >> . >> To unsubscribe from this group, send email to >> rubyonrails-ta...-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org <javascript:>. >> To view this discussion on the web visit >> https://groups.google.com/d/msg/rubyonrails-talk/-/tYWGJ6euWZQJ. >> For more options, visit https://groups.google.com/groups/opt_out. >> >> >> > > >-- 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To view this discussion on the web visit https://groups.google.com/d/msg/rubyonrails-talk/-/6FzcVY8zt5MJ. For more options, visit https://groups.google.com/groups/opt_out.