Chris MacNaughton bio photo

Chris MacNaughton

Chris MacNaughton currently works on the Ecosystem Engineering team at Canonical Ltd, focusing on storage technologies for OpenStack deployments.

Email Public Key Twitter Facebook Google+ LinkedIn Github Stackoverflow

I started a side project recently for hosting many sites from within one application. I decided to use Liquid to allow users to create their own site designs. Shopify designed Liquid to give users design freedom without compromising server integrity.

In the Rails app, I have a Theme and a Template model. A theme has many templates, and templates contain the Liquid markup in a content attribute. A theme has a primary template. To render a theme, we use liquid_template = Liquid::Template.parse(primary_template.content) to parse the Liquid content. This call is cacheable and so it is in the app.

After we parse the primary template, we render it with liquid_template.render(options, registers: {file_system: LiquidTemplateSystem.new(self)}). The LiquidTemplateSystem is a class I wrote to handle the nested template functionality. The goal is to call ` inside one template to render another template’s content.

1
2
3
4
5
6
7
8
9
10
class LiquidTemplateSystem
  attr_reader :theme
  def initialize(theme)
    @theme = theme
  end

  def read_template_file(template_path, context)
    theme.templates.where(name: template_path).first.content
  end
end

The initializer just stores the theme that the we initialize the class with. Our file_system instance responds to the method read_template_file to handle the actual include call. read_template_file can accept one or two arguments (take two!). read_template_file must return a valid Liquid string that will render into the including template.