2011-12-07 15 views
26

Chúng tôi có thể viếtkhớp Động từ-agnostic trong Sinatra

get '/foo' do 
    ... 
end 

post '/foo' do 
    ... 
end 

đó là tốt. Nhưng tôi có thể kết hợp nhiều động từ HTTP trong một tuyến đường không?

+0

Tôi đưa ra hai giải pháp cho bạn bên dưới. Tuy nhiên, hãy lưu ý câu trích dẫn này từ [thảo luận được liên kết] (https://github.com/sinatra/sinatra/issues/253#issuecomment-1102620): _ "Tôi không biết khi nào nó đúng cho GET hoặc POST Tôi đã luôn luôn tìm thấy nó là trường hợp có một sự khác biệt nhỏ trong hành vi, mặc dù phản ứng có thể giống nhau.Đây là những gì các mẫu/xem được cho. có thể chia sẻ có thể dễ dàng được bọc trong một phương thức khác. "_ Bạn có chắc chắn rằng bạn thực sự muốn chính xác cùng một lộ trình cho cả' get' và 'post'? – Phrogz

+0

Cảm ơn bạn. Tôi vẫn muốn có thể phân biệt giữa các động từ bên trong tuyến đường. Có vẻ như multi_route không hỗ trợ điều này, nhưng nó phải tầm thường để thêm vào. – punund

+0

Tôi đã cập nhật câu trả lời của mình để cho thấy rằng bạn luôn có thể sử dụng 'request.env [" REQUEST_METHOD "]' để xác định động từ nằm bên trong tuyến đường của bạn. Thực tế là bạn quan tâm làm cho nó thậm chí còn rõ ràng hơn rằng bạn có lẽ nên có hai tuyến đường riêng biệt với một hoặc nhiều người chia sẻ và quan điểm; Tuy nhiên, vẻ đẹp của Sinatra là không có cách nào đúng ... hãy tận hưởng! :) – Phrogz

Trả lời

32

Điều này có thể thông qua multi-route extension là một phần của 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 

Tuy nhiên, lưu ý rằng bạn có thể làm điều này chỉ đơn giản là chính mình mà không cần phần mở rộng thông qua:

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

Hoặc thanh lịch hơn làm phương pháp meta:

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

get_or_post '/foo' do 
    # ... 
end 

Bạn cũng có thể quan tâm đến this discussion on the feature.

+0

tôi đã sử dụng giải pháp meta-method, có vẻ tốt hơn. – molokoV

4

Phrogz có một câu trả lời tuyệt vời, nhưng nếu một trong hai lambdas hoặc bao gồm Sinatra-contrib không phải dành cho bạn, sau đó phương pháp meta này sẽ đạt được kết quả tương tự như Sinatra-contrib cho mục đích của bạn:

# 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 

Nếu bạn hơi cảnh giác khi có thể gửi các phương thức tùy ý đến self, thì bạn có thể tự bảo vệ mình bằng cách thiết lập danh sách trắng các phương thức được phép trong một mảng và sau đó kiểm tra sự hiện diện của biểu tượng trong mảng.

# 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

Dưới đây là một máy chủ dịch vụ không có sẵn mà tôi quản lý để có được trên dòng duy nhất :)

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

Tôi thực sự sử dụng này để kiểm tra hành vi của một số mã khách hàng khi đối mặt với 503s.

7

FWIW, tôi chỉ làm điều đó bằng tay, không có phương pháp helper hoặc phần mở rộng:

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

Mặc dù nếu bạn đang làm việc đó rất nhiều tất nhiên nó làm cho tinh thần để trừu tượng mà ra.

+0

Đây là giải pháp hoàn hảo cho đến nay.Bạn nhắc tôi một lần nữa rằng đó là tất cả Ruby và khối :) –