Reputation: 2294
tl;dr: is there a clean way to nest layouts in Sinatra?
For all pages on my site, I have a common layout.erb which renders a header, a footer, and some other bits.
For a subset of those pages, I would like to use an inner layout which renders a left menu in addition to those common bits.
erb :pageTemplate
executes layout.erb, where yield
executes pageTemplate
erb :pageTemplate
executes layout.erb, where yield
executes specificLayout.erb, where yield
executes pageTemplate.
make sense?
I am open to separate classes, before statements, and any other ruby magic. I am not looking for adding header/footer partials and including them in each layout.
Upvotes: 9
Views: 6806
Reputation: 2294
erb :site_layout, :layout => false do
erb :region_layout do
erb :page
end
end
now, :site_layout
can contain the header and footer, :region_layout
can contain left navigation, and :page
only has to worry about the page content!
Upvotes: 10
Reputation: 12251
erb :pageTemplate
erb :pageTemplate, :layout => :specificLayout
Edit:
One way is to use partials, either via Erb or Sinatra Partial (I'm the maintainer, I don't get any money for this advertisment;)
Pass a flag to the layout that affects rendering:
<html>
<head>
<title>Example</html>
</head>
<body>
<%= erb @specificLayout if @specificLayout %>
<%= yield %>
</body>
</html>
in the route:
@specificLayout = :left_menu
If you new that a whole bunch of routes will want the same flag, then a bit of inheritance will help:
# one big config.ru
require 'sinatra/base'
class MainController < Sinatra::Base
configure do
# lots of shared settings here
enable :inline_templates
set :specificLayout, nil
end
helpers do
# all subclasses get these too
def route
request.path
end
end
get "/" do
erb :home
end
end
class SubWithLeftMenu < MainController
configure do
set :specificLayout, :left_menu
end
get "/" do
erb :something
end
end
map( "/something" ) { run SubWithLeftMenu }
map( "/" ) { run MainController }
__END__
@@ layout
<html>
<head>
<title>Example</title>
</head>
<body>
<p>Route: <%= route %></p>
<%= erb settings.specificLayout if settings.specificLayout %>
<%= yield %>
</body>
</html>
@@ something
<p>Hello!</p>
@@ home
<p>At home</p>
@@ left_menu
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
Running it:
$ bin/rackup config.ru &
[1] 40556
[2013-06-21 22:16:34] INFO WEBrick 1.3.1olumes/RubyProjects/Test/nestinglayouts
[2013-06-21 22:16:34] INFO ruby 1.9.3 (2013-02-06) [x86_64-darwin10.8.0]
[2013-06-21 22:16:34] INFO WEBrick::HTTPServer#start: pid=40556 port=9292
$ curl http://localhost:9292/
127.0.0.1 - - [21/Jun/2013 22:16:47] "GET / HTTP/1.1" 200 99 0.0399
<html>
<head>
<title>Example</title>
</head>
<body>
<p>Route: /</p>
<p>At home</p>
</body>
</html>
$ curl http://localhost:9292/something/
127.0.0.1 - - [21/Jun/2013 22:16:51] "GET /something/ HTTP/1.1" 200 141 0.0064
<html>
<head>
<title>Example</title>
</head>
<body>
<p>Route: /something/</p>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<p>Hello!</p>
</body>
</html>
Upvotes: 4