ruby-on-rails - Hartl Ruby on Rails 教程 9.2.2 验证失败 : Name has already been taken

标签 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: "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="d4a3a6bbbab394b1acb5b9a4b8b1fab7bbb9" rel="noreferrer noopener nofollow">[email protected]</a>") }
 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: "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="bfc8cdd0d1d8ffdac7ded2cfd3da91dcd0d2" rel="noreferrer noopener nofollow">[email protected]</a>") }
 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: "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="4f383d2021280f2a372e223f232a612c2022" rel="noreferrer noopener nofollow">[email protected]</a>") }
 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 数据库:重置 rake测试:准备

但没有什么区别

以下是我的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: "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="c0b7b2afaea780a5b8a1adb0aca5eea3afad" rel="noreferrer noopener nofollow">[email protected]</a>") }
      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

规范/支持/实用程序.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

规范/工厂.rb

FactoryGirl.define do
  factory :user do
    name     "Michael Hartl"
    email    "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="3a575359525b5f567a5f425b574a565f14595557" rel="noreferrer noopener nofollow">[email protected]</a>"
    password "foobar"
    password_confirmation "foobar"
  end
end

任何帮助将不胜感激。

最佳答案

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

let(:wrong_user) do 
   FactoryGirl.create(:user, name: 'The Wrong Dude', email: "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="2354514c4d4463465b424e534f460d404c4e" rel="noreferrer noopener nofollow">[email protected]</a>")
end

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

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

关于ruby-on-rails - Hartl Ruby on Rails 教程 9.2.2 验证失败 : Name has already been taken,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24283671/

相关文章:

ruby-on-rails - 如何在 Rails 3.0 金属类中访问 c​​ookies 方法

ruby-on-rails - 尝试销毁对象时设计注销(Rails 3.0.5 和设计 1.1.8)

ruby-on-rails - 如何运行一个简单的 each-do 循环来组合来自不同表的列? (返回率)

css - 删除图像链接的悬停颜色

ruby-on-rails - 允许用户一次登录一台机器

ruby-on-rails - 无法安装调试器 gem

javascript - 使用 NVM 的 Phusion Passenger 和 Rails 应用找不到 JavaScript 运行时

ruby-on-rails - RVM 不识别系统的 ruby​​ 版本

javascript - Ruby 哈希等效于 JavaScript 的对象初始化器 ES6 速记

ruby-on-rails - Rails - 具有自定义框架的 Multi-Tenancy 应用程序