为什么#create 在此 FactoryGirl 对象上失败?

Why is #create failing on this FactoryGirl object?

我正在尝试测试 Quotes#create controller 操作,但无法理解失败。我正在使用 Devise 和 FactoryGirl 以及 Quotes 模型 belongs_to :user。 rspec 失败消息是 No route matches {:action=>"show", :controller=>"quotes", :id=>nil} missing required keys: [:id]。 FactoryGirl 创建的 Quote 对象传递给用户:

let(:user) { FactoryGirl.create(:user) }
let(:quote) { FactoryGirl.create(:quote, user: user) }

似乎记录没有保存在数据库中,因此记录 [:id] 也不能传回以呈现给显示操作。

感谢任何指导。

quotes_controller.rb

class QuotesController < ApplicationController
  before_action :authenticate_user!, only: [ :new, :create, :edit, :update, :destroy ]
  before_action :owners_only, only: [ :edit, :update, :destroy ]

  def new
    @quote = Quote.new
  end

  def create
    # @quote = @user.quotes.new(quote_params)
    @quote = Quote.new(quote_params)
    if @quote.save
        redirect_to quote_url(@quote), notice: 'Quote request created'
    else
      render :new
    end
  end

  def show
    @quote = Quote.find(params[:id])
  end

  def index
    @quotes = Quote.all
  end

  def edit
  end

  def update
    if @quote.update_attributes(quote_params)
      redirect_to quote_path(@quote)
    else
      render :edit
    end
  end

  def destroy
    @quote.destroy
    redirect_to quotes_path
  end

private

  def quote_params
    params.require(:quote).permit(:gla, :prev_cover, :co_name, :co_number, :postcode, :industry, :lives_overseas, 
                                  :scheme_start_date, :payment_frequency, :commission_level)
  end

  def owners_only
    @quote = Quote.find(params[:id])
    if current_user != @quote.user
      redirect_to quotes_path
    end
  end
end

quote.rb 型号:

class Quote < ApplicationRecord
    belongs_to :user

    enum industry:          [ :financial_services, :architect, :business_consultancy ]
    enum payment_frequency: [ :annually, :monthly ]
end

users.rb:

FactoryGirl.define do
  factory :user do
    sequence(:email) { |n| "test#{}@tes.com" }
    password "12345678"

    factory :user2 do
    end
  end
end

quotes.rb

FactoryGirl.define do
  factory :quote do
    prev_cover true
    sequence(:co_name) { |n| "Acme Co #{n}" }
    co_number 9999
    postcode "al1 1aa"
    industry :financial_services
    lives_overseas true
    scheme_start_date "2018-01-01"
    payment_frequency :monthly
    commission_level 12
    gla 1

    factory :quote2 do
    end
  end
end

quote_controller_spec.rb

RSpec.describe QuotesController, type: :controller do
    describe "signed in user" do

        let(:user) { FactoryGirl.create(:user) }
        let(:quote) { FactoryGirl.create(:quote, user: user) } #user.id not getting through here?

        before do
            sign_in(user)
        end

        describe "POST create" do

            context "valid data" do
                let(:valid_data) { FactoryGirl.attributes_for(:quote) } #user.id not getting through here?
                it "redirects to quote#show" do
                    post :create, params: { quote: valid_data }
                    expect(response).to redirect_to(quote_path(assigns[:quote]))
                end

                it " creates a new quote in the database" do
                    expect {
                        post :create, params: { quote: valid_data }
                    }.to change(Quote, :count).by(1)
                end
            end
        end
    end
end

rspec 输出:

 1) QuotesController signed in user POST create valid data redirects to quote#show
     Failure/Error: expect(response).to redirect_to(quote_path(assigns[:quote]))

     ActionController::UrlGenerationError:
       No route matches {:action=>"show", :controller=>"quotes", :id=>nil} missing required keys: [:id]
     # ./spec/controllers/quotes_controller_spec.rb:46:in `block (5 levels) in <top (required)>'

  2) QuotesController signed in user POST create valid data  creates a new quote in the database
     Failure/Error:
       expect {
        post :create, params: { quote: valid_data }
       }.to change(Quote, :count).by(1)

       expected #count to have changed by 1, but was changed by 0
     # ./spec/controllers/quotes_controller_spec.rb:50:in `block (5 levels) in <top (required)>'

似乎 user_id 没有通过 :valid_data 对象 let(:valid_data) { FactoryGirl.attributes_for(:quote) }。虽然 :quote 对象被赋予了 :user 对象:

let(:user) { FactoryGirl.create(:user) }
let(:quote) { FactoryGirl.create(:quote, user: user) }

就是打不通,我想这就是问题所在,有什么建议吗?

根据您的评论,我建议将您的创建操作更改为:

def create @quote = current_user.quotes.new(quote_params) if @quote.save redirect_to quote_url(@quote), notice: 'Quote request created' else render :new end end