如何获取液体模板中引用的变量列表

时间:2015-04-17 10:08:07

标签: ruby liquid

我正在开发一个使用Liquid模板语言的项目。我有一个iframes页面显示了一些渲染的液体模板和一个编辑器部分。在编辑器部分,用户可以更改液体模板中引用的某些变量的值。此时需要重新渲染一些模板,但我只想重新渲染那些引用已更改变量的模板。

我坚持的观点是如何最好地获得液体模板中引用的变量列表。

所以,如果我这样做:

templates=[]
templates[0] = Liquid::Template.parse("hi {{name}}") 
templates[1] = Liquid::Template.parse("my cat is called {{cat_name}}") 

我想知道'name'被引用但是(例如)'cat'不在模板0中。然后当名称被更改时我可以重新渲染模板[0]并且当cat被更改时我可以重新渲染模板[1]。

我发现我可以获得一个节点列表并检查每个节点以查看它是否是变量,例如templates [0] .root.nodelist [1]有一种'Liquid :: Variable',但变量的'name'方法返回一个'Liquid :: VariableLookup'类型的对象,而这个对象似乎没有从中获取名称的方法,这感觉就像我可能以错误的方式去做。

2 个答案:

答案 0 :(得分:0)

https://github.com/Shopify/liquid/issues/685#issuecomment-471499796之后,您可以使用FileTreeVisitor类。即:

template = Liquid::Template.parse("hi {{name}}")

Liquid::ParseTreeVisitor.for(template.root)
  .add_callback_for(Liquid::VariableLookup) do |node|
  [node.name, *node.lookups].join('.')
end.visit.flatten.compact # => ["name"]

答案 1 :(得分:0)

Liquid::VariableLookup具有name方法。这有效:

markup = 'My name is {{ my_name }} and I live in {{ my_address}}.'
template = Liquid::Template.parse(markup)  
template.root.nodelist
  .select{ |node| node.is_a?(Liquid::Variable)}
  .map{ |var| var.name.name } # => ["my_name", "my_address"]

,但是如果标记具有其他标记,则可能会出现问题。此标记将使解决方案失败:

'My name is {% if condition == "big" %} Big {% endif %} {{ name }}'

它无法在condition标签内捕获变量if。最好坚持使用@asok建议的ParseTreeVisitor解决方案。