Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Better Callbacks in Rails 5

Better Callbacks in Rails 5

Claudio B.

April 21, 2015
Tweet

More Decks by Claudio B.

Other Decks in Programming

Transcript

  1. TL;DR class User < ActiveRecord::Base before_save { |u| u.admin ||=

    false } end User.create! #=> ActiveRecord::RecordNotSaved Rails 4 User.create! #=> true Rails 5 2/18
  2. Halting the chain class User < ActiveRecord::Base before_save :set_default_values def

    set_default_values self.admin ||= false # return true || false => true end end User.create!(admin: true) #=> true 4/18
  3. Halting the chain class User < ActiveRecord::Base before_save :set_default_values def

    set_default_values self.admin ||= false # return nil || false => false end end User.create! # Rails 4 #=> ActiveRecord::RecordNotSaved 5/18
  4. Rails 4: implicit If a before_* callback returns false, all

    the later callbacks and the associated action are cancelled. If an after_* callback returns false, all the later callbacks are cancelled. ‛ Rails 4.2 API doc 6/18
  5. Rails 5: explicit If a before_* callback throws :abort, all

    the later callbacks and the associated action are cancelled. ‛ PR #17227 7/18
  6. Rails 5: explicit class User < ActiveRecord::Base before_save :set_default_values def

    set_default_values self.admin ||= false # returned value DOES NOT MATTER end end User.create! # Rails 5 #=> true 8/18
  7. Rails 5: explicit class User < ActiveRecord::Base before_save :ensure_admin def

    ensure_admin throw(:abort) unless self.admin # returned value DOES NOT MATTER end end User.create! # Rails 5 #=> ActiveRecord::RecordNotSaved 9/18
  8. Deprecation policy If a before_* callback returns false ✦ Rails

    4: the chain halts ✦ Rails 4 apps ported to Rails 5: the chain halts with a warning ✦ Rails 5: the chain is unaffected 10/18
  9. Deprecation policy ✦ Rails 4: the chain halts ✦ Rails

    4 apps ported to Rails 5: the chain halts with a warning ✦ Rails 5: the chain is unaffected 11/18 If a before_* callback returns false
  10. Deprecation policy User.create! # Rails 4 app ported to 5

    # DEPRECATION WARNING: Returning `false`in a callback will not implicitly halt a callback chain in the next release of Rails. To explicitly halt a callback chain, please use `throw :abort` instead. #=> ActiveRecord::RecordNotSaved 12/18 class User < ActiveRecord::Base before_save { |u| u.admin ||= false } end
  11. Deprecation policy # config/initializers/callback_terminator.rb ActiveSupport.halt_callback_chains_on_retu rn_false = false 13/18 class

    User < ActiveRecord::Base before_save { |u| u.admin ||= false } end User.create! #=> true
  12. TL;DR class User < ActiveRecord::Base before_save { |u| u.admin ||=

    false } end User.create! #=> ActiveRecord::RecordNotSaved Rails 4 User.create! #=> true Rails 5 14/18
  13. Extra: even better! class MeController < ApplicationController skip_before_action :unknown_method end

    User.create! #=> ActiveRecord::RecordNotSaved 15/18 ‛ PR #19029 GET "/me" at 2015-04-21 15:00:00 -0500 #=> ArgumentError Before process_action callback :unknown_method has not been defined
  14. Extra: even better! class MeController < ApplicationController skip_action_callback :authenticate end

    User.create! #=> ActiveRecord::RecordNotSaved 16/18 ‛ PR #19060 GET "/me" at 2015-04-21 15:00:00 -0500 #=> DEPRECATION WARNING skip_action_callback is deprecated and will be removed in the next major version
  15. Extra: even better! class User < ActiveRecord::Base after_commit { raise

    StandardError } end User.create! #=> ActiveRecord::RecordNotSaved 17/18 ‛ PR #18325 User.create! # DEPRECATION WARNING: Currently, Active Record suppresses errors raised within after_commit. You can opt into the new behavior by setting... #=> StandardError