Rails: Raising Model Exceptions, Rescuing in Controller

Consider this bit of code:


## News model
class News < ActiveRecord::Base
  before_create :validate_date
  def validate_date
    raise "Invalid creation date..."  if created_on > Time.now
  end
end

##News controller
class Publish::NewsController < Publish::BaseController
  def create
    begin
      @news = News.new(params[:news])
    rescue
      flash[:notice] = "Invalid creation date"
      render :action => 'new'
    end
    if @news.save
      flash[:notice] = 'News was successfully created.'
      redirect_to :action => 'list'
    else
      render :action => 'new'
    end
  end
end

… I’m well off here, I know. When date validation fails I see a RuntimeError in the controller and the string specified in the News.validate_date method.

Can someone explain how to properly deal with raising exceptions in the model and rescuing in the controller? Much appreciated…

You’re taking the right approach to rescuing exceptions however you are taking the wrong approach to your validations by using exceptions.

Rails already has a built-in mechanism for dealing with whether or not a record is a valid so instead of raising an exception what you should be doing is adding your error to the errors array. This will make @yourobject.valid? and @yourobject.save return false.

Theres also no need to set the validation method as a callback as Rails already has validation hooks you can tie into. So you should do something like this:


class News < ActiveRecord::Base
  protected
    def validate
      self.errors.add(:created_on, "is invalid") if self.created_on > Time.now
    end
end

class Publish::NewsController < Publish::BaseController
  def create
    @news = News.new(params[:news])
    if @news.save
      flash[:notice] = 'News was successfully created.'
      redirect_to :action => 'list'
    else
      flash[:error] = @news.errors
      render :action => 'new'
    end
  end
end

More information on Rails errors and validations:

http://api.rubyonrails.org/classes/ActiveRecord/Errors.html

Cheers thanks for that, Luke.