Rails - before_save不工作?

时间:2011-06-13 01:20:49

标签: ruby ruby-on-rails-3 callback

我正在关注Michael Hartl的RoR教程,它涵盖了密码加密的基础知识。这是目前的用户模型:

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

(显然这没有进行任何加密,因为加密方法并没有真正实现,但这不是我的问题)

然后我编写了以下规范(根据教程):

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

第一次测试通过,但由于@user.encrypted_password为零,第二次测试失败。但是我不明白为什么它是零,因为encrypt_password方法应该调用before_save方法。我知道我必须遗漏一些东西 - 请有人解释一下吗?

2 个答案:

答案 0 :(得分:20)

encrypt_password方法不正确,应该是:

def encrypt_password
  self.encrypted_password = encrypt(password)
end

注意self的使用,它将正确设置用户对象的属性,而不是创建一个被遗忘的实例变量。

答案 1 :(得分:0)

这是一个老问题,这更像是一个评论,但我还没有足够的声誉来发表评论。只是想将这个问题链接起来,因为它涉及self

的一些可靠细节

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