yeah its ok

Jared Carroll

Here’s a SessionController#create action that supports the classic ‘remember me’ functionality of login forms.

def create
  @user = User.authenticate params[:email], params[:password]
  if @user.nil?
    flash.now[:notice] = 'Invalid email and/or passowrd'
    render :action => :new
  else
    if remember_me?
      @user.remember_me!
      cookies[:token] = {
        :value => @user.token,
        :expires => 1.month.from_now
      }
    end
    session[:user_id] = @user.id
    redirect_to home_url
  end
end

Now everything does what you expect it to do, I’ve excluded User#authenticate and SessionController#remember_me? to keep this short plus they’re obvious.

Let’s look at User#remember_me! though.

def remember_me!
  update_attribute :token, "#{email}-#{Time.now}".to_sha1
end

There I’m using ActiveRecord::Base#update_attribute to update a token attribute on a user to a hash of their email and the current time (this is done to make impersonating sessions less likely).

Now ActiveRecord::Base#update_attribute is never going to fail because of failed validation because a user’s validations are not run during it. This feels bad at first but what error message would you show the user in this circumstance? Would this update ever fail anyway? I mean if it failed for some other reason, maybe losing your connection to the database, then I’d want the exception to bubble up and the user to see the 500 page because that is an exceptional circumstance and something I don’t expect.

These situations of saving an object without validating it are rare but sometimes justified. I think Rails agrees because the only method thats documented to save an object without validating it is ActiveRecord::Base#update_attribute and this method only allows you to update 1 attribute at a time. There are other undocumented haxx out there that allow you to update more than 1 attribute at a time without validation but they’re undocumented because you shouldn’t be using them. One attribute without validation is fine but a whole object without validation is unacceptable.