Sinatra中与动词无关的匹配

我们可以写

get '/foo' do ... end 

 post '/foo' do ... end 

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

这可以通过作为sinatra-contrib的一部分的multi-route扩展来实现:

 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 

您可能也对此function的讨论感兴趣。

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

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

虽然如果你做了很多,当然有必要抽象出来。

Phrogz有一个很好的答案,但如果lambda或包括sinatra-contrib不适合你,那么这个meta方法将达到与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 

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

 # 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 

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

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

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