`assign` tag mutates cached template context
Nobody has claimed this yet.
- Dominant language
- Ruby
- Stars
- 11.9k
- Forks
- 1.5k
- Avg merge
- 17h 55m
- Merged PRs (30d)
- 3
Description
The source-code documentation suggests caching Liquid templates and using them to render multiple data:
https://github.com/Shopify/liquid/blob/0847bf560fbb99d20410408c27d750b7b412d9fa/lib/liquid/template.rb#L9-L10
Fair enough. But if a cached template contains an assign tag, rendering it mutates the template's context for subsequent renders.
This may be illustrated with the following Ruby script and its output:
Script
require 'liquid'
CONTENTS = <<~TEXT
Neo: "I am just {{ title | default: 'a regular guy' }}.."
{%- if agent == ' Smith' %}{% assign title = 'A DISEASE' %}{% endif %}
{{ agent }}: "Neo, you're {{ title | default: 'The One' }}!!"
TEXT
TEMPLATE = Liquid::Template.parse(CONTENTS)
puts TEMPLATE.render("agent" => "Morpheus")
puts TEMPLATE.render("agent" => " Trinity")
puts TEMPLATE.render("agent" => " Oracle")
puts TEMPLATE.render("agent" => " Trinity")
puts TEMPLATE.render("agent" => " Smith")
puts TEMPLATE.render("agent" => " Oracle")
puts TEMPLATE.render("agent" => " Trinity")
puts TEMPLATE.render("agent" => "Morpheus")
Output
Neo: "I am just a regular guy.."
Morpheus: "Neo, you're The One!!"
Neo: "I am just a regular guy.."
Trinity: "Neo, you're The One!!"
Neo: "I am just a regular guy.."
Oracle: "Neo, you're The One!!"
Neo: "I am just a regular guy.."
Trinity: "Neo, you're The One!!"
Neo: "I am just a regular guy.."
Smith: "Neo, you're A DISEASE!!"
Neo: "I am just A DISEASE.."
Oracle: "Neo, you're A DISEASE!!"
Neo: "I am just A DISEASE.."
Trinity: "Neo, you're A DISEASE!!"
Neo: "I am just A DISEASE.."
Morpheus: "Neo, you're A DISEASE!!"
Workaround
The workaround is to explicitly reset the assigned variable in an else tag
{% if foo %}
{% assign bar = 'lipsum' %}
{% else %}
{% assign bar = '' %} (or {% assign bar = false %})
{% endif %}
But I feel that the workaround is just a hack and that there shouldn't be a persisting mutation in the first place.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the caching guidance in lib/liquid/template.rb at the linked lines, then reproduce the behavior using the Ruby script in the issue. Trace how repeated render calls handle assign state; done means rendering the same parsed template no longer carries an assigned value into later renders.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- ruby
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100