Layouts in a non-rails web app

69 views
Skip to first unread message

Joe Fiorini

unread,
Jun 26, 2009, 5:54:08 PM6/26/09
to Liquid Templates
I'm writing a web app in Rack. Not Rails, not Sinatra, just Rack :)

I'm trying to use Liquid as my view engine as it seems to be the
closest I can get to clean separation of view logic and business
logic. However, it seems the only way to use layouts and define
{{ content_for_layout }} is if I'm using Rails (content_for_layout
gets processed on ActionView::Base). Is there something I'm missing or
is there no way currently to create layouts and define content
sections with Liquid outside of Rails?

Thanks!
Joe Fiorini

Tobias Lütke

unread,
Jun 27, 2009, 6:11:31 PM6/27/09
to liquid-t...@googlegroups.com
Well, we use liquid in a lot of non-rails environments even at
Shopify. For example, our designer toolkit vision doesn't use rails
but straight up webrick to make it easier to ship. Nothing in liquid
requires rails.

Liquid doesn't actually support layouts directly. This is actually a
good thing. What we do is render the content templates first and then
render the layout afterwards while assigning the html result of the
first render run to the variable name content_for_layout.

layout = Liquid::Template.parse(layout)

content = Liquid::Template.parse(content)

return layout.render 'content_for_layout' => content.render


Regards
-- tobi

Joe Fiorini

unread,
Jun 28, 2009, 11:29:02 AM6/28/09
to Liquid Templates
Thanks Tobi! That's so dang simple it should have been obvious. Have
you considered implementing inheritable templates and the block tag
like Django's view engine? Is there a particular reason not to?

Thanks again!
Joe

Tobias Lütke

unread,
Jun 28, 2009, 2:29:09 PM6/28/09
to liquid-t...@googlegroups.com
We actually already implement the include tag, you just have to set a
Liquid::Template.file_system class to make it work ( Liquid is safe by
default, so no /etc/passwd inclusions in templates, so there is no
default file_system installed ).

I'm actually not too familiar with django's blocks. Would you be able
to compare it to liquid's {% include %} tag? Maybe we can implement
blocks on top of it. Shopify uses the {{content_for_layout}} system
for theming and it's been a big success as it's very simple to
understand for customers so we are pretty married to that approach but
it's in no way mutually exclusive to include blocks and we are
planning to enable {% include %} soon. I like to stay in sync with
Django's terminology so maybe we should switch.


Regards
-- tobi

Joe Fiorini

unread,
Jun 28, 2009, 5:10:58 PM6/28/09
to Liquid Templates
Excellent points Tobi. I like the {{content_for_layout}} suggestion,
although I have a couple concerns I will address later in this
message.

When I talk about Django, I want to stress that I have no practical
experience with the framework myself, just the word of some Python-
influenced friends and the Django docs.

That said, in Django you can tell a template to inherit from another
template that contains its layout and has placeholders for the child
template's content. It looks something like this:

base.html:

<html>
<head>
<title>{% block title %}{% endblock %}</title>
</head>
<body>
<img src="sitelogo.gif" alt="Logo" />
{% block content %}{% endblock %}
</body>
</html>

article_detail.html:

{% extends "base.html" %}

{% block title %}Articles for {{ year }}{% endblock %}

{% block content %}
<h1>Articles for {{ year }}</h1>

{% for article in article_list %}
<p>{{ article.headline }}</p>
<p>By {{ article.reporter.full_name }}</p>
<p>Published {{ article.pub_date|date:"F j, Y" }}</p>
{% endfor %}
{% endblock %}

(taken from the Django docs: http://docs.djangoproject.com/en/dev/intro/overview/#design-your-templates)

So your templates become nothing but a collection of blocks that get
pushed into their placeholders. I like this in that the views are
declaring their own layouts rather than some other layer doing it for
them; this is a great adherence to SRP and improves clarity.

Please correct me if I'm wrong; it looks like Liquid's include tag is
similar to Rails partials. I'd be more apt to compare Django's blocks
to Rails yield :placeholder/content_for :placeholder instead, except
that this uses no magic. Every block is defined with a name. The
controller, or other rendering class, isn't making view decisions like
which layout to use.

At the moment the {{content_for_layout}} system should work well for
my needs. However, having inheritable templates would go a long way
towards improving code clarity. And there's no reason both patterns
can't persist. Since {{content_for_layout}} merely makes use of local
variables and isn't a feature in and of itself.

Just out of curiosity, did Liquid arise out of Django or was there
some common ancestor of the two?

Thanks!
Joe
Reply all
Reply to author
Forward
0 new messages