satyrsynth
satyrsynth

Reputation: 419

Mapping routes to layouts in Sinatra, help me clean this up

I'm a front end guy getting more and more into using sinatra. I'm building an app currently and am trying to find an elegant way to DRY up the routes in my myapp.rb file.

Currently I have these routes:

get '/' do
  haml :content 
end

get '/content' do
  haml :content, :layout => :empty
end

get '/show_layout' do
  haml :show_layout
end

get '/conversion' do
  haml :conversion, :layout => :empty
end

get '/optout' do
  haml :optout, :layout => false
end

get '/terms' do
  haml :terms, :layout => :empty
end

With regards to the templates, I know I can do something like this to combine them:

get '/:name' do
  haml params[:name].to_sym
end

But what about the layouts? There are only 2 layouts here, layout.haml and empty.haml (:layout, and :empty), 3 if you count :layout => false

Is this something that is best done using a hash? Something like:

layout_map = {
  "" => "",
  :content => "",
  :show_layout => "",
  :conversion => :empty,
  :optout => false,
  :terms => :empty    
}

get '/:name' do
  haml params[:name].to_sym, :layout => layout_map[:name]
end

Seems like its on the right track but I can't get it to work properly.

Thanks for all your help.

Upvotes: 1

Views: 282

Answers (2)

satyrsynth
satyrsynth

Reputation: 419

Thanks for all your help everyone. Ended up going with this as my solution due to some other requirements of the app.

get "/:base_route/" do
  haml :"#{params[:base_route]}/content", :layout => :"#{params[:base_route]}/layout"  
end

get "/:base_route/:name" do
  layout_map = {
    :landing => :layout,
    :content => :empty,
    :show_layout => :layout,
    :conversion => :empty,
    :terms => :empty    
  }        
  haml :"#{params[:base_route]}/#{params[:name]}", :layout => :"#{params[:base_route]}/#{layout_map[params[:name].to_sym]}"
end

Upvotes: 0

three
three

Reputation: 8478

You can use your:

get '/:name' do
  haml params[:name].to_sym
end

plus a before route that will set your layout:

before '/:name' do
  layout_map = {
    :content => "",
    :show_layout => "",
    :conversion => :empty,
    :optout => false,
    :terms => :empty    
  }
  set :layout => layout_map[params[:name]]
end

This will set your layout according to params[:name] with every call. But be careful with .simming every route. If someone calls many 404s you create lots and lots of dead symbols which are not garbage collected and eventually will crash your app. Better do this:

get '/:name' do
  halt 404 unless File.exist?("views/#{params[:name]}.haml")
  time = File.stat("views/#{params[:name]}.haml").ctime
  last_modified(time)
  haml params[:name].intern
end

This will only create a symbol for params[:name] if there is a file with that name. So you're on the safe side because the symbol already exists.

Upvotes: 2

Related Questions