Ruby on rails ActionController::RSpec中带有后期创建操作的UrlGenerationError
我正在写一个电子商务网站,我的一个测试遇到了问题。我对创建操作的测试如下所示:Ruby on rails ActionController::RSpec中带有后期创建操作的UrlGenerationError,ruby-on-rails,ruby,rspec,Ruby On Rails,Ruby,Rspec,我正在写一个电子商务网站,我的一个测试遇到了问题。我对创建操作的测试如下所示: require 'rails_helper' RSpec.describe ReviewsController, type: :controller do describe "POST #create" do before(:each) do user = FactoryGirl.create(:user) login user
require 'rails_helper'
RSpec.describe ReviewsController, type: :controller do
describe "POST #create" do
before(:each) do
user = FactoryGirl.create(:user)
login user
@product = FactoryGirl.create(:product)
post :create, params: { blurb: "Lorem ipsum something or other" }
end
it "renders the product path" do
expect(response).to redirect_to(product_path(@product))
end
end
end
Prefix Verb URI Pattern Controller#Action
root GET / landings#index
new_user_session GET /users/sign_in(.:format) devise/sessions#new
user_session POST /users/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
new_user_password GET /users/password/new(.:format) devise/passwords#new
edit_user_password GET /users/password/edit(.:format) devise/passwords#edit
user_password PATCH /users/password(.:format) devise/passwords#update
PUT /users/password(.:format) devise/passwords#update
POST /users/password(.:format) devise/passwords#create
cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel
new_user_registration GET /users/sign_up(.:format) devise/registrations#new
edit_user_registration GET /users/edit(.:format) devise/registrations#edit
user_registration PATCH /users(.:format) devise/registrations#update
PUT /users(.:format) devise/registrations#update
DELETE /users(.:format) devise/registrations#destroy
POST /users(.:format) devise/registrations#create
product_reviews POST /products/:product_id/reviews(.:format) reviews#create
new_product_review GET /products/:product_id/reviews/new(.:format) reviews#new
product GET /products/:id(.:format) products#show
jewelry GET /jewelry(.:format) products#jewelry
clothing GET /clothing(.:format) products#clothing
decorations GET /decorations(.:format) products#decorations
登录用户行可以工作,我用byebug确认存在有效的用户和会话。在这个迭代中,我得到一个错误,没有路由匹配{:action=>create,:blurb=>Lorem ipsum something或other,:controller=>reviews}
,即使我的rake路线如下所示:
require 'rails_helper'
RSpec.describe ReviewsController, type: :controller do
describe "POST #create" do
before(:each) do
user = FactoryGirl.create(:user)
login user
@product = FactoryGirl.create(:product)
post :create, params: { blurb: "Lorem ipsum something or other" }
end
it "renders the product path" do
expect(response).to redirect_to(product_path(@product))
end
end
end
Prefix Verb URI Pattern Controller#Action
root GET / landings#index
new_user_session GET /users/sign_in(.:format) devise/sessions#new
user_session POST /users/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
new_user_password GET /users/password/new(.:format) devise/passwords#new
edit_user_password GET /users/password/edit(.:format) devise/passwords#edit
user_password PATCH /users/password(.:format) devise/passwords#update
PUT /users/password(.:format) devise/passwords#update
POST /users/password(.:format) devise/passwords#create
cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel
new_user_registration GET /users/sign_up(.:format) devise/registrations#new
edit_user_registration GET /users/edit(.:format) devise/registrations#edit
user_registration PATCH /users(.:format) devise/registrations#update
PUT /users(.:format) devise/registrations#update
DELETE /users(.:format) devise/registrations#destroy
POST /users(.:format) devise/registrations#create
product_reviews POST /products/:product_id/reviews(.:format) reviews#create
new_product_review GET /products/:product_id/reviews/new(.:format) reviews#new
product GET /products/:id(.:format) products#show
jewelry GET /jewelry(.:format) products#jewelry
clothing GET /clothing(.:format) products#clothing
decorations GET /decorations(.:format) products#decorations
当我将post行更改为如下所示:
post:create,user:user,params:{blurb:Lorem ipsum something or other}
我获取的密钥不存在:user。这是我的模型:
class Review < ApplicationRecord
belongs_to :user
belongs_to :product
validates_presence_of :blurb
end
我正在使用Ruby 2.4.0和Rails 5.1,如有任何帮助,将不胜感激
//编辑
我将FactoryGirl::Syntax::方法添加到我的RSpec配置中,并进行重构以使用let和product_id,如下所示:
require 'rails_helper'
RSpec.describe ReviewsController, type: :controller do
let(:user) { create(:user) }
let(:product) { create(:product) }
describe "GET #new" do
before(:each) do
get :new, params: { product_id: product.id }
end
it "renders the new template" do
expect(response).to render_template(:new)
end
it "returns a 200 status code" do
expect(response).to have_http_status(200)
end
end
describe "POST #create" do
before do
login user
end
context "with valid attributes" do
let(:action) do
post :create, product_id: product, params: { review: FactoryGirl.attributes_for(:review) }
end
it "creates a review" do
expect { action }.to change(product.reviews, :count).by(+1)
end
it "redirects to the review" do
action
expect(response).to redirect_to product.reviews.last
end
end
end
end
我没有收到错误未知关键字:product\u id。我已在控制器参数中将其列为白名单,不确定从这里转到何处。基于您的操作路线/products/:product\u id/reviews.:您需要传递product\u id的格式 因此,请将规格更改为:
post :create, product_id: @product.id, params: { blurb: "Lorem ipsum something or other" }
您可能需要在ReviewController中将actions:new更改为actions:create
您还可以将config.include FactoryGirl::Syntax::Methods行添加到rails\u helper.rb中,这样您就不必每次调用FG方法时都编写FactoryGirl:
RSpec.configure do |config|
...
config.include FactoryGirl::Syntax::Methods
...
end
以下是基于您的行动路线/产品的:产品id/评论:您需要传递产品id的格式 因此,请将规格更改为:
post :create, product_id: @product.id, params: { blurb: "Lorem ipsum something or other" }
您可能需要在ReviewController中将actions:new更改为actions:create
您还可以将config.include FactoryGirl::Syntax::Methods行添加到rails\u helper.rb中,这样您就不必每次调用FG方法时都编写FactoryGirl:
RSpec.configure do |config|
...
config.include FactoryGirl::Syntax::Methods
...
end
以下是您的路线需要产品id参数。除此之外,你的测试非常需要适当的结构。如果想查看如何测试标准crud控制器的示例,可以在rails中使用scaffold命令
require 'rails_helper'
RSpec.describe ReviewsController, type: :controller do
# use let to setup given variables
let(:user) { FactoryGirl.create(:user) }
let(:product) { FactoryGirl.create(:product) }
describe "POST #create" do
before do
login user
end
context "with valid attributes" do
let(:action) do
post :create, params: { product_id: product, review: FactoryGirl.attributes_for(:review) }
end
it "creates a review" do
expect { action }.to change(product.reviews, :count).by(+1)
end
it "redirects to the review" do
action
expect(response).to redirect_to product.reviews.last
end
end
context "with invalid attributes" do
# ...
end
end
end
您应该将身份验证移到一个before过滤器,并减少重复,这样您就可以将控制器压缩到相当低的程度:
# call this whatever you want but DRY it out.
class ApplicationController < InheritedResources::Base
before_action :authenticate!
def authenticate!
redirect_to new_user_session_path and return false unless user_signed_in?
end
end
class ReviewsController < ApplicationController
respond_to :html
actions :new
def create
@product = Product.find(params[:product_id])
@review = @product.reviews.new(review_params) do |r|
r.user = current_user
end
# don't use .save! here - it will raise an exception
# if the record is not valid
if @review.save
redirect_to product_path(@product)
else
render :new
end
end
private
def review_params
# only permit the params that actually should be assigned to the model!
params.require(:review).permit(:blurb)
end
end
您的路线需要产品标识参数。除此之外,你的测试非常需要适当的结构。如果想查看如何测试标准crud控制器的示例,可以在rails中使用scaffold命令
require 'rails_helper'
RSpec.describe ReviewsController, type: :controller do
# use let to setup given variables
let(:user) { FactoryGirl.create(:user) }
let(:product) { FactoryGirl.create(:product) }
describe "POST #create" do
before do
login user
end
context "with valid attributes" do
let(:action) do
post :create, params: { product_id: product, review: FactoryGirl.attributes_for(:review) }
end
it "creates a review" do
expect { action }.to change(product.reviews, :count).by(+1)
end
it "redirects to the review" do
action
expect(response).to redirect_to product.reviews.last
end
end
context "with invalid attributes" do
# ...
end
end
end
您应该将身份验证移到一个before过滤器,并减少重复,这样您就可以将控制器压缩到相当低的程度:
# call this whatever you want but DRY it out.
class ApplicationController < InheritedResources::Base
before_action :authenticate!
def authenticate!
redirect_to new_user_session_path and return false unless user_signed_in?
end
end
class ReviewsController < ApplicationController
respond_to :html
actions :new
def create
@product = Product.find(params[:product_id])
@review = @product.reviews.new(review_params) do |r|
r.user = current_user
end
# don't use .save! here - it will raise an exception
# if the record is not valid
if @review.save
redirect_to product_path(@product)
else
render :new
end
end
private
def review_params
# only permit the params that actually should be assigned to the model!
params.require(:review).permit(:blurb)
end
end
属于:产品在您的模型中,而不是控制器中!说得好!幸运的是,这是我的复制粘贴错误;您还需要使用before_action回调进行身份验证,而不是在控制器上复制相同的逻辑。before_to:产品在您的模型中,而不是控制器中!说得好!幸运的是,这是我的复制粘贴错误;您还需要使用before_action回调进行身份验证,而不是在所有控制器上复制相同的逻辑。添加product_id属性会产生以下错误:未知关键字:product_id。我将确保它在控制器中被列入白名单,并对此进行处理。添加product_id属性会产生以下错误错误:未知关键字:product_id。我将确保它在控制器中被列入白名单,并对此进行处理。感谢语法提示,我对此表示感谢。添加product_id属性会产生以下错误:unknown关键字:product_id.Ah right-在rails 5中,需要将其放入params中。编辑。我把它放在评论参数中,但没有骰子。不,你需要在规范中的参数键中传递它。帖子:创建,参数:{product\u id:product….您似乎也对强参数的作用感到困惑。它基本上可以让您过滤出应该分配给模型的参数的白名单。其余的被丢弃。这不是因为指定了客户端可以发送的每个参数。感谢语法提示,我很感激。添加product\u id属性产生以下错误:未知关键字:product_id.Ah right-在rails 5中,您需要将其放入params.edited中。我将其放入reviews_params中,但没有骰子。不,您需要在规范中的params键中传递它。post:create,params:{product_id:product….您似乎也对强参数的作用感到困惑。它基本上可以让您过滤出一个应分配给模型的参数白名单。其余的参数将被丢弃。这不是为了指定允许客户端发送的每个参数。