【问题标题】:No route match in controller spec for my complex route我的复杂路由的控制器规范中没有路由匹配
【发布时间】:2012-08-18 08:33:59
【问题描述】:

我有这条路线:

resources :items, path: 'feed', only: [:index], defaults: { variant: :feed }

嵌套在 api 和 v1 命名空间中。 (request_source 参数来自 Api 命名空间)。

我想在我的控制器规范中测试索引操作。我试过了:

get :feed, community_id: community.id, :request_source=>"api"

不起作用,所以也起作用:

get :index, community_id: community.id, :request_source=>"api", variant: 'feed'

说:

ActionController::RoutingError:
   No route matches {:community_id=>"14", :request_source=>"api", :variant=>"feed", :controller=>"api/v1/items"}

-------编辑---------

我之所以要使用变体将参数发送到控制器是因为我拥有所有这些路由:

    resources :items, path: 'feed',    only: [:index], defaults: { variant: 'feed' }
    resources :items, path: 'popular', only: [:index], defaults: { variant: 'popular' }

然后,在 ItemsController 中,我有一个用于索引操作的前置过滤器“get_items”:

def get_items
  if params[:variant] == 'feed'
     ....
elsif params[:variant] == 'popular'
    ....
end

【问题讨论】:

  • 异常的回溯是什么?

标签: ruby-on-rails rspec controller routes


【解决方案1】:

看起来问题出在定义defaults: { variant: :feed } 上。能否请您详细说明您试图用它来完成什么。

我创建了一个应用程序来测试您所拥有的内容,并在config/routes.rb 中使用以下内容

namespace :api do
  namespace :v1 do
    resources :items, path: 'feed', only: :index
  end
end

我在运行 rake routes 时得到了这个。

$ rake routes
api_v1_items GET /api/v1/feed(.:format) api/v1/items#index

更新:params 变量设置默认值,用于在您的操作中使用的路由中未定义的内容。

params[:variant] ||= 'feed'

更新 2:您可以像这样在前置过滤器中有条件地分配 params[:variant]

class ItemsController < ApplicationController
  before_filter :get_variant

  # or more simply
  # before_filter lambda { params[:variant] ||= 'feed' }

  def index
    render text: params[:variant]
  end

private      

  def get_variant
    # make sure we have a default variant set
    params[:variant] ||= 'feed'
  end
end

【讨论】:

  • 我们有很多通往 items#index 的路线。默认值:{ variant: :xxx } 用于设置参数,该参数将根据请求的路由确定索引操作的行为。
  • @Alain 看起来defaults 哈希旨在设置路由参数的默认值。如:id:format。查看我的更新
  • 问题是,我们有 3 条路由:feed、popular 和 index,它们都使用完全相同的代码(来自 index 的那个),我们只需要在执行 index 动作之前做一些设置过滤器查看 :variant 参数。这允许我们重用索引操作,而无需在控制器中编写任何额外的代码。就像我们必须创建每个路由并在每个控制器操作中添加代码以呈现索引页面一样。如果你告诉我没有办法让这条路线工作,我会等几天(希望你错了!;-))然后给你赏金。
  • @Alain 我知道你想等待,我很想看看你是否也可以从路由中设置默认的params。但是,只是为了让您知道,可以有条件地在 before_filter 中设置 params。请参阅我的第二次更新。
【解决方案2】:

我必须设置一个默认变体的一个想法可能是允许路径是动态的。不要将variant 设置为查询字符串,而是将其用作实际路径本身的一部分。此方法不需要控制器中的前置过滤器。

namespace :api do
  namespace :v1 do
    root :to => 'items#index', :defaults => { :variant => 'feed' }
    get ':variant' => 'items#index', :defaults => { :variant => 'feed' }
  end
end

然后您可以访问网站上的不同区域

GET "http://localhost:3000/api/v1" # params[:variant] == 'feed'
GET "http://localhost:3000/api/v1/feed" # params[:variant] == 'feed'
GET "http://localhost:3000/api/v1/popular" # params[:variant] == 'popular'

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-23
    • 1970-01-01
    相关资源
    最近更新 更多