Build routes on top of a common base route?

我与影子孤独终老i 提交于 2019-12-07 03:07:41

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!