问题
I have a common base path; say: get /base
where I need to have basic auth performed and working for all sub calls under that path. Say: get /base/foo
and get /base/bar
.
Looking at http://www.sinatrarb.com/intro.html#Helpers suggests I should be able to do this with the use of helpers. I was looking at the pass
helper and use of call
under triggering a new route in the documentation. But, another suggestion I read was using dynamic routing using regexes IE %r{/base/?:(path)?}
or some such. So what about:
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
Has anyone dealt with this kind of thing before? I'm trying to keep it DRY. Of course, I'm not sure the given example would be the best in preserving params.
回答1:
There are a few ways you could do this (these aren't in any order, they're all good):
Namespaces with a before block and a helper
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
Namespace with a condition
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 and a before filter
helpers do
authenticate!
# funky auth stuff
# but no need for `pass`
end
end
before '/base/*' do
authenticate!
end
mapped Apps
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
#…
I'm not sure about the need to DRY up routes using a case statement. If the routes each do something different then I'd just write them out separately as it's a lot clearer and you're duplicating the work Sinatra does in matching routes.
回答2:
How about using before
filters:
before '/base/?*' do
@foo = 'bar'
end
来源:https://stackoverflow.com/questions/15695861/build-routes-on-top-of-a-common-base-route