Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails -- before_save not working?

I am following Michael Hartl's RoR tutorial, and it is covering the basics of password encryption. This is the User model as it currently stands:

class User < ActiveRecord::Base
    attr_accessor :password

    attr_accessible :name, :email,: password, :password_confirmation

    email_regex = /^[A-Za-z0-9._+-]+@[A-Za-z0-9._-]+\.[A-Za-z0-9._-]+[A-Za-z]$/
                                              #tests for valid email addresses.

    validates :name, :presence => true,
                     :length => {:maximum => 50}
    validates :email, :presence => true,
                      :format => {:with => email_regex},
                      :uniqueness => {:case_sensitive => false}
    validates :password, :presence => true,
                         :length => {:maximum => 20, :minimum => 6},
                         :confirmation => true

    before_save :encrypt_password

    private

        def encrypt_password
            @encrypted_password = encrypt(password)
        end

        def encrypt(string)
            string
        end
end

(Obviously this isn't doing any encrypting because the encrypt method isn't really implemented but that's not my question)

I then wrote the following Spec (according to the tutorial):

require 'spec_helper'

describe User do

    before(:each) do
        @attr = { :name => "Example User", :email => "[email protected]",
                  :password => "abc123", :password_confirmation => "abc123"}
    end

    describe "password encryption" do

        before(:each) do
            @user = User.create!(@attr) # we are going to need a valid user in order
                                        # for these tests to run.
        end

        it "should have an encrypted password attribute" do
            @user.should respond_to(:encrypted_password)
        end

        it "should set the encrypted password upon user creation" do
            @user.encrypted_password.should_not be_blank
        end

    end
end

The first of these tests passes, but since @user.encrypted_password is nil, the second test fails. But I don't understand why it's nil since the encrypt_password method should be being called by before_save. I know I must be missing something -- can someone please explain?

like image 643
Kvass Avatar asked Jun 13 '11 01:06

Kvass


1 Answers

The encrypt_password method is incorrect, it should read:

def encrypt_password
  self.encrypted_password = encrypt(password)
end

Note the use of self, which will properly set the attribute for the user object rather than creating an instance variable which is forgotten.

like image 134
nmunson Avatar answered Sep 29 '22 11:09

nmunson