【问题标题】:ERB/Templating clue for ruby红宝石的 ERB/模板线索
【发布时间】:2014-02-13 12:48:48
【问题描述】:

我希望模板看起来像这样:

interfaces {
  <%= name %> {
    description "<%= description %>";
    mtu <%= mtu %>;
  }
}

但是,如果代码评估为非真实值,我希望不打印行。它可能是对 ERB 的破解,在 \n 之后它设置 print_line = true 并且在使用 b%> 评估代码为 false 之后它设置 print_line = false,并且仅在 print_line 时打印。
但似乎为此更改 ERB 并不是微不足道的,它读取整个模板,非代码部分作为打印“数据”插入,结果是单个大字符串 ruby​​ 代码,在#result 期间整体评估。我需要在字符串扫描期间评估 b%> 代码,如果它返回 true,则只需插入打印“数据”,或者根本不插入,或者我需要重新扫描 #result 中的代码以首先运行 b%>。

如果您最终将所有模板都写在代码块中,那么即使使用模板也似乎没有结果,例如:

interfaces {
  <%= name %> {
    <% if description %>
    description "<%= description %>";
    <% end%>
    <% if mtu %>
    mtu <%= mtu%>;
    <% end%>
  }
}

或:

interfaces {
  <%= name %> {
    <%= "description \"#{description}\";" if description %>
    <%= "mtu #{mtu};" if mtu %>
  }
}

我需要支持各种不同的配置格式,在其他一些配置格式中它可能是'maximum-transfer-unit bytes'。我希望将模板中的所有特定于平台的智能和模板中的实际代码保持在最低限度。在模板之外添加与平台无关的复杂性没有问题。

似乎是相对常见的用例。在我去 NIHing 我自己的模板语言或破解 ERB 之前,也许还有其他一些模板语言更适合我的用例。还是遗漏了什么?

我已经为 实现了 hack,如果计算结果为 false,则省略整行。 ERB 根本不是为这样的事情而设计的,所以它很脏,我最好只编写自己的模板语言,除非有人可以建议我可以干净地实现类似的现有解决方案。
对于有兴趣的人,黑客在这里http://p.ip.fi/-NeJ

最终重新发明了轮子:https://github.com/ytti/malline

【问题讨论】:

  • 你能简单地传入名称和值的数组,然后循环吗?
  • @NeilSlater 不是真的。让我们假设 'description' 和 'mtu' 是键,而 description 和 mtu 是它们的值。我只从模型中得到值,没有得到键。我需要为各种平台生成配置,其他人用不同的键引用这些值。我想我可以在模板中做类似 %w(description mtu).each{|key|val=eval(key);puts #{key} #{value} if val} 的事情。但同样,它并不是真正的模板。也许我可以破解 ERB 在它看到 \n 后设置“print_line = true”,并在 b%> evals false 的块后设置“print_line = false”。
  • 您已经知道“键”,否则您将不知道将它们放入模板中。我建议不要在模板代码中使用这些变量名,而是创建一个本地数组,在 Ruby 中可能像这样:config_items = [ :description, :mtu ].map { |vname| vval = send( vname ); vval ? [ vname, vval ] : nil }.compact -尽管我不清楚 self 是你的模型,还是你是已经将值加载到 Ruby 中的其他局部变量?
  • 我的意思是,我可能需要在其他一些平台 mtu 中引用 'maximum-transfer-unit bytes',所以我只知道值在 'mtu' 内,我不知道他们的关键,在本例中为“最大传输单元”。因此,任何迭代的神奇建议都意味着我对每个平台都了解。模板的原因是,键是静态的,我只是用值填充它们。 self 是我的模型(它是续集的子类)。
  • 好的,我认为您需要在模板之外解决此类映射,以便数组有用。需要明确的是,您有描述带有标准化标签的配置的数据,并且您希望将它们放入配置文件中,可能使用另一个名称,前提是该值存在于数据中。并且您想在模板代码中解决映射(到特定于配置的键)和存在与否?您至少知道如何做到这一点,但认为必要的模板代码过于冗长?

标签: ruby erb template-engine


【解决方案1】:

辅助方法

def description_helper(description)
  "description \"#{description}\";" if description
end
def mtu_helper(mtu)
  "mtu #{mtu};" if mtu
end

interfaces {
  <%= name %> {
    <%= description_helper %>
    <%= mtu_helper %>
  }
}

Decorator pattern

class MyObject
  def description
    'some description'
  end
  def mtu
    nil
  end
  module ViewDecorator
    def description
      "description \"#{super}\";" if super
    end
    def mtu
      "mtu #{super};" if super
    end
  end
end

o = MyObject.new
p o.description #=> "some description"
p o.mtu #=> nil
o.extend MyObject::ViewDecorator
p o.description #=> "description \"some description\";"
p o.mtu #=> nil

【讨论】:

  • 这里是帮助器或装饰器中特定于平台的代码,这使得模板的意义不大,我不妨使用字符串/heredoc 等。我真的想只在模板中保留特定于平台的智能。这可能是我唯一的解决方案是 NIH 新模板语言,或者使用 %b> 修补 ERB。
  • 好吧,我想我明白了;我的回答显然不符合你的问题。我建议您使用这些附加信息更新您的问题(我也阅读了与@NeilSlater 的讨论),因为阅读它的用户可能会被误导恕我直言
猜你喜欢
  • 2011-02-03
  • 1970-01-01
  • 2018-10-09
  • 1970-01-01
  • 1970-01-01
  • 2012-03-01
  • 1970-01-01
  • 2018-10-30
  • 1970-01-01
相关资源
最近更新 更多