Rails rspec unexpected tIDENTIFIER - ruby-on-rails

I'm going through the RoR tutorial, ran into the following error and can't seem to figure it out. I copied the sample code exactly but my rspec test still won't run (console won't even create a new User)
Appreciate any help, thanks!
Error:
user#ubuntu:~/Ruby/rails_projects/sample_app$ bundle exec rspec spec/
No DRb server is running. Running in local process instead ...
/home/user/.rvm/gems/ruby-1.9.3-p327/gems/activesupport-3.2.9/lib/active_support/dependencies.rb:245:in `load': /home/user/Ruby/rails_projects/sample_app/spec/models/user_spec.rb:51: syntax error, unexpected tIDENTIFIER, expecting keyword_end (SyntaxError)
from /home/user/.rvm/gems/ruby-1.9.3-p327/gems/activesupport-3.2.9/lib/active_support/dependencies.rb:245:in `block in load'
from /home/user/.rvm/gems/ruby-1.9.3-p327/gems/activesupport-3.2.9/lib/active_support/dependencies.rb:236:in `load_dependency'
from /home/user/.rvm/gems/ruby-1.9.3-p327/gems/activesupport-3.2.9/lib/active_support/dependencies.rb:245:in `load'
from /home/user/.rvm/gems/ruby-1.9.3-p327/gems/rspec-core-2.11.1/lib/rspec/core/configuration.rb:780:in `block in load_spec_files'
from /home/user/.rvm/gems/ruby-1.9.3-p327/gems/rspec-core-2.11.1/lib/rspec/core/configuration.rb:780:in `map'
from /home/user/.rvm/gems/ruby-1.9.3-p327/gems/rspec-core-2.11.1/lib/rspec/core/configuration.rb:780:in `load_spec_files'
from /home/user/.rvm/gems/ruby-1.9.3-p327/gems/rspec-core-2.11.1/lib/rspec/core/command_line.rb:22:in `run'
from /home/user/.rvm/gems/ruby-1.9.3-p327/gems/rspec-core-2.11.1/lib/rspec/core/runner.rb:66:in `rescue in run'
from /home/user/.rvm/gems/ruby-1.9.3-p327/gems/rspec-core-2.11.1/lib/rspec/core/runner.rb:62:in `run'
from /home/user/.rvm/gems/ruby-1.9.3-p327/gems/rspec-core-2.11.1/lib/rspec/core/runner.rb:8:in `block in autorun'
Here's my rspec test:
require 'spec_helper'
describe User do
before { #user = User.new(name: "Example User", email: "user#example.com") }
subject { #user }
it { should respond_to(:name) }
it { should respond_to(:email) }
it { should be_valid }
describe "when name is not present" do
before { #user.name = " " }
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 not valid" 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 first.last#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
end
And here's my user model:
class User < ActiveRecord::Base
attr_accessible :name, :email, :password, :password_confirmation
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

This line has a typo:
#user.email = valid_address|
There's a trailing | that shouldn't be there

Related

No method error - save from rubystutorial.org

I've been following along Hartl's book at rubystutorial.org and stuck on this error
When I run rspec tests it tells me that the method (save) does not exist for user
Here's my code and test. I can't find what's wrong with it and why the method doesn't exist within #user
user_spec.rb
require 'spec_helper'
describe User do
before do
#user = User.new(name: "Example User", email: "user#example.com")
end
subject { #user }
it { should respond_to(:name) }
it { should respond_to(:email) }
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 "shoud 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 = #user.email.upcase
user_with_same_email.save
end
it { should_not be_valid }
end
end
And my user.rb
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 } )
end
Exact error is
Failures:
1) User when email address is already taken
Failure/Error: user_with_same_email.save
NoMethodError:
undefined method `save' for "USER#EXAMPLE.COM":String
# ./spec/models/user_spec.rb:55:in `block (3 levels) in <top (required)>'
Finished in 0.411 seconds
24 examples, 1 failure
Failed examples:
rspec ./spec/models/user_spec.rb:58 # User when email address is already take
You are defining a user and then change it on string (email, so email has no save method) in the next lines:
user_with_same_email = #user.dup
user_with_same_email = #user.email.upcase
user_with_same_email.save
You should change it for this:
user_with_same_email = #user.dup
user_with_same_email.email = #user.email.upcase
user_with_same_email.save
Object
The problem here can be seen with the error itself:
undefined method `save' for "USER#EXAMPLE.COM":String
The problem you have is not that .save is unavailable, but that the object you're trying to call it on is unable to process it.
The problem is specifically to do with this line:
user_with_same_email = #user.email.upcase
--
Fix
The issue is you're setting the user_with_same_email variable as #user.email.upcase. You can do what zishe suggested (to set the email attribute of the new variable)
I don't really understand what you're trying to achieve - as your User model sets the email to downcase on the before_save callback.

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

Validation failed: Password digest can't be blank

I have seen other threads with similar problems but they don't seem to fix my problem. I am following along with with the tutorial on http://ruby.railstutorial.org/ to get a basic user sign up and login or a different project then that sample one.
Basically when I run rspec I keep getting this error. I have run all my migrations and test prepare. Really stumped with this.
1) User should reject duplicate email addresses
Failure/Error: User.create!(#attr)
ActiveRecord::RecordInvalid:
Validation failed: Password digest can't be blank, Password can't be blank, Password is too short (minimum is 6 characters), Password confirmation can't be blank
# ./spec/models/user_spec.rb:60:in `block (2 levels) in <top (required)>'
2) User should accept valid email addresses
Failure/Error: valid_email_user.should be_valid end
expected #<User id: nil, name: "Example User", email: "user#foo.com", created_at: nil, updated_at: nil, password_digest: nil> to be valid, but got errors: Password digest can't be blank, Password can't be blank, Password is too short (minimum is 6 characters), Password confirmation can't be blank
# ./spec/models/user_spec.rb:48:in `block (3 levels) in <top (required)>'
# ./spec/models/user_spec.rb:46:in `each'
# ./spec/models/user_spec.rb:46:in `block (2 levels) in <top (required)>'
3) User should create a new instance given valid attributes
Failure/Error: User.create!(#attr)
ActiveRecord::RecordInvalid:
Validation failed: Password digest can't be blank, Password can't be blank, Password is too short (minimum is 6 characters), Password confirmation can't be blank
# ./spec/models/user_spec.rb:25:in `block (2 levels) in <top (required)>'
4) User should reject email addresses identical up to case
Failure/Error: User.create!(#attr.merge(:email => upcased_email))
ActiveRecord::RecordInvalid:
Validation failed: Password digest can't be blank, Password can't be blank, Password is too short (minimum is 6 characters), Password confirmation can't be blank
# ./spec/models/user_spec.rb:67:in `block (2 levels) in <top (required)>'
Here is my user_spec
require 'spec_helper'
describe User do
before(:each) do
#attr = { :name => "Example User", :email => "user#example.com" }
end
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 }
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 address" do
no_email_user = User.new(#attr.merge(:email => ""))
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 => 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 => 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 => address))
invalid_email_user.should_not be_valid end
end
it "should reject duplicate email addresses" do
# Put a user with given email address into the database.
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 => upcased_email))
user_with_duplicate_email = User.new(#attr)
user_with_duplicate_email.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
here is my user model
class User < ActiveRecord::Base
attr_accessible :name, :email, :password, :password_confirmation
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
your validation is broken too, a password and password_confirmation should be required if the user is created but not thereafter
validates :password, presence: true, length: { minimum: 6 }
validates :password_confirmation, presence: true
you will run into problems if you try to update the user later on, say changing its Name, because then it will check for both password and password_confirmation but the user already has a password set stored usually in the password_digist field encrypted by bcrypt but not stored along with password and confirmation in plain text.
I recommend this only to be validated for new records:
validates :password, presence: true, length: { minimum: 6 } if new?
validates :password_confirmation, presence: true if new?
In all the failing tests, you use #attr = { :name => "Example User", :email => "user#example.com" } to create a new user. But to create a new user, you MUST set password and password_confirmation. Add these attributes to the #attr hash. The password_digest field should then be set automatically and it should be possible to save the user.
delete this line
attr_accessible :name, :email, :password, :password_confirmation
It should work now.
This preventes the method rails method password= from being called. (also see secure_password.rb)

"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.

NoMethodError undefined method `save' for nil:NilClass

What do I need to do to fix this? I am new to ruby on rails.
Error when rspec is ran
1) remember token should have a nonblank remember token
Failure/Error: before { #user.save }
NoMethodError:
undefined method `save' for nil:NilClass
# ./spec/models/user_spec.rb:125:in `block (2 levels) in <top (required)>'
user_spec.rb
require 'spec_helper'
describe User do
before do
#user = User.new(name: "Example User", email: "user#example.com",
password: "foobar", password_confirmation: "foobar")
end
.
.
.
it { should respond_to(:remember_token) }
.
.
.
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
describe "remember token" do
before { #user.save }
it "should have a nonblank remember token" do
subject.remember_token.should_not be_blank
end
end
user.rb
class User < ActiveRecord::Base
attr_accessible :name, :email, :password, :password_confirmation
has_secure_password
before_save { |user| user.email = email.downcase }
before_save :create_remember_token
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, length: { minimum: 6 }
validates :password_confirmation, presence: true
private
def create_remember_token
self.remember_token = SecureRandom.urlsafe_base64
end
end
It looks like this block of code
describe "remember token" do
is outside the block
describe User do
...
end
If you move it inside the block, then it will have the before action fire that creates the #user object (which you then save in your own before block)
the #user variable will be not found, so
you should move describe "remember token" inside ->
describe User do
//current definitions
describe "remember token" do
before { #user.save }
it "should have a nonblank remember token" do
subject.remember_token.should_not be_blank
end
end
end

Resources