【问题标题】:Verb-agnostic matching in SinatraSinatra 中的动词不可知匹配
【发布时间】:2012-01-14 21:50:22
【问题描述】:

我们可以写

get '/foo' do
  ...
end

post '/foo' do
  ...
end

这很好。但是我可以在一个路由中组合多个 HTTP 动词吗?

【问题讨论】:

  • 下面我给你两个解决方案。但是,请注意linked discussion 中的这句话:“我不知道什么时候对相同路径的 GET 或 POST 是正确的应该会导致相同的行为/响应。我一直发现它是情况下,尽管响应可能相同,但行为存在细微差别。这就是模板/视图的用途。它们可能共享的任何功能都可以轻松包装在另一种方法中。" 你确定您真的希望getpost 使用完全相同的路线吗?
  • 谢谢。我仍然希望能够区分路线内的动词。 multi_route 好像不支持这个,不过加起来肯定是微不足道的。
  • 我更新了我的答案,表明您始终可以使用request.env["REQUEST_METHOD"] 来确定您的路线中的动词是什么。您关心的事实使您可能应该拥有两条单独的路线以及一个或多个共享助手和视图的事实更加明显;然而,Sinatra 的美妙之处在于没有一种正确的方法……所以尽情享受吧! :)

标签: ruby sinatra


【解决方案1】:

这可以通过multi-route extension 实现,它是 sinatra-contrib 的一部分:

require 'sinatra'
require "sinatra/multi_route"
route :get, :post, '/foo' do
  # "GET" or "POST"
  p request.env["REQUEST_METHOD"]
end

# Or for module-style applications
class MyApp < Sinatra::Base
  register Sinatra::MultiRoute
  route :get, :post, '/foo' do
    # ...
  end
end

但是,请注意,您可以通过以下方式简单地自己执行此操作而无需扩展:

foo = lambda do
  # Your route here
end
get  '/foo', &foo
post '/foo', &foo

或者更优雅地作为元方法:

def self.get_or_post(url,&block)
  get(url,&block)
  post(url,&block)
end

get_or_post '/foo' do
  # ...
end

你可能也对this discussion on the feature感兴趣。

【讨论】:

    【解决方案2】:

    FWIW,我只是手动完成,没有辅助方法或扩展:

    %i(get post).each do |method|
       send method, '/foo' do 
           ...
       end
     end
    

    虽然如果你经常做这件事,把它抽象出来当然是有意义的。

    【讨论】:

    • 这是迄今为止完美的解决方案。你再次提醒我,这都是 Ruby 和块 :)
    【解决方案3】:

    Phrogz 有一个很好的答案,但如果 lambdas 或包含 sinatra-contrib 不适合您,那么此元方法将获得与 sinatra-contrib 相同的结果:

    # Provides a way to handle multiple HTTP verbs with a single block
    #
    # @example
    #   route :get, :post, '/something' do
    #       # Handle your route here
    #   end
    def self.route(*methods, path, &block)
        methods.each do |method|
            method.to_sym
            self.send method, path, &block
        end
    end
    

    如果您对能够向self 发送任意方法有点担心,那么您可以通过在数组中设置允许方法的白名单,然后检查该符号在数组中的存在来保护自己。

    # Provides a way to handle multiple HTTP verbs with a single block
    #
    # @example
    #   route :get, :post, '/something' do
    #       # Handle your route here
    #   end
    def self.route(*methods, path, &block)
        allowed_methods = [:get, :post, :delete, :patch, :put, :head, :options]
        methods.each do |method|
            method.to_sym
            self.send(method, path, &block) if allowed_methods.include? method
        end
    end
    

    【讨论】:

      【解决方案4】:

      这是一个服务不可用的服务器,我设法在单行上获得了 :)

      require 'sinatra';set port: ARGV[0]||80;%w.get post put patch options delete..map{|v|send(v,'*'){503}}
      

      我实际上是用这个来测试一些客户端代码在面对 503 时的行为。

      【讨论】:

        猜你喜欢
        • 2019-02-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-10-01
        • 1970-01-01
        • 2011-04-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多