Строить маршруты поверх общего базового маршрута?
У меня есть общий базовый путь; сказать: get /base
где мне нужно выполнить базовую аутентификацию и работать для всех дополнительных вызовов по этому пути. Сказать: get /base/foo
а также get /base/bar
,
Глядя на http://www.sinatrarb.com/intro.html предположить, что я смогу сделать это с помощью помощников. Я смотрел на pass
помощник и использование call
при запуске нового маршрута в документации. Но еще одно предложение, которое я прочитал, было использование динамической маршрутизации с использованием регулярных выражений IE %r{/base/?:(path)?}
или что-то подобное. Так что насчёт:
def '/base'
# do some funky basic auth stuff here
# to work with all request to this common
# base path?
pass
end
def %r{/base/?(path)?} do |path|
case path
when 'foo'
# do something.
when 'bar'
# do something else.
end
# some kind of redirection or template rendering here:
erb :template
end
Кто-нибудь имел дело с такими вещами раньше? Я пытаюсь держать это сухим. Конечно, я не уверен, что данный пример будет лучшим в сохранении параметров.
2 ответа
Есть несколько способов сделать это (они не в любом порядке, все хорошо):
Пространства имен с блоком before и помощником
http://rubydoc.info/gems/sinatra-contrib/1.3.2/Sinatra/Namespace
require 'sinatra/namespace'
class App < Sinatra::Base
register Sinatra::Namespace
namespace "/base" do
helpers do # this helper is now namespaced too
authenticate!
# funky auth stuff
# but no need for `pass`
end
end
before do
authenticate!
end
get "/anything" do
end
get "/you" do
end
get "/like/here" do
end
end
Пространство имен с условием
require 'sinatra/namespace'
class App < Sinatra::Base
register Sinatra::Namespace
set(:auth) do |*roles| # <- notice the splat here
condition do
unless logged_in? && roles.any? {|role| current_user.in_role? role }
redirect "/login/", 303
end
end
end
namespace "/base", :auth => [:user] do
# routes…
end
namespace "/admin", :auth => [:admin] do
# routes…
end
Помощники и фильтр перед
helpers do
authenticate!
# funky auth stuff
# but no need for `pass`
end
end
before '/base/*' do
authenticate!
end
сопоставленные приложения
class MyBase < Sinatra::Base
helpers do
authenticate!
# funky auth stuff
# but no need for `pass`
end
end
before do
authenticate!
end
get "/" do
end
get "/another" do
end
end
# in rackup file
map "/" do
run App1
end
map "/base" do
# every route in MyBase will now be accessed by prepending "/base"
# e.g. "/base/" and "/base/another"
run MyBase
end
#…
Я не уверен насчет необходимости высушивать маршруты, используя инструкцию case. Если каждый из маршрутов делает что-то свое, то я просто выписал бы их по отдельности, так как это намного понятнее, и вы дублируете работу, которую Синатра выполняет в сопоставлении маршрутов.
Как насчет использования before
фильтры:
before '/base/?*' do
@foo = 'bar'
end