No commit activity in last 3 years
No release in over 3 years
A replacement for ActiveRecord::Base#save! for Ruby on Rails
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Runtime

> 2.0.0
 Project 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.
  
  == Java Exceptions
  
    Java is the first programming language I used in production it and gave me the
    idea for this plugin.
  
    The parallel idea in the Java universe is outlined in Item 40 of
    Joshua Bloch's book Effective Java: "Use checked exceptions for recoverable
    conditions and run-time exceptions for programming errors".
    
    Java checked exceptions can be caught and handled gracefully and the program can
    continue.  Java run-time (or unchecked) exceptions should not be caught by the
    Java VM and allowed to bubble to the top of the call stack, where they will
    make the program fail.