public
Description: A replacement for ActiveRecord::Base#save! for Ruby on Rails
Homepage:
Clone URL: git://github.com/ryanlowe/save_or_raise.git
ryanlowe (author)
Mon May 26 09:03:16 -0700 2008
commit  2fe328c4da94efdcd0ac8e2ffb956bf718437c5a
tree    15e92782191d807c36844628a2030dd32e4fbccd
parent  4d5db3c25157177e193445c07211b8b4dfcda4b7
name age message
file .gitignore Loading commit data...
file CHANGELOG
file MIT-LICENSE Sun May 25 16:54:55 -0700 2008 add the MIT license [ryanlowe]
file README
file Rakefile
file TODO
directory app/
directory config/
directory db/
file init.rb
directory lib/ Sun May 25 16:17:33 -0700 2008 finished first rough implementation [ryanlowe]
file save_or_raise.gemspec
directory test/
README
= save_or_raise

  This plugin includes one new method for ActiveRecord::Base called
  save_or_raise which does almost the same thing as ActiveRecord::Base#save!
  but in a more readable way.
  
  == Installation
  
    gem install ryanlowe-save_or_raise --source http://gems.github.com/
  
  == save vs save!
  
    The ActiveRecord::Base save method returns true if the model save
    is successful and false if it is not successful.  The save! method
    returns true if the model save is successful and raises an exception
    if it is not successful.
  
  == utility
  
    The save method is useful for control flow in cases where a failed
    save can be handled gracefully:
  
      if model.save
        ...
      else
        ...
      end
    
    Sometimes the control flow - often within or called by a controller -
    cannot handle an unsuccessful save gracefully.  The programmer's
    choices are:
  
      1. Do not branch on the save call and ignore failures.
      2. Throw an exception:
    
           raise "Save failed!" unless model.save
      
      3. Call save! which does the same as 2
      
    The exception thrown by 2 and 3 will generate a 500 HTTP code for the user
    in production but it will also notify an admin by email when used in combination
    with a plugin like exception_notification.  Result of choice 1 is possible data
    corruption and invalid application state.
    
    So doing 1 is just not a good idea!
  
  == The problem with save!
  
    ...is that is poorly named.  Ruby methods that end with an exclamation
    point are a signal that they change the object they operate on.
  
    An irb example:
  
      >> a = " hello "
      => " hello "
      >> b = a.strip!
      => "hello"
      >> a
      => "hello"
      
      The method strip! returns the result to b but also changes a.
    
    The save! method does not change the ActiveRecord model it is called on any more
    than the save method does.  Also the name save! does not hint that it throws an
    exception in the failure case.
  
    Both of these things make the code that uses save! less readable.
  
  == Solution
  
    This plugin implements a new ActiveRecord#Base method
    
      save_or_raise(raiseable = ActiveRecord::RecordNotSaved)
  
    which can be used the following ways:
    
      model.save_or_raise                            # instead of model.save!
      model.save_or_raise "Unrecoverable save error" # raises RuntimeError with this message on failure
      model.save_or_raise CustomException            # raises CustomException on failure
      
    In all three cases the raised exception presents a 500 HTTP error to
    the user in production if the save fails.
    
    The save! method remains untouched and can still be used.