Rails Tutorial by Michael Hartl Chapter 6 Authenticate User - ruby-on-rails

I can't for the life of me seem to figure out why these three tests aren't passing. I'm pretty new with rails but I feel as though I've tried about everything, at least according to the tutorial. I'm sure its something obvious but my attempts to find an answer have been in vain. My failed tests are as follows(pulled from Michael Hartl's Rails Tutorial). Thanks.
Failures:
1) User when password is not present return value of authenticate method with valid password
Failure/Error: it { should eq found_user.authenticate(#user.password) }
NoMethodError:
undefined method authenticate' for nil:NilClass
# ./spec/models/user_spec.rb:94:inblock (5 levels) in '
2) User when password is not present return value of authenticate method with invalid password
Failure/Error: let(:user_for_invalid_password) { found_user.authenticate("invalid") }
NoMethodError:
undefined method authenticate' for nil:NilClass
# ./spec/models/user_spec.rb:98:inblock (5 levels) in '
# ./spec/models/user_spec.rb:100:in `block (5 levels) in '
3) User when password is not present return value of authenticate method with invalid password
Failure/Error: let(:user_for_invalid_password) { found_user.authenticate("invalid") }
NoMethodError:
undefined method authenticate' for nil:NilClass
# ./spec/models/user_spec.rb:98:inblock (5 levels) in '
# ./spec/models/user_spec.rb:101:in `block (5 levels) in '
User_spec tests
require 'spec_helper'
describe User do
before do
#user = User.new(name: "Example User", email: "user#example.com",
password: "foobar", password_confirmation: "foobar")
end
subject { #user }
it { should respond_to(:name) }
it { should respond_to(:email) }
it { should respond_to(:password_digest) }
it { should respond_to(:password) }
it { should respond_to(:password_confirmation) }
it { should respond_to(:authenticate) }
it { should be_valid }
describe "when name is not present" do
before { #user.name = " " }
it { should_not be_valid }
end
it "should be valid" do
expect(#user).to be_valid
end
describe "when email is not present" do
before { #user.email = " " }
it { should_not be_valid }
end
describe "when name is too long" do
before { #user.name = 'a' * 51 }
it { should_not be_valid }
end
describe "when email format is invalid" do
it "should be invalid" do
addresses = %w[user#foo,com user_at_foo.org example.user#foo.
foo#bar_baz.com foo#bar+baz.com]
addresses.each do |invalid_address|
#user.email = invalid_address
expect(#user).not_to be_valid
end
end
end
describe "when email format is valid" do
it "should be valid" do
addresses = %w[user#foo.COM A_US-ER#f.b.org frst.lst#foo.jp a+b#baz.cn]
addresses.each do |valid_address|
#user.email = valid_address
expect(#user).to be_valid
end
end
end
describe "when email address is already taken" do
before do
user_with_same_email = #user.dup
user_with_same_email.email = #user.email.upcase
user_with_same_email.save
end
it { should_not be_valid }
end
describe "when password is not present" do
before do
#user = User.new(name:"Example User", email: "user#example.com",
password: " ", password_confirmation: " ")
end
it { should_not be_valid }
describe "when password does not match confirmation" do
before { #user.password_confirmation = "mismatch" }
it { should_not be_valid }
end
describe "with a password thats too short" do
before { #user.password = #user.password_confirmation = "a" * 5 }
it { should be_invalid }
end
describe "return value of authenticate method" do
before { #user.save }
let(:found_user) { User.find_by(email: #user.email) }
describe "with valid password" do
it { should eq found_user.authenticate(#user.password) }
end
describe "with invalid password" do
let(:user_for_invalid_password) { found_user.authenticate("invalid") }
it { should_not eq user_for_invalid_password }
specify { expect(user_for_invalid_password).to be_false }
end
end
end
end
User model
class User < ActiveRecord::Base
before_save { self.email = email.downcase }
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
has_secure_password
validates :password, length: { minimum: 6 }
end

You are getting the error as found_user is nil.
Thats because you are not closing when password is not present describe block properly.
So what happens is, this invalid #user is set with a blank password and its been carried forward till your failing test case.
describe "when password is not present" do
before do
#user = User.new(name:"Example User", email: "user#example.com",
password: " ", password_confirmation: " ")
end
it { should_not be_valid }
end ### Add end here
Also, remove the very last end from the bottom of the file.

Related

User authenticate not passing rspec testing

I am following the Ruby on Rails Tutorial Learn Rails by Example Michael Hartli and am getting this error during rspec testing for authenticating the password. i think the other two errors are because of the first one. so just need a little help understanding whats going wrong and a solution.
Rays-MBP:sample_app raycove$ bundle exec rspec spec/
............F...............FF..
Failures:
1) User return value of authenticate method with valid password
Failure/Error: it { should == found_user.authenticate(#user.password) }
expected: #<User id: 6, name: "Example User", email: "user#example.com", created_at: "2016-02-19 21:45:28", updated_at: "2016-02-19 21:45:28", password_digest: "$2a$04$mweZJiYW0O/iDts7bCwUS.hb9GUznoH3nSGSeWdMHuW...">
got: #<User id: nil, name: "Example User", email: "user#example.com", created_at: nil, updated_at: nil, password_digest: "$2a$04$juZNb6HH/yrXQUhYBd.tCeFqWYnwuQs2x.batWwMWhY..."> (using ==)
Diff:
## -1,9 +1,9 ##
-#<User:0x007fa71611a4f8
- id: 6,
+#<User:0x007fa7161b0f70
+ id: nil,
name: "Example User",
email: "user#example.com",
- created_at: Fri, 19 Feb 2016 21:45:28 UTC +00:00,
- updated_at: Fri, 19 Feb 2016 21:45:28 UTC +00:00,
+ created_at: nil,
+ updated_at: nil,
password_digest:
- "$2a$04$mweZJiYW0O/iDts7bCwUS.hb9GUznoH3nSGSeWdMHuWpxMMAV2W42">
+ "$2a$04$juZNb6HH/yrXQUhYBd.tCeFqWYnwuQs2x.batWwMWhYJQtIAKvTou">
# ./spec/models/user_spec.rb:108:in `block (4 levels) in <top (required)>'
2) User pages profile page
Failure/Error: let(:user) { FactoryGirl.create(:user) }
ActiveRecord::RecordInvalid:
Validation failed: Email has already been taken
# ./spec/requests/user_pages_spec.rb:8:in `block (3 levels) in <top (required)>'
# ./spec/requests/user_pages_spec.rb:9:in `block (3 levels) in <top (required)>'
3) User pages profile page
Failure/Error: let(:user) { FactoryGirl.create(:user) }
ActiveRecord::RecordInvalid:
Validation failed: Email has already been taken
# ./spec/requests/user_pages_spec.rb:8:in `block (3 levels) in <top (required)>'
# ./spec/requests/user_pages_spec.rb:9:in `block (3 levels) in <top (required)>'
Finished in 0.34838 seconds
32 examples, 3 failures
Failed examples:
rspec ./spec/models/user_spec.rb:108 # User return value of authenticate method with valid password
rspec ./spec/requests/user_pages_spec.rb:11 # User pages profile page
rspec ./spec/requests/user_pages_spec.rb:12 # User pages profile page
Randomized with seed 13988
My user_pages_spec
require 'spec_helper'
describe "User pages" do
subject { page }
describe "profile page" do
let(:user) { FactoryGirl.create(:user) }
before { visit user_path(user) }
it { should have_selector('h1', text: user.name) }
it { should have_selector('title', text: user.name) }
end
describe "signup page" do
before { visit signup_path }
it { should have_selector('h1', text: 'Sign up') }
it { should have_selector('title', text: 'Sign up') }
end
end
My user_spec
require 'spec_helper'
describe User do
before do
#user = User.new(name: "Example User", email: "user#example.com",
password: "foobar", password_confirmation: "foobar")
end
subject { #user }
it { should respond_to(:name) }
it { should respond_to(:email) }
it { should respond_to(:password_digest) }
it { should respond_to(:password) }
it { should respond_to(:password_confirmation) }
it { should respond_to(:authenticate) }
describe "when name is not present" do
before { #user.name = " " }
it { should_not be_valid }
end
describe "when email is not present" do
before { #user.email = " " }
it { should_not be_valid }
end
describe "when name is too long" do
before { #user.name = "a" * 51 }
it { should_not be_valid }
end
describe "when email format is invalid" do
it "should be invalid" do
addresses = %w[user#foo,com user_at_foo.org example.user#foo.
foo#bar_baz.com foo#bar+baz.com]
addresses.each do |invalid_address|
#user.email = invalid_address
#user.should_not be_valid
end
end
end
describe "when email format is valid" do
it "should be valid" do
addresses = %w[user#foo.COM A_US-ER#f.b.org frst.lst#foo.jp a+b#baz.cn]
addresses.each do |valid_address|
#user.email = valid_address
#user.should be_valid
end
end
end
describe "when email address is already taken" do
before do
user_with_same_email = #user.dup
user_with_same_email.email = #user.email.upcase
user_with_same_email.save
end
it { should_not be_valid }
end
describe "when password is not present" do
before { #user.password = #user.password_confirmation = " " }
it { should_not be_valid }
end
describe "when password doesn't match confirmation" do
before { #user.password_confirmation = "mismatch" }
it { should_not be_valid }
end
describe "when password confirmation is nil" do
before { #user.password_confirmation = nil }
it { should_not be_valid }
end
describe "with a password that's too short" do
before { #user.password = #user.password_confirmation = "a" * 5 }
it { should be_invalid }
end
describe "return value of authenticate method" do
before { #user.save }
let(:found_user) { User.find_by_email(#user.email) }
describe "with valid password" do
it { should == found_user.authenticate(#user.password) }
end
describe "with invalid password" do
let(:user_for_invalid_password) { found_user.authenticate("invalid") }
it { should_not == user_for_invalid_password }
specify { user_for_invalid_password.should be_false }
end
end
end
My user.rb
class User < ActiveRecord::Base
private
# Using a private method to encapsulate the permissible parameters
# is just a good pattern since you'll be able to reuse the same
# permit list between create and update. Also, you can specialize
# this method with per-user checking of permissible attributes.
def user_params
params.require(:user).permit :name, :email, :password, :password_confirmation
end
has_secure_password
before_save { |user| user.email = email.downcase }
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true,
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
validates :password, presence: true, length: { minimum: 6 }
validates :password_confirmation, presence: true
end
I belive what is happening is when it runs through and gets to the describe "return value of authenticate method" do section in user_spec
it changed the password or something as the passwords dont match but they are pre set so this cant be, any help is very much appreciated.

undefined method Hartl chapter 6

I'm currently working on 6.3.3 of Hartl's tutorial http://www.railstutorial.org/book/modeling_users
after running rspec spec/ I'm getting the following failures - I'm sure I'm misunderstanding the instructions or something. I'm grateful for any insight into what I'm doing wrong:
leo$ rspec spec/
............FFF...................
Failures:
1) User return value of authenticate method with invalid password
Failure/Error: let(:user_for_invalid_password) { found_user.authenticate("invalid") }
NoMethodError:
undefined method `authenticate' for nil:NilClass
# ./spec/models/user_spec.rb:92:in `block (4 levels) in <top (required)>'
# ./spec/models/user_spec.rb:95:in `block (4 levels) in <top (required)>'
2) User return value of authenticate method with invalid password
Failure/Error: it { should_not eq user_for_invalid }
NameError:
undefined local variable or method `user_for_invalid' for # <RSpec::Core::ExampleGroup::Nested_2::Nested_10::Nested_2:0x007faed251c830>
# ./spec/models/user_spec.rb:94:in `block (4 levels) in <top (required)>'
3) User return value of authenticate method with valid password
Failure/Error: it { should eq found_user.authenticate(#user.password) }
NoMethodError:
undefined method `authenticate' for nil:NilClass
# ./spec/models/user_spec.rb:88:in `block (4 levels) in <top (required)>'
Finished in 0.24185 seconds
34 examples, 3 failures
Failed examples:
rspec ./spec/models/user_spec.rb:95 # User return value of authenticate method with invalid password
rspec ./spec/models/user_spec.rb:94 # User return value of authenticate method with invalid password
rspec ./spec/models/user_spec.rb:88 # User return value of authenticate method with valid password
here is what I have in my user_spec.rb file:
require 'spec_helper'
describe User do
before do
#user = User.new(name: "Example User", email: "user#example.com",
password: "foobar", password_confirmation: "foobar")
end
subject { #user }
it { should respond_to(:name) }
it { should respond_to(:email) }
it { should respond_to(:password_digest) }
it { should respond_to(:password) }
it { should respond_to(:password_confirmation) }
it { should respond_to(:authenticate) }
it { should be_valid }
describe "when name is not present" do
before { #user.name = " " }
it { should_not be_valid }
end
describe "when email is not present" do
before { #user.email = " " }
it { should_not be_valid }
end
describe "when name is too long" do
before { #user.name = "a" * 51 }
it { should_not be_valid }
end
describe "when email format is invalid" do
it "should be invalid" do
addresses = %w[user#foo,com user_at_foo.org example.user#foo. foo#bar_baz.com foo#bar+baz.com]
addresses.each do |invalid_address|
#user.email = invalid_address
expect(#user).not_to be_valid
end
end
end
describe "when email format is valid" do
it "should be valid" do
addresses = %w[user#foo.COM A_US-er#f.b.org frst.1st#foo.jp a+b#baz.cn]
addresses.each do |valid_address|
#user.email = valid_address
expect(#user).to be_valid
end
end
end
describe "when email address is already taken" do
before do
user_with_same_email = #user.dup
user_with_same_email.email = #user.email.upcase
user_with_same_email.save
end
it { should_not be_valid }
end
describe "when password is not present" do
before do
#user = User.new(name: "Example User", email: "user#example.com", password: " ", password_confirmation: " ")
end
it { should_not be_valid }
end
describe "when password doesn't match confirmation" do
before { #user.password_confirmation = "mismatch" }
it { should_not be_valid }
end
describe "with a password that's too short" do
before { #user.password = #user.password_confirmation = "a" * 5 }
it { should be_invalid }
end
describe "return value of authenticate method" do
before { #user.save }
let(:found_user) { User.find_by(email: #user.password) }
describe "with valid password" do
it { should eq found_user.authenticate(#user.password) }
end
describe "with invalid password" do
let(:user_for_invalid_password) { found_user.authenticate("invalid") }
it { should_not eq user_for_invalid }
specify { expext(user_for_invalid_password).to be_false }
end
end
end
and here's what I have in my user.rb file:
class User < ActiveRecord::Base
before_save { self.email = email.downcase }
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true,
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
has_secure_password
validates :password, length: { minimum:6 }
end
Found your typo:
describe "return value of authenticate method" do
# should find by #user.email
let(:found_user) { User.find_by(email: #user.password) }
end

Not sure why getting Syntax Errors

I'm following the online ruby on rails tutorial using an imac with OSx10.8 using rvm and ruby 1.8.7. When running bundle exec rspec spec/ I get these errors
/Users/hetzerbr/.rvm/gems/ruby-1.8.7-p374/gems/activesupport-3.2.13/lib/active_support/dependencies.rb:245:in `load': /Users/hetzerbr/sample_app/spec/models/user_spec.rb:88: syntax error, unexpected kEND, expecting $end (SyntaxError)
from /Users/hetzerbr/.rvm/gems/ruby-1.8.7-p374/gems/activesupport-3.2.13/lib/active_support/dependencies.rb:245:in `load'
from /Users/hetzerbr/.rvm/gems/ruby-1.8.7-p374/gems/activesupport-3.2.13/lib/active_support/dependencies.rb:236:in `load_dependency'
from /Users/hetzerbr/.rvm/gems/ruby-1.8.7-p374/gems/activesupport-3.2.13/lib/active_support/dependencies.rb:245:in `load'
from /Users/hetzerbr/.rvm/gems/ruby-1.8.7-p374/gems/rspec-core-2.11.1/lib/rspec/core/configuration.rb:780:in `load_spec_files'
from /Users/hetzerbr/.rvm/gems/ruby-1.8.7-p374/gems/rspec-core-2.11.1/lib/rspec/core/configuration.rb:780:in `map'
from /Users/hetzerbr/.rvm/gems/ruby-1.8.7-p374/gems/rspec-core-2.11.1/lib/rspec/core/configuration.rb:780:in `load_spec_files'
from /Users/hetzerbr/.rvm/gems/ruby-1.8.7-p374/gems/rspec-core-2.11.1/lib/rspec/core/command_line.rb:22:in `run'
from /Users/hetzerbr/.rvm/gems/ruby-1.8.7-p374/gems/rspec-core-2.11.1/lib/rspec/core/runner.rb:66:in `run'
from /Users/hetzerbr/.rvm/gems/ruby-1.8.7-p374/gems/rspec-core-2.11.1/lib/rspec/core/runner.rb:8:in `autorun'
from /Users/hetzerbr/.rvm/gems/ruby-1.8.7-p374/bin/ruby_noexec_wrapper:14
My user_spec.rb file looks like this, I think the error might be that I placed an end somewhere that I should not have or I might be missing and end somewhere:
require 'spec_helper'
describe User do
before do
#user = User.new(:name => "Example User", :email => "user#example.com", :password => "foobar", :password_confirmation => "foobar")
end
subject { #user }
it { should respond_to(:name) }
it { should respond_to(:email) }
it { should respond_to(:password_digest) }
it { should respond_to(:password) }
it { should respond_to(:password_confirmation) }
it { should respond_to(:authenticate) }
it { should be_valid }
describe "when name is not present" do
before { #user.name = " " }
it { should_not be_valid }
describe "when email is not present" do
before { #user.email = " " }
it { should_not be_valid }
describe "when name is too long" do
before { #user.name = "a" * 51 }
it { should_not be_valid }
end
end
describe "when email address is already taken" do
before do
user_with_same_email = #user.dup
user_with_same_email.email = #user.email.upcase
user_with_same_email.save
end
it { should_not be_valid }
end
end
describe "when email format is invalid" do
it "should be invalid" do
addresses = %w[user#foo,com user_at_foo.org example.user#foo.
foo#bar_baz.com foo#bar+baz.com foo#bar..com]
addresses.each do |invalid_address|
#user.email = invalid_address
expect(#user).not_to be_valid
end
end
end
describe "when email format is valid" do
it "should be valid" do
addresses = %w[user#foo.COM A_US-ER#f.b.org frst.lst#foo.jp a+b#baz.cn]
addresses.each do |valid_address|
#user.email = valid_address
expect(#user).to be_valid
end
end
end
end
describe "email address with mixed case" do
let(:mixed_case_email) { "Foo#ExAMPle.CoM" }
it "should be saved as all lower-case" do
#user.email = mixed_case_email
#user.save
expect(#user.reload.email).to eq mixed_case_email.downcase
end
end
describe "when password is not present" do
before do
#user = User.new(:name => "Example User", :email => "user#example.com",
:password => " ", :password_confirmation => " ")
end
it { should_not be_valid }
end
describe "when password doesn't match confirmation" do
before { #user.password_confirmation = "mismatch" }
it { should_not be_valid }
end
end
describe "with a password that's too short" do
before { #user.password = #user.password_confirmation = "a" * 5 }
it { should be_invalid }
end
describe "return value of authenticate method" do
before { #user.save }
let(:found_user) { User.find_by(:email => #user.email) }
describe "with valid password" do
it { should eq found_user.authenticate(#user.password) }
end
describe "with invalid password" do
let(:user_for_invalid_password) { found_user.authenticate("invalid") }
it { should_not eq user_for_invalid_password }
specify { expect(user_for_invalid_password).to be_false }
end
end
end
Some of your describe blocks don't have an 'end'
describe "when name is not present" do
before { #user.name = " " }
it { should_not be_valid }
describe "when email is not present" do
before { #user.email = " " }
it { should_not be_valid }
describe "when name is too long" do
before { #user.name = "a" * 51 }
it { should_not be_valid }
end
should be..
describe "when name is not present" do
before { #user.name = " " }
it { should_not be_valid }
end
describe "when email is not present" do
before { #user.email = " " }
it { should_not be_valid }
end
describe "when name is too long" do
before { #user.name = "a" * 51 }
it { should_not be_valid }
end
It is a hash you must pass to the new() method while mass-assign , try it in {}
#user = User.new( { :name => "Example User", :email => "user#example.com", :password => "foobar", :password_confirmation => "foobar" } )
at your error line : syntax error, unexpected keyword_end, expecting $end (SyntaxError)
kEND means end of file but $end means end keyword, you must close your describe do body of codes each by one end

"undefined local variable or method" in the rails console when it encounters methods provided by has_secure_password

My problem is when I try to use the rails console to update a user email I get NoMethodError: undefined method 'update_attribute'
While working thru the problem I tried
current_user = user.authrnticate(foobar) and got back NameError: undefined local variable or method 'user' for main:Object
Which leads me to believe the "rails c" isn't using or seeing the user.rb file corectly.
I have tried restarting the rails server before and after performing [rake db:test:prepare] and [rake db:migrate].
My [rails c] will execute methods not defined in user.rb.
Rspec is running without a problem. All tests in the user_spec are passing. and when I comment out has_secure_password all tests fail.
require 'spec_helper'
describe User do
before do
#user = User.new(name: "Example User", email: "user#example.com",
password: "foobar", password_confirmation: "foobar")
end
subject { #user }
it { should respond_to(:name) }
it { should respond_to(:email) }
it { should respond_to(:password_digest) }
it { should respond_to(:password) }
it { should respond_to(:password_confirmation) }
it { should respond_to(:authenticate) }
it { should be_valid }
describe "when name is not present" do
before { #user.name = " " }
it { should_not be_valid }
end
describe "when email is not present" do
before { #user.email = " " }
it { should_not be_valid }
end
describe "when name is to long" do
before { #user.name = "a" * 51 }
it { should_not be_valid }
end
describe "when email format is invalid" do
it "should be invalid" do
addresses = %w[user#foo,com user_at_foo.org example.user#foo.
foo#bar_baz.com foo#bar+baz.com]
addresses.each do |invalid_address|
#user.email = invalid_address
#user.should_not be_valid
end
end
end
describe "when email format is valid" do
it "should be valid" do
addresses = %w[user#foo.COM A_US-ER#f.b.org frst.lst#foo.jp a+b#baz.cn]
addresses.each do |valid_address|
#user.email = valid_address
#user.should be_valid
end
end
end
describe "when email address is already taken" do
before do
user_with_same_email = #user.dup
user_with_same_email.email = #user.email.upcase
user_with_same_email.save
end
it { should_not be_valid }
end
describe "when password is not present" do
before { #user.password = #user.password_confirmation = " " }
it { should_not be_valid }
end
describe "when password doesn't match confirmation " do
before { #user.password_confirmation = "mismatch" }
it { should_not be_valid }
end
describe "when password confirmation is nil" do
before { #user.password_confirmation = nil }
it { should_not be_valid }
end
describe "when password is too short" do
before { #user.password = #user.password_confirmation = "a" * 5}
it { should_not be_valid }
end
describe "return value of authenticate method" do
before { #user.save }
let(:found_user) { User.find_by_email(#user.email) }
describe "with valid password" do
it { should == found_user.authenticate(#user.password) }
end
describe "with invalid password" do
let(:user_for_invalid_password) { found_user.authenticate("invalid") }
it { should_not == user_for_invalid_password }
specify { user_for_invalid_password.should be_false }
end
end
end
My user.rb is
class User < ActiveRecord::Base
attr_accessible :name, :email, :password, :password_confirmation
has_secure_password
before_save { |user| user.email = user.email.downcase }
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
validates :password, presence: true, length: {minimum: 6 }
validates :password_confirmation, presence: true
end
and here is the entire project on github
I have looked exhaustively for a solution including a throe read of the ActiveRecord documentation and I'm stumped.
Any help is greatly appreciated.
Many of the helper methods are not available to be called in the console.
you can often access them by calling them via helper.helpername, but this doesn't always work
How are you getting the User from the database?
For example user = User.find_by_name('name')
This error:
NameError: undefined local variable or method 'user' for main:Object
Says that you didn't instantiate a variable user.
Did you fetch User from a database in to user variable?
Your irb session should look something like this:
To check if you have a user in database:
> User.all
If you have a valid user in database named "Jon"
> user = User.find_by_name("Jon")
> current_user = user.auhenticate("valid_password") #will work
If you don't have a user in database:
> User.create(name: "Jon", email: "user#example.com",
password: "foobar", password_confirmation: "foobar")
> user = User.find_by_name("Jon")
> current_user = user.auhenticate("valid_password") #will work
RSpec uses test database but rails c on default uses development one so make sure that you have a record in your development database when you want to work on it in rails c.
rails c command is loading all your project libraries.

Failing Rspec Test with MongoID , Custom Authentication, Password Digest

i have completed the rails tutorial http://ruby.railstutorial.org/, and trying to implement the user model, but in MongoDB, using MongoID.
I have the following code, which is almost exactly the same as the tutorial, yet it's failing on one of the test cases.
class User
include Mongoid::Document
include ActiveModel::SecurePassword
attr_accessible :name, :email, :password, :password_confirmation
field :name, type: String
field :email, type: String
field :password_digest, type: String
has_secure_password
before_save { |user| user.email = email.downcase }
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, length: { minimum: 5}
validates :password_confirmation, presence: true
end
and rspec tests:
require 'spec_helper'
describe User do
before do
#user = User.new(name: "Example User", email: "user#example.com",
password: "foobar", password_confirmation: "foobar")
end
subject { #user }
it { should respond_to(:name) }
it { should respond_to(:email) }
it { should respond_to(:password_digest) }
it { should respond_to(:password) }
it { should respond_to(:password_confirmation) }
it { should respond_to(:authenticate) }
describe 'without a name' do
before { #user.name = "" }
it { should_not be_valid }
end
describe 'without an email' do
before { #user.email = "" }
it { should_not be_valid }
end
describe "when name is too long" do
before { #user.name = "a" * 51 }
it { should_not be_valid }
end
describe "when email format is invalid" do
it "should be invalid" do
addresses = %w[user#foo,com user_at_foo.org example.user#foo.
foo#bar_baz.com foo#bar+baz.com]
addresses.each do |invalid_address|
#user.email = invalid_address
#user.should_not be_valid
end
end
end
describe "when email format is valid" do
it "should be valid" do
addresses = %w[user#foo.COM A_US-ER#f.b.org frst.lst#foo.jp a+b#baz.cn]
addresses.each do |valid_address|
#user.email = valid_address
#user.should be_valid
end
end
end
describe "when email address is already taken" do
before do
user_with_same_email = #user.dup
user_with_same_email.email = #user.email.upcase
user_with_same_email.save
end
it { should_not be_valid }
end
describe "when password is not present" do
before { #user.password = #user.password_confirmation = " " }
it { should_not be_valid }
end
describe "when password doesn't match confirmation" do
before { #user.password_confirmation = "mismatch" }
it { should_not be_valid }
end
describe "when password confirmation is nil" do
before { #user.password_confirmation = nil }
it { should_not be_valid }
end
describe "with a password that's too short" do
before { #user.password = #user.password_confirmation = "a" * 5 }
it { should be_invalid }
end
describe "return value of authenticate method" do
before { #user.save }
let(:found_user) { User.find_by(email: #user.email) }
describe "with valid password" do
it { should == found_user.authenticate(#user.password) }
end
describe "with invalid password" do
let(:user_for_invalid_password) { found_user.authenticate("invalid") }
it { should_not == user_for_invalid_password }
specify { user_for_invalid_password.should be_false }
end
end
end
The failure on the spec is:
........F..........
Failures:
1) User return value of authenticate method with valid password
Failure/Error: it { should == found_user.authenticate(#user.password) }
expected: #<User _id: 50e30a678bffa61a9e000001, _type: nil, name: "Example User", email: "user#example.com", password_digest: "$2a$10$C6klW7B9ok4OIHFopy5AfuncvwNYTZqHWTbqpdd8gXmruSLlwizPO">
got: #<User _id: 50e30f158bffa6df67000001, _type: nil, name: "Example User", email: "user#example.com", password_digest: "$2a$10$mDCz9JVPXGSvpGBwbyHIsuV/k.lJ/ux1TuvgRzxSLYlIna/CdztN2"> (using ==)
Diff:
## -1,2 +1,2 ##
-#<User _id: 50e30a678bffa61a9e000001, _type: nil, name: "Example User", email: "user#example.com", password_digest: "$2a$10$C6klW7B9ok4OIHFopy5AfuncvwNYTZqHWTbqpdd8gXmruSLlwizPO">
+#<User _id: 50e30f158bffa6df67000001, _type: nil, name: "Example User", email: "user#example.com", password_digest: "$2a$10$mDCz9JVPXGSvpGBwbyHIsuV/k.lJ/ux1TuvgRzxSLYlIna/CdztN2">
# ./spec/models/user_spec.rb:89:in `block (4 levels) in <top (required)>'
Finished in 1.79 seconds
19 examples, 1 failure
Update:
Did a bit more diggig, and querying the test database it seems that the data is not being cleared before each test case.
Updat2:
I have managed to fix this by including the following in my Spec Helper:
config.before :each do
Mongoid.purge!
end
But tests are noticeably slower now! any idea how to speed it up?
The problem is calling save, which recreates the password_digest
describe "return value of authenticate method" do
#before { #user.save } #comment this line
#....
end

Resources