title: RoR tutorial, chapter 7 - rspec tests failing: NoMethodError 'encrypt'
body: <p>Well I've searched all over the place and it seems that nobody else has the issue with this 'encrypt' method causing their tests to fail, though it seems plenty others have had some difficulty with chapter 7.  Without further adieu,</p>
  
  <p>Here's the link to Hartl's <a href="http://ruby.railstutorial.org/chapters/modeling-and-viewing-users-two#sec%3aimplementing_has_password" rel="nofollow">Chapter 7</a></p>
  
  <p>My code in the user model file, and the corresponding spec file, appear to be completely exact to what he has written and I still cannot get the tests to pass.  The errors?</p>
  
  <pre><code>Failures:
  1) User should create a new instance given valid attributes
  Failure/Error: User.Create!(@attr)
  NoMethodError: undefined method 'encrypt' for #&lt;User:asdf&gt;
  #./app/models/user.rb:22:in 'has_password?'
  #./app/models/user.rb:28:in 'encrypt_password'
  #./spec/models/user_spec.rb:15:in 'block (2 levels) in &lt;top (required)&gt;'
  
  2) User should not allow duplicate email addresses
  Failure/Error: User.Create!(@attr)
  NoMethodError: undefined method 'encrypt' for #&lt;User:asdf&gt;
  #./app/models/user.rb:22:in 'has_password?'
  #./app/models/user.rb:28:in 'encrypt_password'
  #./spec/models/user_spec.rb:15:in 'block (2 levels) in &lt;top (required)&gt;'
  
  3) User should reject email addresses identical up to case
  Failure/Error: User.Create!(@attr)
  NoMethodError: undefined method 'encrypt' for #&lt;User:asdf&gt;
  #./app/models/user.rb:22:in 'has_password?'
  #./app/models/user.rb:28:in 'encrypt_password'
  #./spec/models/user_spec.rb:15:in 'block (2 levels) in &lt;top (required)&gt;'
  
  ...
  
  7) User has_password? method should be false if passwords do not match
  Failure/Error: User.Create!(@attr)
  NoMethodError: undefined method 'encrypt' for #&lt;User:asdf&gt;
  #./app/models/user.rb:22:in 'has_password?'
  #./app/models/user.rb:28:in 'encrypt_password'
  #./spec/models/user_spec.rb:15:in 'block (3 levels) in &lt;top (required)&gt;'
  </code></pre>
  
  <p>so i'm getting the same error messages for each test and I am going nuts trying to find out why!</p>
  
  <p>Here's my user.rb:</p>
  
  <pre><code>require 'digest'
  class User &lt; ActiveRecord::Base
    attr_accessor :password
    attr_accessible :name, :email, :password, :password_confirmation
  
    email_regex = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  
    validates :name,  :presence =&gt; true,
                      :length   =&gt; { :maximum =&gt; 50 }
    validates :email, :presence =&gt; true,
                      :format   =&gt; { :with =&gt; email_regex },
                      :uniqueness =&gt; { :case_sensitive =&gt; false }
  #automatically create the virtual attribute for 'password_confirmation'
    validates :password, :presence =&gt; true,
                         :confirmation =&gt; true,
                         :length =&gt; { :within =&gt; 6..40 }
  
    before_save :encrypt_password
  
    #returns true if the users password matches the submitted one
    def has_password?(submitted_password)
    encrypted_password == encrypt(submitted_password)
    end
  
    private
  
    def encrypt_password
      self.salt = make_salt unless has_password?(password)
      self.encrypted_password = encrypt(password)
    end
  
    def encrypt_string
      secure_hash("#{salt}--#{string}")
    end
  
    def make_salt
      secure_hash("#{Time.now.utc}--#{password}")
    end
  
    def secure_hash(string)
      Digest::SHA2.hexdigest(string)
    end
  end
  </code></pre>
  
  <p>and my user_spec.rb file:</p>
  
  <pre><code>require 'spec_helper'
  require 'digest'
  
  describe User do
    before(:each) do
  @attr = {
    :name =&gt; "User Name",
    :email =&gt; "example@email.com",
    :password =&gt; "password",
    :password_confirmation =&gt; "password"
  }
    end
  
    it "should create a new instance given valid attributes" do
  User.create!(@attr)
    end
  
    it "should require a name" do
  no_name_user = User.new(@attr.merge(:name =&gt; ""))
  no_name_user.should_not be_valid
    end
  
    it "should require an email" do
  no_email_user = User.new(@attr.merge(:email =&gt; ""))
  no_email_user.should_not be_valid
    end
  
    it "should reject names that are too long" do
  long_name = "a" * 51
  long_name_user = User.new(@attr.merge(:name =&gt; long_name))
  long_name_user.should_not be_valid
    end
  
    it "should accept valid email addresses" do
  addresses = %w[user@foo.com THE_USER@foo.bar.org first.last@foo.jp]
  addresses.each do |address|
    valid_email_user = User.new(@attr.merge(:email =&gt; address))
    valid_email_user.should be_valid
  end
    end
  
    it "should reject invalid email addresses" do
  addresses = %w[user@foo,com user_at_foo.org example.user@foo.]
      addresses.each do |address|
    invalid_email_user = User.new(@attr.merge(:email =&gt; address))
    invalid_email_user.should_not be_valid
      end
    end
  
    it "should not allow duplicate email addresses" do 
  User.create!(@attr)
  user_with_duplicate_email = User.new(@attr)
  user_with_duplicate_email.should_not be_valid
    end
  
    it "should reject email addresses identical up to case" do
  upcased_email = @attr[:email].upcase
  User.create!(@attr.merge(:email =&gt; upcased_email))
  user_with_duplicate_email = User.new(@attr)
  user_with_duplicate_email.should_not be_valid
    end
  
    describe "password validations" do
  it "should require a password" do
    User.new(@attr.merge(:password =&gt; "", :password_confirmation =&gt; ""))
    should_not be_valid
  end
  
  it "should require password to match the password confirmation" do
    User.new(@attr.merge(:password_confirmation =&gt; "invalid"))
    should_not be_valid
  end
  
  it "should reject short passwords" do
    short = "a" * 5
    hash = @attr.merge(:password =&gt; short, :password_confirmation =&gt; short)
    User.new(hash).should_not be_valid
  end
  
  it "should reject long passwords" do
    long = "a" * 41
    hash = @attr.merge(:password =&gt; long, :password_confirmation =&gt; long)
    User.new(hash).should_not be_valid
      end
    end
  
    describe "password encryption" do
  
  before(:each) do
    @user = User.create!(@attr)
  end
  
  it "should have an encrypted password attribute" do
    @user.should respond_to(:encrypted_password)
  end
  
  it "should not allow a blank encrypted password" do
    @user.encrypted_password.should_not be_blank
      end
    end
  
    describe "has_password? method" do
  
      before(:each) do
    @attr = User.create!(@attr)
      end
  
    it "should be true if the passwords match" do
      @user.has_password?(@attr[:password]).should be_true
    end
  
    it "should be false if the passwords don't match" do
          @user.has_password?("invalid").should be_false
        end 
    end
  end
  </code></pre>
  
  <p>Any help would be greatly appreciated.  I've poured over other's problems, my code, and changed various aspects to try and get the tests to work, all to no avail.  I hope it's not something really stupid I'm still not seeing.</p>