Hartl Ruby on Rails教程9.2.2验证失败:名称已被采用

时间:2014-06-18 10:52:13

标签: ruby-on-rails ruby ruby-on-rails-4

一直在关注RoR教程,而是坚持第9.2.2节。 GET请求和补丁请求测试失败,并显示以下错误消息,我不明白为什么:

 1) Authentication authorization as wrong user submitting a GET request to the Users#edit action 
 Failure/Error: let(:wrong_user) { FactoryGirl.create(:user, email: "wrong@example.com") }
 ActiveRecord::RecordInvalid:
   Validation failed: Name has already been taken
 # ./spec/requests/authentication_pages_spec.rb:62:in `block (4 levels) in <top (required)>'
 # ./spec/requests/authentication_pages_spec.rb:66:in `block (5 levels) in <top (required)>'

  2) Authentication authorization as wrong user submitting a GET request to the Users#edit action 
 Failure/Error: let(:wrong_user) { FactoryGirl.create(:user, email: "wrong@example.com") }
 ActiveRecord::RecordInvalid:
   Validation failed: Name has already been taken
 # ./spec/requests/authentication_pages_spec.rb:62:in `block (4 levels) in <top (required)>'
 # ./spec/requests/authentication_pages_spec.rb:66:in `block (5 levels) in <top (required)>'

  3) Authentication authorization as wrong user submitting a PATCH request to the Users#update action 
 Failure/Error: let(:wrong_user) { FactoryGirl.create(:user, email: "wrong@example.com") }
 ActiveRecord::RecordInvalid:
   Validation failed: Name has already been taken
 # ./spec/requests/authentication_pages_spec.rb:62:in `block (4 levels) in <top (required)>'
 # ./spec/requests/authentication_pages_spec.rb:72:in `block (5 levels) in <top (required)>'

Failed examples:

rspec ./spec/requests/authentication_pages_spec.rb:67 # Authentication authorization as wrong user submitting a GET request to the Users#edit action 
rspec ./spec/requests/authentication_pages_spec.rb:68 # Authentication authorization as wrong user submitting a GET request to the Users#edit action 
rspec ./spec/requests/authentication_pages_spec.rb:73 # Authentication authorization as wrong user submitting a PATCH request to the Users#update action

我试过了:

rake db:reset rake test:prepare

但没有区别

以下是我的authentication_pages_spec.rb

require 'spec_helper'

describe "Authentication" do

  subject { page }

  describe "signin page" do
    before { visit signin_path }

    it { should have_content('Sign in') }
    it { should have_title('Sign in') }
  end

 describe "signin" do
    before { visit signin_path }

describe "with invalid information" do
  before { click_button "Sign in" }

      it { should have_title('Sign in') }
      it { should have_selector('div.alert.alert-error') }

     describe "after visiting another page" do
        before { click_link "Home" }
        it { should_not have_selector('div.alert.alert-error') }
      end
    end

    describe "with valid information" do
      let(:user) { FactoryGirl.create(:user) }
      before {sign_in user}

      it { should have_title(user.name) }
      it { should have_link('Profile',     href: user_path(user)) }
      it { should have_link('Settings',    href: edit_user_path(user)) }
      it { should have_link('Sign out',    href: signout_path) }
      it { should_not have_link('Sign in', href: signin_path) }
     end
  end 

  describe "authorization" do

     describe "for non-signed-in users" do
       let(:user) { FactoryGirl.create(:user) }

       describe "in the Users controller" do

        describe "visiting the edit page" do
          before { visit edit_user_path(user) }
          it { should have_title('Sign in') }
        end

        describe "submitting to the update action" do
          before { patch user_path(user) }
          specify { expect(response).to redirect_to(signin_path) }
        end
      end
     end

     describe "as wrong user" do
      let(:user) { FactoryGirl.create(:user) }
      let(:wrong_user) { FactoryGirl.create(:user, email: "wrong@example.com") }
      before { sign_in user, no_capybara: true }

     describe "submitting a GET request to the Users#edit action" do
        before { get edit_user_path(wrong_user) }
        specify { expect(response.body).not_to match(full_title('Edit user')) }
        specify { expect(response).to redirect_to(root_url) }
      end

      describe "submitting a PATCH request to the Users#update action" do
        before { patch user_path(wrong_user) }
        specify { expect(response).to redirect_to(root_url) }
      end
    end
  end
end

users_controller.rb

class UsersController < ApplicationController

before_action :signed_in_user, only: [:edit, :update]
before_action :correct_user,   only: [:edit, :update]


  def show
    @user = User.find(params[:id])
   end

  def new
    @user = User.new
   end

  def create
    @user = User.new(user_params)
    if @user.save
      sign_in @user
      flash[:success] = "Welcome to the Sample App!"
      redirect_to @user
    else
      render 'new'
    end
   end

  def edit
  end

 def update
    if @user.update_attributes(user_params)
      flash[:success] = "Profile updated"
      redirect_to @user
    else
      render 'edit'
    end
  end

  private
    def user_params
      params.require(:user).permit(:name, :email, :password,
                               :password_confirmation)
    end

    # Before filters

    def signed_in_user
      redirect_to signin_url, notice: "Please sign in." unless signed_in?
    end

    def correct_user
      @user = User.find(params[:id])
      redirect_to(root_url) unless current_user?(@user)
    end
  end

sessions_helper.rb

module SessionsHelper

  def sign_in(user)
    remember_token = User.new_remember_token
    cookies.permanent[:remember_token] = remember_token
    user.update_attribute(:remember_token, User.digest(remember_token))
    self.current_user = user
  end

  def signed_in?
    !current_user.nil?
  end

  def current_user=(user)
    @current_user = user
  end

  def current_user
    remember_token = User.digest(cookies[:remember_token])
    @current_user ||= User.find_by(remember_token: remember_token)
  end

  def current_user?(user) 
    user == current_user
  end

  def sign_out
    current_user.update_attribute(:remember_token, User.digest(User.new_remember_token))
    cookies.delete(:remember_token)
    self.current_user = nil
  end
end

规格/支持/ utilities.rb

def full_title(page_title)
  base_title = "Ruby on Rails Tutorial Sample App"
  if page_title.empty?
    base_title
  else
    "#{base_title} | #{page_title}"
  end
end

def sign_in(user, options={})
  if options[:no_capybara]
    # Sign in when not using Capybara.
    remember_token = User.new_remember_token
    cookies[:remember_token] = remember_token
    user.update_attribute(:remember_token, User.digest(remember_token))
  else
    visit signin_path
    fill_in "Email",    with: user.email
    fill_in "Password", with: user.password
    click_button "Sign in"
  end
end

规格/ factories.rb

FactoryGirl.define do
  factory :user do
    name     "Michael Hartl"
    email    "michael@example.com"
    password "foobar"
    password_confirmation "foobar"
  end
end

非常感谢任何协助。

1 个答案:

答案 0 :(得分:1)

问题是userwrong_user都有相同的名称。您可以通过传递唯一名称在规范中解决此问题:

let(:wrong_user) do 
   FactoryGirl.create(:user, name: 'The Wrong Dude', email: "wrong@example.com")
end

或者通过更改your factory to use a sequence

FactoryGirl.define do
  factory :user do
    sequence(:name) {|n| "J. Random User #{n}" }
  end
end