【问题标题】:Rails routing: format constraints when none is specifiedRails 路由:未指定时的格式约束
【发布时间】:2013-10-19 23:43:32
【问题描述】:

For Reasons™,我想让一个控制器处理 html 请求,另一个处理 json api 请求。

我的路线中有这个:

scope module: :api, as: :api do
  constraints format: :json do
    resources :users
  end
end
constraints format: :html do
  resources :users
end

当 url 带有后缀时,这很有效:/users.json 通过我的 Api::UsersController à la api_users_path; /users.html 通过我的UsersController à la users_path

但是,当 url 中没有后缀时,这不会像预期的那样运行。将约束实现为 lambda 显示出问题:

#=> visiting /users

scope module: :api, as: :api do
  constraints ->(request){ puts "In api: #{request.format}"; request.format == :json } do
    resources :users
  end
end
constraints ->(request){ puts "In html: #{request.format}"; request.format == :html } do
  resources :users
end

#=> In api: text/html
#=> (request.format == :json) => false

但它最终出现在 api 控制器中。

如果没有任何约束匹配,则不要摆弄自定义约束类或 lambdas 或任何东西来阻止 rails 选择定义的第一个路由。

我找不到编写约束条件的方法,该约束条件可以在 url 缺少后缀时捕获,而且我觉得我不应该这样做——当我导航到 /users 时,request.format == :html 报告为真.为什么第二个约束没有捕捉到这一点?

另外,虽然我可以通过改变这两个的顺序来“解决”这个问题,但我更想知道为什么我的约束不能正常工作。

有谁知道如何以不同的方式强制执行这些约束以有效地打开任何格式,而不仅仅是 url 后缀,或者有一个不包含格式后缀的显式约束?

【问题讨论】:

  • 第二个约束无法捕捉到路由不匹配
  • 为什么不简单地为您的 api 中的所有操作设置请求格式?
  • 实际上,既然你命名了你的控制器,我不明白你为什么需要路由约束
  • 我正在尝试按格式进行路由。除了防止链接助手(api_users_path vs users_path)的名称空间冲突之外,命名空间对此没有任何影响,因为这些路由除了约束之外是相同的。有没有办法在我的问题中澄清这个意图?
  • 哦,明白了,你放了一个模块但没有命名空间!好的,所以我总是帮不了你,但我的 api 在 api./api

标签: ruby-on-rails routing ruby-on-rails-4 rails-routing


【解决方案1】:

将无后缀的默认格式设置为 json 应该可以满足您的需求。

scope module: :api, as: :api, defaults: { format: :json} do
  constraints format: :json do
    resources :users
  end
end

只有明确的 .html 后缀请求才会在此资源中结束

resources :users

【讨论】:

    【解决方案2】:

    扩展 Jeremy 的答案.. 如果您在路由的 api 范围之前插入用户默认的 html 路由会怎样?

    喜欢,

    resources :users
    scope module: :api, as: :api do
      constraints format: :json do
        resources :users
      end
    end
    

    奇怪的是,这对我有用!

    【讨论】:

    • 改变顺序,不管有没有限制,确实工作,这就是我现在正在做的。我提到过:"While I could "fix" this by changing the order of these two, I'd much rather know why my constraints aren't working right.",因为虽然覆盖路由不是我的职责,但我宁愿让以 API 为中心的应用程序的 API 路由优先。
    • 哇……我的错!快速解决了这个问题..但是考虑到 Ruby 是一种过程驱动的语言..这应该是最好的解决方案。
    【解决方案3】:

    我认为您不需要第二个约束块(:html 的那个)。我认为这应该做你想做的:

    scope module: :api, as: :api do
      constraints format: :json do
        resources :users
      end
    end
    
    resources :users
    

    【讨论】:

    • 令人惊讶的是,没有!这仍然将/users 作为text/html 推迟到 api 控制器,触发 406。
    • 创建一个干净的应用程序表明这是可行的,因此我的应用程序堆栈中有一些东西非常混乱。当我弄清楚时,我会在这里发布,但由于这个赏金即将到期......
    • 啊,错过了一分钟。 ://
    猜你喜欢
    • 2013-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-27
    • 2012-09-07
    • 1970-01-01
    • 2014-04-25
    • 1970-01-01
    相关资源
    最近更新 更多