0

I looked on stack overflow for an answer and found a few people who posted on similar problems but the solutions didn't help. From what I can tell my code is exactly right.

I am following the tutorial on: http://ruby.railstutorial.org/chapters/modeling-users#code-validates_uniqueness_of_email_case_insensitive_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 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" do
    #  expect(@user).not_to be_valid
    #end
    it { should_not be_valid }

  end


end

The last specification is failing.

My User validation is as such:

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_sensative: false }
end

I followed the tutorial perfectly and yet I can't seem to get this validation to work properly. I know this tutorial is a bit old and I may be using a few newer gems. I also know this isn't the best way to do this type of validation but the tutorial is just making it really simple at first. What is going on here?

Thank you!


EDIT: There is no error. The validation is giving a failure when it should be success.

Failures:
1) User when email address is already taken should not be valid
Failure/Error: it { should_not be_valid }
expected #<User id: nil, name: "Example User", email: "user@example.com", created_at: nil, updated_at: nil> not to be valid
# ./spec/models/user_spec.rb:58:in `block (3 levels in <top (required)>'

Finished in 0.09887 seconds
1 example, 1 failure

Edit again. user_spec.rb has been completely pasted in quest. Sorry I am really new at ruby and didn't realize what might be needed to help troubleshoot.

Bil1
  • 440
  • 2
  • 18
  • 1
    Can you put the error message? – Rafa Paez Feb 16 '14 at 18:45
  • Is the expectation failing to be met, or is it failing because of a raised exception? – Alex Wayne Feb 16 '14 at 18:46
  • Where/how do you set the subject? In other words, what is "it" in the spec? Note that the email in question isn't uppercased, so unless you have a callback/etc lower-casing it, it looks like you're testing the wrong thing. Run with -b, and call save!. – Dave Newton Feb 16 '14 at 20:05
  • It is strange that you upcase the email, but the email in the failed test is downcased. Other than that, you need to save the original @user, so there would be a record in the database to validate it to. – sonnyhe2002 Feb 16 '14 at 20:14
  • @DaveNewton Question updated with more information. – Bil1 Feb 16 '14 at 20:17
  • @sonnyhe2002: The test `it { should_not be_valid }` is actually testing the `@user` user, the user user_with_same_email is created to make the @user be not valid. I agree it is a bit confusing syntax. – Rafa Paez Feb 16 '14 at 20:20
  • @sonnyhe2002 I may be wrong because I don't completely understand all this yet but I think it is making user_with_same_email exactly like (a)user. Then ucasing the e-mail of that variable. Then trying to save it. Then we check to see if (a)user is still valid to be written. Also, I can't type an at symbol in a comment here lol. – Bil1 Feb 16 '14 at 20:20
  • If @user is already saved, it's valid. I don't see where you save it, so there's no reason the new user would be invalid. – Dave Newton Feb 16 '14 at 20:43

3 Answers3

2

If you continue reading the tutorial you realise that the author says that the test is still not completed to be passed. That's because the current validation is still case sensitive.

Adding uniqueness: { case_sensitive: false } makes the test passed as expected

validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
                    uniqueness: { case_sensitive: false }
Rafa Paez
  • 4,820
  • 18
  • 35
  • Shoot! Thank you for that but I pasted the old code by accident. I was tinkering with it at the time of posting. I updated the question to reflect the current code. – Bil1 Feb 16 '14 at 20:22
0

I think it just solved itself. Maybe someone can explain what just happened. I decided to just continue with the tutorial and added gem 'bcrypt-ruby', '3.1.2' to the gemfile. Then I ran bundle install.

Then I tried to run rspec spec/ and it returned an error:

Migrations are pending; run 'bin/rake db:migrate RAILS_ENV=development' to resolve this issue.

But when I ran rake db:migrate nothing happened. SO I googled and found this SO post which had a solution.

I ran:

rake test:prepare 
rake db:migrate

and then all tests passed.

Perhaps my test environment went crazy on me? I still don't know what just happened.

Community
  • 1
  • 1
Bil1
  • 440
  • 2
  • 18
0

You can add user_with_same_email.valid? before .save and provide its output, but I believe it will be true, because:

  1. you haven't changed the id of @user

  2. you just change the case of , but it is as also valid, so "A@A.COM", and "a@a.com" are the same, and valid.

  3. #valid returns true since :email is present, have good Regexp, and still unique.

Малъ Скрылевъ
  • 16,187
  • 5
  • 56
  • 69