3

我正在尝试为自学目的构建一个简单的小模板解析器。

我如何构建“模块化”的东西并在其中共享数据?数据不需要从外部访问,它只是内部数据。这是我所拥有的:

# template_parser.rb
module TemplateParser
  attr_accessor :html
  attr_accessor :test_value

  class Base
    def initialize(html)
      @html = html
      @test_value = "foo"
    end

    def parse!
      @html.css('a').each do |node|
        ::TemplateParser::Tag:ATag.substitute! node
      end
    end
  end
end

# template_parser/tag/a_tag.rb
module TemplateParser
  module Tag
    class ATag
      def self.substitute!(node)
        # I want to access +test_value+ from +TemplateParser+
        node = @test_value # => nil
      end
    end
  end
end

根据 Phrogz 的评论进行编辑,
我目前正在考虑类似的事情:

p = TemplateParser.new(html, *args) # or TemplateParser::Base.new(html, *args)
p.append_css(file_or_string)
parsed_html = p.parse!

不应该有太多暴露的方法,因为解析器应该解决非一般问题并且不可移植。至少在这个早期阶段不会。我试图从 Nokogiri 那里窥探一下结构。

4

1 回答 1

2

使用您提供的示例代码,我建议使用组合将实例传递TemplateParser::Baseparse!方法,如下所示:

# in TemplateParser::Base#parse!
::TemplateParser::Tag::ATag.substitute! node, self

# TemplateParser::Tag::ATag
def self.substitute!(node, obj)
  node = obj.test_value
end

您还需要将attr_accessor调用移动到Base类中才能正常工作。

module TemplateParser
  class Base
    attr_accessor :html
    attr_accessor :test_value
    # ...
  end
end

考虑到这是一个试图访问不同类实例属性的类方法这一事实,我现在能想到的任何其他访问test_value方式都会相当复杂。parse!

以上假设每个实例@test_value都需要是唯一的。TemplateParser::Base如果不是这种情况,您可以通过使用类或模块实例变量来简化该过程。

module TemplateParser
  class Base
    @test_value = "foo"
    class << self
      attr_accessor :test_value
    end
    # ...
  end
end

# OR

module TemplateParser
  @test_value = "foo"
  class << self
    attr_accessor :test_value
  end
  class Base
    # ...
  end
end

然后根据实现使用TemplateParser::Base.test_valueOR设置或检索值。TemplateParser.test_value

另外,为了说明这一点,我假设您在此处包含的伪代码不能准确地反映您的真实应用程序代码。如果是这样,那么该substitute!方法是实现简单赋值的一种非常圆的方法。只需node = test_value在内部使用TemplateParser::Base#parse!并跳过往返行程。我相信你知道这一点,但它似乎至少值得一提......

于 2012-05-01T20:36:32.993 回答