ActionController::UrlGenerationError,没有路由匹配

Posted

技术标签:

【中文标题】ActionController::UrlGenerationError,没有路由匹配【英文标题】:ActionController::UrlGenerationError, No route matches 【发布时间】:2015-11-26 00:24:59 【问题描述】:

我已经阅读了所有我能找到的类似问题,但仍然无法弄清楚我的问题。

# routes.rb
Rails.application.routes.draw do
  resources :lists, only: [:index, :show, :create, :update, :destroy] do
    resources :items, except: [:new]
  end
end

# items_controller.rb (excerpt)
class ItemsController < ApplicationController
  ...

  def create
    @list = List.find(params[:list_id])
    ...
  end
  ...
end

# items_controller_spec.rb (excerpt)
RSpec.describe ItemsController, type: :controller do
   ...

  let!(:list)  List.create(title: "New List title") 

  let(:valid_item_attributes) 
     title: "Some Item Title", complete: false, list_id: list.id 
  

  let!(:item)  list.items.create(valid_item_attributes) 
  describe "POST #create" do
    context "with valid params" do
      it "creates a new item" do
        expect 
          post :create,  item: valid_item_attributes, format: :json  
        .to change(Item, :count).by(1)
      end
    end
  end
  ...
end

还有 RSpec 错误:

1) ItemsController POST #create with valid params creates a new item
     Failure/Error: post :create,  item: valid_item_attributes, format: :json  
     ActionController::UrlGenerationError:
       No route matches :action=>"create", :controller=>"items", :format=>:json, :item=>:title=>"Some Item Title", :complete=>false, :list_id=>1

rake routes 的输出:

list_items     GET    /lists/:list_id/items(.:format)          items#index
               POST   /lists/:list_id/items(.:format)          items#create
edit_list_item GET    /lists/:list_id/items/:id/edit(.:format) items#edit
     list_item GET    /lists/:list_id/items/:id(.:format)      items#show
               PATCH  /lists/:list_id/items/:id(.:format)      items#update
               PUT    /lists/:list_id/items/:id(.:format)      items#update
               DELETE /lists/:list_id/items/:id(.:format)      items#destroy

我可以通过curl 在现有列表中成功创建一个新项目,它告诉我路线没问题,我一定是在测试中做错了。

curl -i -X POST -H "Content-Type:application/json" -H "X-User-Email:admin@example.com" -H "X-Auth-xxx" -d ' "item":  "title": "new item", "complete": "false" ' http://localhost:3000/lists/5/items

我真的很困惑。我的路线设置正确。 ItemsController#create 方法肯定存在。 items_controller_spec.rb 中的其余测试顺利通过。

我是否遗漏了一些明显的东西?

【问题讨论】:

rake routes 对您的物品路线有什么看法? 添加了rake routes 的输出(上图)。 【参考方案1】:

这是我必须对测试进行的修复 (items_controller_spec.rb)。我没有将正确的哈希传递给post create:

  describe "POST #create" do
    context "with valid params" do
      it "creates a new item" do
        expect 
          post :create,  list_id: list.id, item: valid_item_attributes, format: :json  
        .to change(Item, :count).by(1)
      end

      it "assigns a newly created item as @item" do
        post :create,  list_id: list.id, item: valid_item_attributes, format: :json  

        expect(assigns(:item)).to be_a(Item)
        expect(assigns(:item)).to be_persisted
      end
    end # "with valid params"

    context "with invalid params" do
      it "assigns a newly created but unsaved item as @item" do
        post :create,  list_id: list.id, item: invalid_item_attributes, format: :json  

        expect(assigns(:item)).to be_a_new(Item)
      end

      it "returns unprocessable_entity status" do
        put :create,  list_id: list.id, item: invalid_item_attributes, format: :json 

        expect(response.status).to eq(422)
      end
    end # "with invalid params"
  end # "POST #create"

【讨论】:

您的ItemsController 不应该被称为Lists::ItemsController,并位于lists 文件夹中吗?看来您没有遵循 Rails 结构约定。我是,我也有同样的问题。 控制器文件的物理位置与我原来的问题无关。 感谢您的帮助!在我的情况下,我必须删除参数。【参考方案2】:

我收到了同样的错误并以不同的方式修复了它。我正在使用 Rails ~&gt; 5.0.7

路线

这是运行rake routes CONTROLLER=bills的输出:

 Prefix            Verb   URI Pattern                                  Controller#Action
download_site_bill GET    /sites/:site_id/bills/:id/download(.:format) bills#download
        site_bills GET    /sites/:site_id/bills(.:format)              bills#index
                   POST   /sites/:site_id/bills(.:format)              bills#create
     new_site_bill GET    /sites/:site_id/bills/new(.:format)          bills#new
    edit_site_bill GET    /sites/:site_id/bills/:id/edit(.:format)     bills#edit
         site_bill GET    /sites/:site_id/bills/:id(.:format)          bills#show
                   PATCH  /sites/:site_id/bills/:id(.:format)          bills#update
                   PUT    /sites/:site_id/bills/:id(.:format)          bills#update
                   DELETE /sites/:site_id/bills/:id(.:format)          bills#destroy
             bills GET    /bills(/page/:page)(.:format)                bills#index
     download_bill GET    /bills/:id/download(.:format)                bills#download
                   GET    /bills(.:format)                             bills#index
                   POST   /bills(.:format)                             bills#create
          new_bill GET    /bills/new(.:format)                         bills#new
         edit_bill GET    /bills/:id/edit(.:format)                    bills#edit
              bill GET    /bills/:id(.:format)                         bills#show
                   PATCH  /bills/:id(.:format)                         bills#update
                   PUT    /bills/:id(.:format)                         bills#update
                   DELETE /bills/:id(.:format)                         bills#destroy

参考代码

# controllers/admin/bills_controller.rb (excerpt)

module Admin
 class BillsController < ApplicationController

    ...

    def edit
      authorize(@bill)
    end
  end
end

# spec/controllers/admin/bills_controller_spec.rb (excerpt)

require 'rails_helper'

RSpec.describe Admin::BillsController, type: :controller do
 ...

    context 'as an AdminUser' do
      login_admin_user

      it 'loads the bill edit page' do
        request.host = 'admin.example.com'
        get :edit,  id: bill 
        expect(response.status).to eq(200)
      end
    end
  end
end

# Error message

2) Admin::BillsController GET bills/:id/edit as a User redirects to the home page
     Failure/Error: get :edit

     ActionController::UrlGenerationError:
       No route matches :action=>"edit", :controller=>"admin/bills"

可能的解决方案

我尝试了this solution 的变体。它可能对其他人有用,但我收到此错误:

Failure/Error: require 'admin/bills_controller'

LoadError:
  cannot load such file -- admin/bills_controller

解决方案

我在this github issues 中尝试了案例 2,它成功了。我对代码所做的更改是添加此params: use_route: 'admins/bills/', id: bill.id 。以下是此添加的上下文:

context 'as an AdminUser' do
   login_admin_user

   it 'loads the bill edit page' do
     request.host = 'admin.example.com'
     get :edit, params:  use_route: 'admins/bills/', id: bill.id 
     expect(response.status).to eq(200)
   end
 end

【讨论】:

以上是关于ActionController::UrlGenerationError,没有路由匹配的主要内容,如果未能解决你的问题,请参考以下文章