ActiveSupport.halt_callback_chains_on_return_false = false
Finally getting to upgrading to Rails 5.1 and there are lots of cases where we use before_* callbacks to block behaviour, most often in before_destroy to prevent a record being deleted when some conditions are met / not met. Previously Rails 5.1 allowed you to just return false in a callback to halt the callback chain. Now you must use throw(:abort).
The behaviour change was turned off by default in Rails 5.0
ActiveSupport.halt_callback_chains_on_return_false = trueSo you can implement the change sooner by changing that setting in an initializer.
class Thing < ApplicationRecord
before_create do
throw(:abort)
end
before_destroy do
throw(:abort)
end
endI thought initially this would result in having to cope with exceptions raised from throwing that abort rather than say checking if object.destroy returned false. However, it seems it’s just a clarification of behaviour to avoid accidental blocking.
2.3.0 :006 > Thing.create.persisted?
(0.1ms) BEGIN
(0.1ms) ROLLBACK
=> false
2.3.0 :007 > reload!
Reloading...
=> true
2.3.0 :008 > Thing.create.persisted?
(0.1ms) BEGIN
SQL (0.3ms) INSERT INTO `things` (`created_at`, `updated_at`) VALUES ('2019-01-17 08:38:24', '2019-01-17 08:38:24')
(0.5ms) COMMIT
=> true
2.3.0 :009 > Thing.last.destroy
Thing Load (0.3ms) SELECT `things`.* FROM `things` ORDER BY `things`.`id` DESC LIMIT 1
(0.1ms) BEGIN
(0.1ms) ROLLBACK
=> false
2.3.0 :010 > reload!
Reloading...
=> true
2.3.0 :011 > Thing.create.persisted?
(0.1ms) BEGIN
SQL (0.2ms) INSERT INTO `things` (`created_at`, `updated_at`) VALUES ('2019-01-17 08:39:29', '2019-01-17 08:39:29')
(21.0ms) COMMIT
=> true
2.3.0 :010 > reload!
Reloading...
2.3.0 :014 > Thing.last.destroy
Thing Load (0.1ms) SELECT `things`.* FROM `things` ORDER BY `things`.`id` DESC LIMIT 1
(0.1ms) BEGIN
SQL (0.2ms) DELETE FROM `things` WHERE `things`.`id` = 2
(0.6ms) COMMIT
=> #<Thing id: 2, created_at: "2019-01-17 08:39:29", updated_at: "2019-01-17 08:39:29">Hopefully this won’t be too painful an exercise.