2011-12-07 20 views
26

Podemos escribirjuego verbo-agnóstico en Sinatra

get '/foo' do 
    ... 
end 

y

post '/foo' do 
    ... 
end 

que está muy bien. ¿Pero puedo combinar múltiples verbos HTTP en una ruta?

+0

Doy dos soluciones para usted a continuación. Sin embargo, tenga en cuenta esta cita de la [discusión vinculada] (https://github.com/sinatra/sinatra/issues/253#issuecomment-1102620): _ "No estoy al tanto de cuándo es correcto un GET o POST para el mismo camino debe dar como resultado comportamientos/respuestas idénticas. Siempre he encontrado que hay una diferencia menor en el comportamiento, aunque la respuesta puede ser la misma. Para eso son las plantillas/vistas. Cualquier funcionalidad que tengan puede compartir fácilmente puede ser envuelto en otro método. "_ ¿Estás seguro de que realmente quieres la misma ruta exacta para ambos' get' y 'post'? – Phrogz

+0

Gracias. Me gustaría aún poder diferenciar entre los verbos dentro de la ruta. No parece que multi_route sea compatible con esto, pero debe ser trivial para agregar. – punund

+0

He actualizado mi respuesta para mostrar que siempre puede usar 'request.env [" REQUEST_METHOD "]' para determinar qué es el verbo dentro de su ruta. El hecho de que te importe hace que sea aún más evidente que probablemente deberías tener dos rutas separadas con una o más ayudantes y vistas compartidas; sin embargo, la belleza de Sinatra es que no hay una sola manera correcta ... ¡así que disfruta! :) – Phrogz

Respuesta

32

Esto es posible a través de la multi-route extension que forma parte de 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 

Sin embargo, tenga en cuenta que usted puede hacer esto simplemente a sí mismo sin la extensión a través de:

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

O más elegante como un meta-método:

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

get_or_post '/foo' do 
    # ... 
end 

Usted también podría estar interesado en this discussion on the feature.

+0

utilicé la solución de meta-método, se ve mejor. – molokoV

4

Phrogz tiene una gran respuesta, pero si cualquiera de lambdas o incluyendo Sinatra-contrib no es para ti, entonces este método meta será lograr el mismo resultado que Sinatra-contrib para sus propósitos:

# 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 

Si no está seguro de poder enviar métodos arbitrarios al self, puede protegerse configurando una lista blanca de métodos permitidos en una matriz y luego verificando la presencia del símbolo en la matriz.

# 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 
0

Aquí es un servidor de servicio disponible que he conseguido en una sola línea :)

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

realidad he usado esto para probar el comportamiento de algunos código de cliente en la cara de 503s.

7

Fwiw, acabo de hacerlo de forma manual, sin métodos de ayuda o extensiones:

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

Aunque si lo está haciendo mucho que por supuesto tiene sentido abstracto que fuera.

+0

Esta es la solución perfecta de lejos.Me recuerdas una vez más que todo es Ruby y bloquea :) –