Chúng tôi có thể viếtkhớp Động từ-agnostic trong Sinatra
get '/foo' do
...
end
và
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?
Chúng tôi có thể viếtkhớp Động từ-agnostic trong Sinatra
get '/foo' do
...
end
và
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?
Đ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.
tôi đã sử dụng giải pháp meta-method, có vẻ tốt hơn. – molokoV
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
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.
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.
Đâ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 :) –
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
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
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