为什么#create在这个FactoryGirl对象上失败了?

时间:2017-06-05 12:53:10

标签: ruby-on-rails-3 authentication devise factory-bot

我正在尝试测试引号#create控制器操作,但我无法理解故障。我正在使用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]也不能传回来呈现给show动作。

任何指导意见。

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) }

它只是没有通过,我认为这是问题在哪里,任何建议?

1 个答案:

答案 0 :(得分:1)

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

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