In Michael Hartl's Ruby on Rails Tutorial, ch 7.2.3, rspec is returns the following errors:
Failures:
1) User has_password? method should be true if the passwords match
Failure/Error: #user.has_password?(#attr[:password].should be_true)
NoMethodError:
undefined method `has_password?' for nil:NilClass
# ./spec/models/user_spec.rb:132:in `block (3 levels) in <top (required)>'
2) User has_password? method should be false if the passwords don't match
Failure/Error: #user.has_password?("invalid").should be_false
NoMethodError:
undefined method `has_password?' for nil:NilClass
# ./spec/models/user_spec.rb:136:in `block (3 levels) in <top (required)>'
Finished in 0.23931 seconds
18 examples, 2 failures
Failed examples:
rspec ./spec/models/user_spec.rb:131 # User has_password? method should be true if the passwords match
rspec ./spec/models/user_spec.rb:135 # User has_password? method should be false if the passwords don't match
In the console I'm also getting an undefined local variable error on 'password confirmation'
I've thoroughly checked my code and can't find the discrepancy but I'm obviously doing it wrong.
here's my users model:
require 'digest'
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 }
# Automatically create the virtual attribute 'password_confirmation'.
validates :password, :presence => true,
:confirmation => true,
:length => { :within => 6..40 }
before_save :encrypt_password
def has_password?(submitted_password)
self.encrypted_password == encrypt(submitted_password)
end
private
def encrypt_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
Make sure this bit is in your spec, sounds like it's missing
before(:each) do
#user = User.create!(#attr)
end
Related
I am working my through Hartl's Rails Tutorial. I have gotten up to chapter 7, but one of my RSpec test cases is failing, specifically the one dealing with passwords that do not match:
describe "has_password? method" do
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
Output from Terminal:
Failures:
1) User password encryption has_password? method should be false if the passwords don't match
Failure/Error: #user.has_password?("invalid").should be_false
expected "273725daa81e74764ea1e941a0789da7d580656cd321c64e39d1389f6a7e14d9" to be false
# ./spec/models/user_spec.rb:111
Here is my /user.rb code:
require 'digest'
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 :encrypt_password
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
I can't seem to figure out what is wrong for the life of me. I appreciate the help!
In your has_password? method
encrypted_password = encrypt(submitted_password) needs to read:
encrypted_password == encrypt(submitted_password)
I am learning ruby on rails. I am creating a model for storing User information and when calling rake db:seed then I am getting the following error , any idea what I am missing ?
rake db:seed
require 'digest'
class User < ActiveRecord::Base
attr_accessor :password
attr_accessible :email, :password
validates :email, :uniqueness => true,
:length => {:within => 5..50},
:presence => true
validates :password, :confirmation => true, :length => { :within => 4..20 }, :presence => true, :if => :password_required?
has_one :profile
has_many :articles, :order => 'published_at DESC, title ASC',
:dependent => :nullify
has_many :replies, :through => :articles, :source => :comments
before_save :encrypt_new_password
def self.authenticate(email, password)
user = find_by_email(email)
return user if user && user.authenticated?(password)
end
def authenticated?(password)
self.hashed_password == encrypt(password)
end
def encrypt_new_password
return if password.blank?
self.hashed_password = encrypt(password)
end
def password_required?
hashed_password.blank? || password.present?
end
def encrypt(string)
Digest::SHA2.hexdigest(string)
end
end
Can't mass-assign protected attributes: password_confrimation
c:/Ruby192/lib/ruby/gems/1.9.1/gems/activemodel-3.2.3/lib/active_model/mass_assignment_security/sanitizer.rb:48:in `process_removed_attributes'
c:/Ruby192/lib/ruby/gems/1.9.1/gems/activemodel-3.2.3/lib/active_model/mass_assignment_security/sanitizer.rb:20:in `debug_protected_attribute_removal'
c:/Ruby192/lib/ruby/gems/1.9.1/gems/activemodel-3.2.3/lib/active_model/mass_assignment_security/sanitizer.rb:12:in `sanitize'
c:/Ruby192/lib/ruby/gems/1.9.1/gems/activemodel-3.2.3/lib/active_model/mass_assignment_security.rb:230:in `sanitize_for_mass_assignment'
c:/Ruby192/lib/ruby/gems/1.9.1/gems/activerecord-3.2.3/lib/active_record/attribute_assignment.rb:75:in `assign_attributes'
c:/Ruby192/lib/ruby/gems/1.9.1/gems/activerecord-3.2.3/lib/active_record/base.rb:498:in `initialize'
c:/Ruby192/lib/ruby/gems/1.9.1/gems/activerecord-3.2.3/lib/active_record/persistence.rb:44:in `new'
c:/Ruby192/lib/ruby/gems/1.9.1/gems/activerecord-3.2.3/lib/active_record/persistence.rb:44:in `create'
C:/Users/huzaifa.gain/My Documents/Aptana Studio 3 Workspace/blog/db/seeds.rb:6:in `<top (required)>'
c:/Ruby192/lib/ruby/gems/1.9.1/gems/activesupport-3.2.3/lib/active_support/dependencies.rb:245:in `load'
c:/Ruby192/lib/ruby/gems/1.9.1/gems/activesupport-3.2.3/lib/active_support/dependencies.rb:245:in `block in load'
c:/Ruby192/lib/ruby/gems/1.9.1/gems/activesupport-3.2.3/lib/active_support/dependencies.rb:23
You have to add password_confirmation to attr_accessible
class User < ActiveRecord::Base
attr_accessor :password
attr_accessible :email, :password, :password_confirmation
and it should work.
As logs says "Can't mass-assign protected attributes: password_confrimation"
you need to add password_confrimation to User Model
attr_accessible :password_confrimation
I just wrote a test for testing if a new user creation also consists of an admin setting. Here is the test:
describe User do
before(:each) do
#attr = {
:name => "Example User",
:email => "user#example.com",
:admin => "f"
}
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 => ""))
no_name_user.should_not be_valid
end
it "should require an email" do
no_email_user = User.new(#attr.merge(:email => ""))
no_email_user.should_not be_valid
end
it "should require an admin setting" do
no_admin_user = User.new(#attr.merge(:admin => ""))
no_admin_user.should_not be_valid
end
end
Then, in my User model I have:
class User < ActiveRecord::Base
attr_accessible :name, :email, :admin
has_many :ownerships
has_many :projects, :through => :ownerships
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 :admin, :presence => true
end
I clearly created a new user with an admin setting, so why is it saying it's false? I created the migration for the admin setting as admin:boolean. Did I do something wrong?
Here's the error:
Failures:
1) User should create a new instance given valid attributes
Failure/Error: User.create!(#attr)
ActiveRecord::RecordInvalid:
Validation failed: Admin can't be blank
# ./spec/models/user_spec.rb:14:in `block (2 levels) in <top (required)>'
Oddly enough, when I comment out validates :admin, :presence => true, the test creates the user correctly but fails on "User should require an admin setting"
EDIT: When I change the #attr :admin value to "t" it works! Why doesn't it work when the value is false?
From the rails guides:
Since false.blank? is true, if you want to validate the presence of a
boolean field you should use validates :field_name, :inclusion => {
:in => [true, false] }.
Basically, it looks like ActiveRecord is converting your "f" to false before the validation, and then it runs false.blank? and returns true (meaning that the field is NOT present), causing the validation to fail. So, to fix it in your case, change your validation:
validates :admin, :inclusion => { :in => [true, false] }
Seems a little hacky to me... hopefully the Rails developers will reconsider this in a future release.
Good day! I'm practising materials from "Ruby on Rails Tutorial" by Michael Hartle.
Below is the failure message I received, even though the "expected" and "got" seems to match. Would you please give me some suggestion to see how I should approach this issue?
Thank you so much!
Below is the implementation code:
class User < ActiveRecord::Base
attr_accessor :password
attr_accessible :name, :emp_id, :dept_id, :password, :password_confirmation
validates :emp_id, :presence => true
validates :name, :presence => true,
:length => { :maximum => 50 }
validates :password, :presence => true,
:confirmation => true,
:length => { :within => 6..40 }
before_save :encrypt_password
def has_password?(submitted_password)
encrypted_password == encrypt(submitted_password)
end
def self.authenticate(emp_id, submitted_password)
user = find_by_emp_id(emp_id)
return nil if user.nil?
return user if user.has_password?(submitted_password)
end
private
def encrypt_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
Below is the SPEC code:
require 'spec_helper'
describe User do
before(:each) do
#attr = {:name=>"Example", :dept_id=>01, :emp_id=>10, :password=>"pwdabcd", :password_confirmation => "pwdabcd" }
end
.
.
.
describe "password encryption" do
before(:each) do
#user = User.create!(#attr)
end
.
.
.
describe "authenticate method" do
it "should return the user on emp_id password match" do
matching_user = User.authenticate(#attr[:emp_id], #attr[:password])
matching_user.should == #user
end
end
end
end
Thank you so much for your kind assistance.
Have a nice day!
Kevin - when you see a failure message like that, the representation of the object (#<User ...>) is up to the object, so it's possible that it doesn't show you everything that is being compared by ==. My guess is it has something to do with :password_confirmation, but I'm not certain. It doesn't look like the implementation is using it yet, so try removing password_confirmation from #attr in the spec, and from the attr_accessible declaration, and see if it passes.
everyone. I've got the following problem:
After implementing has_password? in section 7.2.3 RSpec displays the following error for "should create a new instance given valid attributes" test for example
1) User should create a new instance given valid attributes
Failure/Error: User.create!(#attr)
ArgumentError:
wrong number of arguments (1 for 0)
# ./app/models/user.rb:42:in secure_hash'
# ./app/models/user.rb:39:inmake_salt'
# ./app/models/user.rb:30:in encrypt_password'
# ./spec/models/user_spec.rb:14:inblock (2 levels) in '
Finished in 1.47 seconds
1 example, 1 failure
<-- Slave(1) run done!
I don't understand, what exactly causes the problem.
Here is my user.rb code:
require 'digest'
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 }
# Automatically create the virtual attribute "password_confirmation"
validates :password, :presence => true,
:confirmation => true,
:length => { :within => 6..40 }
before_save :encrypt_password
# Return 'true' if the user's password matches the submitted password
def has_password?(submitted_password)
encrypted_password == encrypt(submitted_password)
end
private
def encrypt_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
Digest::SHA2.hexdigest(string)
end
end
What can it be?
Thank you in advance!
Your secure_hash method needs to take an argument.
def secure_hash(string)
Digest::SHA2.hexdigest(string)
end