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

RoR ActiveRecord Callbacks

RoR ActiveRecord Callbacks

Primer Presentation on AR Callbacks given on 6/12/2012 by Allen Maxwell at the Utah Valley Ruby Users Group Meeting at MoneyDesktop

Allen Maxwell

June 13, 2012
Tweet

Other Decks in Programming

Transcript

  1. First  Things  First:   Come  to  Agile  Roots  2012!  

    l  10  %  discount  before  6/12/2012   l  Great  speakers  and  topics!   l  Mike  Moore   l  Pat  Maddox   l  Corey  Haines   l  And  more….   l  See  all  the  info:      hLp://www.agileroots.com    
  2. I’m  sure  there’s  a  beLer  way   I’m  not  lazy

     enough  to  be  a  rails   developer…                                    -­‐-­‐  Dave  Moulton   But  I’m  lazy  enough  to  have  cut  and  pasted  a   lot  of  this  material  from  the  great  oracle  (i.e.   Google)  
  3. What’s  a  CallBack?   l  by  definiNon  (from:  rubyonrails.org):  

    l  Callbacks  are  hooks  into  the  life  cycle  of  an  AcNve  Record  object  that  allow   you  to  trigger  logic  before  or  a[er  an  alteraNon  of  the  object  state.   l   This  can  be  used  to  make  sure  that  associated  and  dependent  objects  are   deleted  when  destroy  is  called  (by  overwriNng  before_destroy)   l  or  to  massage  aLributes  before  they're  validated  (by  overwriNng   before_validaNon)  
  4. Of  Topic:  (slightly)   l  AcNveRecord  inherits  from  AcNveModel.  

    l  AcNveModel  encapsulates  the  non-­‐database  related  behavior  of  AcNveRecord   (like  callbacks  and  validaNons)  which  allow  you  to  create  classes  (technically   models)  that  are  not  connected  to  the  database.   l  Ryan  Bates  has  a  RailsCast  that  goes  into  this.    It’s  outside  the  scope  of  this  primer   but  it’s  preLy  cool  stuff…  
  5. Available  Callbacks  -­‐  CreaNng  an  Object:   l  Before_validaNon  

    l  A[er_validaNon   l  Before_save   l  A[er_save   l  Before_create   l  Around_create   l  A[er_create  
  6. Available  Callbacks  -­‐  UpdaNng  an  Object:   l  Before_validaNon  

    l  A[er_validaNon   l  Before_save   l  A[er_save   l  Before_create   l  Around_create   l  A[er_create  
  7. Other  Useful  Callbacks     :a2er_ini6alize  is  called  right  a[er

     an  object  has  been  unmarshalled  from  the  database.   This  allows  you  to  do  any  other  custom  iniNalizaNon  you  want.  Instead  of  defining  an   iniNalize  method  on  a  model,  use  this  instead.     :a2er_find  hasn't  been  useful  in  my  experience.  I  haven't  run  into  a  case  where  I  wanted   to  manipulate  documents  a[er  a  find  acNon.  It  could  potenNally  be  useful  for  metrics  and   profiling.     :a2er_touch.  AcNveRecord  allows  you  to  touch  a  record  or  its  associaNon  to  refresh  its   updated_at  aLribute.  I've  found  this  callback  useful  to  triggering  noNficaNons  to  users   a[er  a  model  has  been  marked  as  updated,  but  not  actually  changed.    
  8. What  are  callbacks  good  for?   l  Great  to  ensure

     values  and  state  during  db  operaNons   l  Forcing  case  on  values  saved     l  Secng  default  values   l  EncrypNng  passwords  etc   l  ValidaNons   l  Some  of  which  is  available  using  db  defaults  etc.  –  probably  beLer  to  do  it   that  way…  
  9. Around  Callbacks:   For  save,  create,  update,  and  destroy,  Rails

     also  gives  extra  helper  methods  for  defining   both  a  before  and  a[er  save  callback  at  the  same  Nme.     For  example,  suppose  you  wanted  to  trigger  your  own  custom  callback  while  a  model   was  being  destroyed.  You  can  do  so  by  defining  and  triggering  your  own  callback  as   follows:   class  SomeModel  <  AcNveRecord::Base      define_callbacks  :custom_callback        around_destroy  :around_callback        def  around_callback          run_callbacks  :custom_callback  do              yield    #  runs  the  actual  destroy  here          end      end   end  
  10. Something  to  watch  out  for:   l  Recursion…  be  sure

     to  boLom  them  out!   l  Return  false  –  error  messages  not  available:  tough  to  debug   l  If  you  use  create!  It  will  fail  if  the  callback  returns  false   l  If  callback  operaNons  take  a  long  Nme,  use  delayed  jobs  or  some  other  way   to  pull  the  operaNon  out  of  the  thread.     l  hLps://github.com/tobi/delayed_job   l  Parent  callbacks  are  called  before  child  callbacks  
  11. More  advanced  stuff…     l  hLp://intridea.com/posts/define-­‐custom-­‐callbacks-­‐for-­‐acNverecord-­‐and-­‐ more   l 

    Callbacks  are  abstracted  into  AcNveSupport::Callbacks  so  you  can  integrate   callbacks  into  regular  ruby  classes!   #  Look  Ma,  I'm  just  a  normal  ruby  class!   class  Group      include  AcNveSupport::Callbacks      define_callbacks  :user_added        def  iniNalize(opts  =  {})          @users  =  []      end        #  Whenever  we  add  a  new  user  to  our  array,  we  wrap  the  code      #  with  `run_callbacks`.  This  will  run  any  defined  callbacks      #  in  order.      def  add_user(u)          run_callbacks  :user_added  do              @users  <<  u          end      end   end  
  12. :a2er_commit  is  an  interesNng  and  tricky  callback.  Whenever  AcNveRecord  wants

     to  make   a  change  to  a  record  (create,  update,  destroy),  it  wraps  it  around  a  transacNon.   a[er_commit  is  called  a[er  you're  posiNve  that  something  has  been  wriLen  out  to  the   database.  Because  it  is  also  called  for  destroys,  it  makes  sense  to  scope  the  callback  if  you   intend  to  use  it  only  for  saves.  Be  warned  that  a[er_commit  can  be  tricky  to  use  if  you're   using  nested  transacNons.         :a2er_rollback  is  the  complement  to  a[er_commit.    Could  be  used  for  doing  manual   cleanup  a[er  a  failed  transacNon.