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 => "[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?

2 Answers 2

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.

1
  • 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: stackoverflow.com/questions/6327174/rails-self-vs :) another opportunity to earn points.
    – Kvass
    Commented Jun 13, 2011 at 6: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?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.