简体   繁体   English

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

[英]Hartl Ruby on Rails Tutorial 9.2.2 Validation failed: Name has already been taken

Have been following the RoR tutorial and am rather stuck on section 9.2.2. 一直在遵循RoR教程,而是停留在9.2.2节。 The GET Request and Patch request tests are failing with the following error messages and I can't see why: 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

I have tried: 我努力了:

rake db:reset rake test:prepare

but makes no difference 但没有区别

following is my authentication_pages_spec.rb 以下是我的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 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 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

spec/support/utilities.rb 规格/支持/ 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

spec/factories.rb 投机/ factories.rb

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

Any assistance would be greatly appreciated. 任何帮助将不胜感激。

The problem is that both user and wrong_user have the same name. 问题是userwrong_user user都具有相同的名称。 You can solve this in the spec by passing a unique name: 您可以在规范中通过传递唯一名称来解决此问题:

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

Or by changing your factory to use a sequence : 或通过更改工厂以使用序列

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM