在 Liquid 标签调用中使用 Liquid 变量

问题描述 投票:0回答:6

我在 Liquid 中创建了一个自定义链接标签,我试图将 Liquid 变量传递到该标签的调用中,如下所示

{{ assign id = 'something' }} // this value is actual dynamic while looping through data 
{% link_to article: id, text: 'Click Me!' %} // my custom tag

然而,这会导致文章参数作为“id”而不是上面的分配语句中的“something”传入。

有谁知道如何将变量传递到标签调用中?

ruby-on-rails-3 template-engine liquid
6个回答
11
投票

我最近使用 Jekyll 0.11.2 和 Liquid 2.3.0 非常简单地解决了这个问题,方法是将变量的 name 作为标签参数传递。

{% assign v = 'art' %}
{% link_to_article v %}

您还可以在循环中传递控件变量的名称,如上面的

article

Liquid::Tag.initialize
中,
@markup
是第二个参数,即标签名称后面的字符串。分配的变量在
context
的顶层可用。

def render(context)
  "/#{context[@markup.strip]}/"
end

这显然只允许传递一个参数。更复杂的解决方案将解析像

x: 2, y: 3
这样的参数。


8
投票

这解决了我的问题

context[@markup.strip]

我的问题是我希望能够将变量传递给我的自定义 Liquid 标签,如下所示:

{% get_menu main_menu navigation.html settings.theme.id %}

为了做到这一点,我首先将变量字符串拆分为每个空格字符上的不同变量。

class GetMenu < Liquid::Tag
    include ApplicationHelper
    def initialize(tag_name, variables, tokens)

        @variables = variables.split(" ")

        @menu_object = @variables[0]
        @file_name = @variables[1]
        @theme_id = @variables[2]

        super
    end

    def render(context)

        # This is where i use context[@theme_id.strip] to get the variable of "settings.theme.id"
        content = CodeFile.find_by(hierarchy: 'snippet', name: @file_name.to_s, theme_id: context[@theme_id.strip])

        @menu ||= Menu.find_by_slug(@menu_object)

        context.merge('menu' => @menu)

        Liquid::Template.parse(content.code).render(context)

    end

end

Liquid::Template.register_tag('get_menu', GetMenu)

*这只是一个比 Jonathan Julian 上面的答案更丰富的例子


7
投票

这看起来不可能,我的解决方案是将变量名称传递给标签,然后从标签渲染的上下文中获取它。就像这样:

{% for article in category.articles %}
  {% link_to variable: article, text: title %}
{% endfor %}

在我的标签代码(精简)中:

def render(context)
  uri = "article/#{context[@options[:variable]]['id']}"
  "<a href='#{uri}'>#{build_link_text context}</a>"
end

3
投票

如果有一个可以用文字和变量调用的标签就好了

{% assign v = 'art' %}
{% link_to_article v %}

{% link_to_article 'art' %}

{% link_to_article "art" %}

当然还有

{% link_to_article include.article %}

为了做到这一点,我提出了一个辅助函数

def get_value(context, expression)
  if (expression[0]=='"' and expression[-1]=='"') or (expression[0]=="'" and expression[-1]=="'")
    # it is a literal
    return expression[1..-2]
  else
    # it is a variable
    lookup_path = expression.split('.')
    result = context
    puts lookup_path
    lookup_path.each do |variable|
      result = result[variable] if result
    end
    return result
  end
end

在渲染中只需调用辅助函数即可获取文字或变量的值。

def render(context)
  v = get_value(context, @markup.strip)
end

仅供参考,初始化程序看起来像这样:

def initialize(tag_name, markup, tokens)
  @markup = markup
  super
end

0
投票

这并不能严格回答问题,但它可能会帮助其他刚接触 Liquid 的人(比如我自己)并尝试这样的事情。不要实现自定义 tag,而是考虑实现 custom filter。变量在传递到过滤器之前会被解析。

红宝石代码:

module MyFilters
  def link_to_article(input, text)
    "<a href='https://example.org/article/#{input}'>#{text}</a>"
  end
end

Liquid::Template.register_filter(MyFilters)

液体模板:

{% assign id = 'something' %} 
{{ id | link_to_article: 'Click Me!' }}

输出:

<a href='https://example.org/article/something'>Click Me!</a>

您还可以使用变量作为参数。因此以下内容将具有相同的输出:

{% assign id = 'something' %} 
{% assign text = 'Click Me!' %}
{{ id | link_to_article: text }}

过滤器可以有零个或多个(逗号分隔)参数:

{{ 'input' | filter_with_zero_parameters }}
{{ 'input' | filter_with_two_parameters: 'parameter 1', 'parameter 2' }}

0
投票

您可以像 Liquid 本身一样解析变量,例如查看

assign
中的表达式:link

这是一个示例自定义标签,它将整个标记计算为表达式:

require 'liquid/variable'

module Jekyll
  class MyTag < Liquid::Tag
    def initialize(tag_name, markup, parse_context)
      super
      # Parse the variable
      @var = Liquid::Variable.new(markup.strip, parse_context)
    end

    def render(context)
      # Evaluate it within the usage context
      var = @var.render(context)
      "Variable: #{var}"
    end
  end
end

Liquid::Template.register_tag('mytag', Jekyll::MyTag)

您可能想要使用正则表达式从复杂的标记中提取表达式。

© www.soinside.com 2019 - 2024. All rights reserved.