8

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 => "user@example.com",
                  :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?

Kvass
  • 8,294
  • 12
  • 65
  • 108

2 Answers2

20

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.

nmunson
  • 902
  • 8
  • 11
  • 1
    I gave you the "accepted answer" because this resolved my issue, but I am still having conceptual issues with this so if you would like to resolve those my follow-up question is here: http://stackoverflow.com/questions/6327174/rails-self-vs :) another opportunity to earn points. – Kvass Jun 13 '11 at 06:14
0

This is an old question and this is more of a comment but I don't have enough reputation to comment yet. Just wanted to link this question too as it goes into some solid detail about self.

Why isn't self always needed in ruby / rails / activerecord?

Community
  • 1
  • 1
Andrew Haust
  • 356
  • 2
  • 12