Passing a variable to access a hash
When attempting to fetch values from a hash by passing a variable, I'm getting errors when trying to render:
{% assign value = hash[variable] %}
Example
For example this elixir test passes with no issues when giving the hash a literal value:
test "fetch hash with variable" do
template = """
{% assign greeting = greetings['greeting_b'].text %}
<p>{{ greeting }} world</p>
"""
data = %{
"default" => "greeting_c",
"greetings" => %{
"greeting_a" => %{"text" => "Hello"},
"greeting_b" => %{"text" => "Hey!"},
"greeting_c" => %{"text" => "Yo!"}
}
}
markup = template |> Solid.parse!() |> Solid.render!(data) |> to_string()
assert """
<p>Hey! world</p>
""" == markup
end
However when changing the template to:
{% assign greeting = greetings[default].text %}
<p>{{ greeting }} world</p>
I get a render error:
%Solid.TemplateError{
message: "Reason: expected end of string, line: 1, header: {% assign greeting = ",
line: {1, 0},
reason: "expected end of string",
header: "{% assign greeting = "
}
Likewise if I define the variable above it with an assign (update: fixed template typo, corrected parse error):
{% assign default = "greeting_a" %}
{% assign greeting = greetings[default].text %}
<p>{{ greeting }} world</p>
The above gives a:
%Solid.TemplateError{
message: "Reason: expected end of string, line: 2, header: {% assign default = \"",
line: {2, 36},
reason: "expected end of string",
header: "{% assign default = \""
}
Wondering if this is expected behaviour or maybe a bug?
:thinking: I could be wrong but I don't think this is valid Liquid:
{% assign greeting = greetings[default].text %}
Have you tried doing this with the Liquid gem in ruby? Do you get the expected result or Liquid just ignores the [default] bit?
From memory the [] access is just for positional access like [1], [2]. I don't remember if there was a way to do what you want without a custom filter :thinking:
I think if there is a bug here is that we should still allow non-numbers but just ignore like Liquid does :thinking:
Examples: https://github.com/edgurgel/solid/blob/main/test/integration/objects_test.exs#L27-L34
Ah I see, I think it is somewhat hinted in the official liquid page that this syntax should work however the example is scoped down to the EmptyDrop return value:
{% assign variable = "hello" %}
{% assign page_1 = pages[variable] %}
Thanks for the pointer! Will try to setup the liquid gem from ruby and get back with results.
So I tried this in a Ruby 3.2.2 version in my machine.
- Installed the liquid gem with
gem install liquid. - Launched
irland ran this script.
require 'liquid'
template = "\n" +
"{% assign greeting = greetings[default] %}\n" +
"<p>{{ greeting }} world</p>"
hash = {
'default' => 'special',
'greetings' => {
'default' => 'Hello',
'special' => 'Yo!' }
}
Liquid::Template.parse(template).render(hash, {})
Which renders the string:
"\n\n<p>Yo! world</p>"
Thanks for the detailed report! Yeah definitely something we should support then!
Any update on when this might be released? We’d love to add support here for dynamic hash lookups in our liquid templating
Oh yup will get this release later today! 👍
https://github.com/edgurgel/solid/releases/tag/v0.17.0
Thanks @jmks !