I'm following Iteration 13 of Agile Web development, for User login.
I create a migration to add 2 columns to my User model : hashed_password and salt.
- Creation of Users works
- login fails, due to this error undefined method 'hashed_password' in method 'authenticate'
The problem is that :
- In rails console, I can fetch User.first.hashed_password, what seems OK :-)
- I outputted the User that I fecth, and it is NOT nil
- I tried to output user.hashed_password as I did in the rails console, but that throws always the same error :
NoMethodError (undefined method hashed_password' for #<ActiveRecord::Relation:0x00000003e6c3c0>):
app/models/user.rb:21:in
authenticate'
app/controllers/sessions_controller.rb:6:in `create'
This is my User model :
require 'digest/sha2'
class User < ActiveRecord::Base
has_and_belongs_to_many :products
has_many :created_products, :class_name => "Product", :foreign_key => :product_id
default_scope :order => "username ASC"
# Attributs pour le login (Livre)
validates :username, :presence => true, :uniquenes开发者_运维问答s => true
validates :password, :confirmation => true
attr_accessor :password_confirmation
attr_reader :password
validate :password_must_be_present
def User.authenticate(name, password)
logger.debug "---------- Beginning of Authenticate"
if user = User.where(:username => name)
logger.debug "utilisateur = #{user.inspect}" # THIS IS OK AND NOT NIL
logger.debug "utilisateur hashed PW = #{user.hashed_password}" # ERROR
if user.hashed_password == encrypt_password(password, user.salt)
return user
end
end
end
def User.encrypt_password(password, salt)
Digest::SHA2.hexdigest(password + "wibble" + salt)
end
def password=(password)
@password = password
if (password.present?)
generate_salt
self.hashed_password = self.class.encrypt_password(password, salt)
end
end
private
def password_must_be_present
errors.add(:password, "Mot de passe manquant") unless hashed_password.present?
end
def generate_salt
self.salt = self.object_id.to_s + rand.to_s
end
end
User.where(:username => name) is returning an ActiveRecord::Relation object (hence the error message you are seeing). Try changing your if statement to:
if user = User.where(:username => name).first
That will set take the first matching user, which will be an instance of User and so will have a hashed_password field. If no user matches, you'll get nil.
put this in your model
private
def self.hash_password(password)
Digest::SHA1.hexdigest(password)
end
精彩评论