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 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.
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.