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 = true
So 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
end
I 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.