chapter 7 authenticate method returns nil and it's not a typo

  • Question
  • Updated 2 years ago
There's a similar question on this forum, but different than that topic, there's no typo in my code, and i can't figure out why the authenticate method returns nil.

many thanks if anyone can help me.

class User < 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 => true,
:length => { :maximum => 50 }
validates :email, :presence => true,
:format => { :with => email_regex },
:uniqueness => { :case_sensitive => false }
validates :password, :presence => true,
:confirmation => true,
:length => { :within => 6..40 }
before_save :encrypted_password

def has_password?(submitted_password)
encrypted_password == encrypt(submitted_password)
end

def User.authenticate(email, submitted_password)
user = find_by_email(email)
return nil if user.nil?
return user if user.has_password?(submitted_password)
end

private
def encrypted_password
self.salt = make_salt if new_record?
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
Photo of xuan.aiX

xuan.ai

  • 4 Posts
  • 0 Likes

Posted 3 years ago

  • 1
Photo of EricM

EricM

  • 9 Posts
  • 0 Likes
Apparently I'm not using the same book as you since your code is very different from what I'm getting in the current online version, but lets try to figure it out anyway!

When does the problem occur? All the time? Only in the tests?
Photo of xuan.aiX

xuan.ai

  • 4 Posts
  • 0 Likes
I found this problem by running the test, and it occurs all the time. i tried it in the rails console and the result is nil.
Photo of xuan.aiX

xuan.ai

  • 4 Posts
  • 0 Likes
And there's 1 thing drive me crazy:

1. enter the rails console
2. create a user with a password, like 123456 and save it.
3. Try the User.last.has_password?(123456), it returns true,
4. quit the rails console,
5. enter the rails console again,
6. repeat step 3, and it returns false.

how come?
Photo of EricM

EricM

  • 9 Posts
  • 0 Likes
Not sure why your console doesn't seem to be saving the data. Sounds like it is rolling back your transactions when you quit like it does it the test environment. It works for me. I removed some of the output to make it shorter:

sample_app eric_mccullough$ bundle exec rails c
Loading development environment (Rails 3.2.2)
[1] pry(main)> User.create(:email => 'em@em.com', :password => '123456', :name => 'em', :password_confirmation => '123456')

(0.1ms) begin transaction
User Exists (0.3ms) SELECT 1 FROM "users" WHERE LOWER("users"."email") = LOWER('em@em.com') LIMIT 1
Binary data inserted for `string` type on column `password_digest`

SQL (4.2ms) INSERT INTO "users" ("admin", "created_at", "email", "name", "password_digest", "remember_token", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?) [["admin", false], ["created_at", Wed, 11 Apr 2012 12:18:19 UTC +00:00], ["email", "em@em.com"], ["name", "em"], ["password_digest", "$2a$10$1aiI3KeKqkraMUXtEmXSjuKGgthjZFvofBxa8ryHKuNHJRbcjBHLC"], ["remember_token", "ZpCbWXxeMQJimgOftasjnw"], ["updated_at", Wed, 11 Apr 2012 12:18:19 UTC +00:00]]

(1.2ms) commit transaction

=> [created record is here...]

[2] pry(main)> User.last.authenticate('123456') User Load (0.2ms) SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT 1
=> [valid user record returned here...]

[3] pry(main)> quit

sample_app eric_mccullough$ bundle exec rails c
Loading development environment (Rails 3.2.2)

[1] pry(main)> User.last.authenticate('123456')
User Load (0.1ms) SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT 1

=> [valid user record returned here...]

[2] pry(main)> quit

What version of railstutorial are you using?
Photo of EricM

EricM

  • 9 Posts
  • 0 Likes
Back to the original problem. Just to make sure I understand, the application doesn't work when you run rails server and access it through your browser?

I've had tests fail, but the application work, just because I didn't make the test correctly.
Photo of xuan.aiX

xuan.ai

  • 4 Posts
  • 0 Likes
Hi EricM, I've just found it's a typo issue.

As "before_save :encrypted_password" should be "before_save :encrypt_password", and the method definition "def encrypted_password" should be "def encrypt_password".

After change the code, the application works and the test pass.

It's my bad, sorry for bothering you and thank you for your help.
Next time i'll use the diff tool to compare my code with the original source code first.

by the way, I've finished following the tutorial and deployed my clone to heroku, you can visit it here: http://esnake0-twt.heroku.com/

I'll read the book again and refer the book "Agile Web Development with Rails", try to understand what I've done.

I'm a total beginner in web development, thank you for your patient.
Photo of EricM

EricM

  • 9 Posts
  • 0 Likes
There is a new version of the tutorial that uses new authentication that is much easier to use.

Good luck!
Photo of John Katsnelson

John Katsnelson

  • 1 Post
  • 0 Likes
Yay for this post! I made a very similar error and was able to fix it by reading this.