【问题标题】:How do I specify a custom POST action when using `match` in my `routes.rb` file?在我的 `routes.rb` 文件中使用 `match` 时,如何指定自定义 POST 操作?
【发布时间】:2012-09-13 13:35:40
【问题描述】:

我正在尝试在控制器中定义自定义 post 操作,但我有一些问题。

这是我的控制器:

module Api
  module V1
    class ExamplesController < ApplicationController
      def create_a
        ...
      end

      def create_b
        ...
      end
    end
  end
end

我希望两个动作/方法都是post 动作。这是我的路线文件中的内容:

namespace :api do
  namespace :v1 do
    match 'examples/create_a', :controller => 'examples', :action => 'create_a'
    match 'examples/create_b', :controller => 'examples', :action => 'create_b'
  end
end

我可以通过get 请求访问这两种方法,但我想基于http post 触发它们。此外,如果我通过rake routes 进行检查,它不会告诉我它是否是 GET、PUT、POST 等方法。它只是空白。如何告诉路由它应该是 post 方法?

浏览器中的post 请求在我的方法中看起来如何?

url: http://localhost:3000/api/v1/examples/create_a.json/create_a
header: Content-Type: application/x-www-form-urlencoded
data: paramA=45&paramB&paramC

这是对我的控制器操作 create_a 执行 post 的正确 URL 模式吗?

【问题讨论】:

  • 尝试“post”而不是“match”。“match”默认获取操作。
  • "match" 应该路由任何类型的请求,至少对我来说是这样。
  • 希望您不介意编辑。我清理了一些小的格式化内容,并将标题改写为 (a) 更具体地针对您的问题,以及 (b) 将其形成一个问题。

标签: ruby-on-rails api controller action


【解决方案1】:

当您想将某种逻辑名称映射到 RESTful 路由和/或为 RESTful 路由创建别名时,通常使用match。你用match 做的事情很好(从某种意义上说它会起作用),但你只是错过了一件小事(我稍后会告诉你)。

首先,让我们看一下match 为路由创建别名的典型用法:

match "profile" => "users#show"

此路由允许您使用 /profileshowuser 的应用程序路径,而不是路径 /users/:id

由于您的代码没有将一个名称映射到另一个名称,因此您不需要match 规则。您对match 的使用会在您的代码中添加不必要的重复,并且在您提供的情况下使用match 比必要的更冗长。下面是一个示例,说明如何在没有match 的情况下编写您的API 路由,并指定它们只能通过post 访问:

namespace :api do
  namespace :v1 do
    post "examples/create_a"
    post "examples/create_b"
  end
end

这是一个示例 match,添加:via 参数(这是您的代码示例中缺少的)来指定HTTP 动词:

namespace :api do
  namespace :v1 do
    match 'examples/create_a' => "examples#create_a", :via => :post
    match 'examples/create_b' => "examples#create_b", :via => :post
  end  #           ^ ---- DUPLICATION ---- ^
end

注意这里的代码重复。由于您没有将一个路径名映射到另一个路径名,因此与 match 版本相比,您输入了两次名称相同的路径

您还会注意到,与您的原始示例代码相比,我去掉了 :controlleraction 参数,因为 Rails 会在您使用表单时自动推断:

"[controller]/[action]" => "[controller]#[action]"

【讨论】:

  • 感谢您的精彩解释!所以我的帖子网址看起来像这样:“localhost:3000/api/v1/examples#create_a”?
  • 关闭。它将是http://localhost:3000/api/v1/examples/create_a(注意控制器和动作名称之间的斜线)。 # 只是路线中的约定。在您的情况下,我将使用第一个示例(没有使用match),因为如您所见,第二个示例指定了两次路线。由于您没有将一个路由名称重新映射到另一个路由名称,因此您不需要match,因此,您可以避免这种重复。
  • 我已经更新了我的答案,以更好地突出 match 示例中不必要的代码重复。
【解决方案2】:

添加 :via => :post 应该可以解决问题。

namespace :api do
  namespace :v1 do
    match 'examples/create_a', :controller => 'examples', :action => 'create_a', :via => :post
    match 'examples/create_b', :controller => 'examples', :action => 'create_b', :via => :post
  end
end

更多信息请访问http://guides.rubyonrails.org/routing.html

【讨论】:

  • 我认为你误解了match 方法的工作。它将允许任何 http 动词与指定的路径一起使用。通过使用:via,您只需对其施加一些限制,将其接受范围限制为您指定的动词。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多