我正在尝试为自学习目的构建一个简单的小模板解析器。
如何构建“模块化”的东西并在其中共享数据?数据不需要从外部访问,它只是内部数据。这就是我所拥有的:
# 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那里看一下结构。
答案 0 :(得分:2)
使用您提供的示例代码,我建议使用合成将TemplateParser::Base
的实例传递给parse!
方法,如下所示:
# 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_value
或TemplateParser.test_value
设置或检索值。
另外,或许说明显了,我假设您在此处包含的伪代码并不能准确反映您的实际应用程序代码。如果是这样,那么substitute!
方法是一种非常简单的方法来实现简单的赋值。只需在node = test_value
内使用TemplateParser::Base#parse!
即可跳过往返行程。我相信你知道这一点,但至少值得一提......