将参数传递给 class 方法 Ruby

Passing args to class method Ruby

我是 Jekyll 的新手,Ruby。我正在尝试为 Jekyll 创建自定义插件。到目前为止,我的代码如下。我不明白 Ruby 编译器的行为,现在这段代码不起作用,出现错误 undefined method scan,但是如果我把从 parseinitialize 的所有内容而不是 parse(text),然后开始工作。

完全错误:Liquid Exception: undefined method 'scan' for #<Liquid::Tokenizer:0x005577b047a220> in index.html

module Jekyll
  class CreatePicTag < Liquid::Tag
    def initialize(tag_name, text, tokens)
      super
      parse(text)
    end

    def parse(text)
      pattern = /(?<=\[).+?(?=\])/
      @class = text.scan(pattern)[0]
      @alt = text.scan(pattern)[1]
      @path = text.scan(pattern)[2]
    end
  end
end

在调用之前验证文本是否有任何 scan 方法:

module Jekyll
  class CreatePicTag < Liquid::Tag
    def initialize(tag_name, text, tokens)
      super
      parse(text)
    end

    def parse(text)
      pattern = /(?<=\[).+?(?=\])/
      if text.respond_to?(:scan)
        @class = text.scan(pattern)[0]
        @alt = text.scan(pattern)[1]
        @path = text.scan(pattern)[2]
      end
    end
  end
end

并这样称呼它:

Jekyll::CreatePicTag.new(tag_name, text, tokens)

scan 是在String class 上定义的方法。 undefined method 'scan' 意味着有时局部变量不是 String.

所以,你可以稍微修改parse方法来确保text总是一个String:

def parse(text)
  text = text.to_s
  pattern = /(?<=\[).+?(?=\])/

  @class = text.scan(pattern)[0]
  @alt = text.scan(pattern)[1]
  @path = text.scan(pattern)[2]
end

if I place everything from parse to initialize instead of parse(text), then it starts working

如果您不能将一些简单的代码提取到方法中,则一定是有其他事情发生了。

在这种特定情况下,您将覆盖 Liquid 的内置 parse 方法。此方法是在内部调用的,因此您看到的错误是由 Liquid 引起的,而不是由您自己调用引起的。除非你试图改变 Liquid 的解析,否则你不应该自己实现该方法。 Liquid需要这个方法才能正常工作。

最简单的解决方法是简单地重命名您的方法,例如:

require 'liquid'

class CreatePicTag < Liquid::Tag
  def initialize(tag_name, text, tokens)
    super
    parse_text(text)
  end

  def parse_text(text)
    pattern = /(?<=\[).+?(?=\])/
    @class = text.scan(pattern)[0]
    @alt   = text.scan(pattern)[1]
    @path  = text.scan(pattern)[2]
  end

  def render(context)
    [@class, @alt, @path].join('|')
  end
end

Liquid::Template.register_tag('create_pig', CreatePicTag)
@template = Liquid::Template.parse("{% create_pig [foo][bar][baz] %}")
p @template.render

输出:

foo|bar|baz