【问题标题】:Rails 3 is "_method=PUT" still supposed to work?Rails 3“_method=PUT”仍然应该工作吗?
【发布时间】:2010-09-17 01:55:22
【问题描述】:

我正在使用 FLEX 3 向 Rails 3 发出 XML 请求。由于 FLEX 3 只提供 POST 和 GET,我必须使用“?_method=PUT”hack 来保持适当的 RESTfulness:

http://127.0.0.1:3000/locator/locator_users/1.xml?_method=PUT

在服务器端它显示为 POST,我得到一个 ActionController::RoutingError (No Route Matches)。

我做了一个 rake 路线,路线就在那里,正确命名空间等等。 这在 Rails 2 中运行良好,所以我有理由相信一定是 Rails 3 发生了变化。在进行了一些搜索之后,人们似乎表示它应该仍然有效。但是,它不适合我。谁能确认或否认 Rails 3 的兼容性?

更新

好的,经过一番修改,我认为这实际上是 Flash Player 10 的问题。Flash PLayer 9 似乎可以在 "_method=" hack 下正常工作,而 10 则不行。请参阅我写的这篇新帖子 (Flash Player 9 vs Flash Player 10 with FLEX 3, ?_method=PUT/DELETE not working?)。

【问题讨论】:

    标签: ruby-on-rails apache-flex


    【解决方案1】:

    部分原因是Rack::MethodOverride 的行为。它不会检查 _method 的查询参数,因此对 http://127.0.0.1:3000/locator/locator_users/1.xml?_method=PUT 的调用不会因此而被正确覆盖。

    我写了一个 piece of Rack middleware 来替换它以解决这个特定问题。

    你所要做的就是 将其添加到Gemfile

    gem 'rack-methodoverride-with-params'
    

    config/environment.rb中交换Rack::MethodOverride

    config.middleware.swap Rack::MethodOverride, Rack::MethodOverrideWithParams
    

    【讨论】:

    • 哇,谢谢。我以为我要疯了……我在责备 Rails 3、Flash Player 和 Flex 4……这是有道理的,但我不敢相信他们会在迁移到 Rack 时忽略这一点?似乎默认情况下这绝对应该是 MethodOverride 的一部分......但话又说回来,我知道什么?
    • Rails 的灯塔上有一张关于它的票rails.lighthouseapp.com/projects/8994/tickets/…
    【解决方案2】:

    如果您可以在请求正文中添加_method=PUT,则无需更换机架中间件。

    如果你不能这样做,那么我遇到了另一个(影响较小的)解决方案,即简单地定义一个自定义路由来完成你正在寻找的东西,例如:

    # config/routes.rb
    post '/locator/locator_users/:id', to: 'locator_users#update', constraints: {_method: 'POST'} # allow http method override
    

    当然,您必须为需要 HTTP 方法覆盖的每个资源添加此路由,但如果您想限制潜在的怪异事件,这可能是一件好事,因为这会破坏 HTTP 语义。

    编辑:如果需要,您可以对 GET 请求执行相同的操作,只需将 post 替换为 get(如果您需要支持 REST over JSONP,这将很有用)。

    【讨论】:

      【解决方案3】:

      您可能需要重写向服务器发出请求的方式。我同时使用 Rails 3、Flex 4 和 Flash 10(但使用 Flex 3 开发的应用程序)并在我的 HTTPService 对象中使用 _method 作为参数(将内容类型保留为默认 application/x-www-form-url )。

      HTTPService 仅支持 GETPOST 请求。如果您在 HTTPService 对象上使用 set useProxy 属性为 true,则可以使用 HEADOPTIONSTRACEDELETE,但前提是您还使用基于服务器的代理服务。如果这不起作用,那么您可能想尝试URLLoaderURLRequest 或实施您自己的自定义解决方案。

      【讨论】:

        猜你喜欢
        • 2010-10-14
        • 2016-06-09
        • 2018-10-09
        • 2018-08-15
        • 2020-07-06
        • 1970-01-01
        • 2019-07-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多