【问题标题】:Bind ERB Template from more than one class绑定多个类的 ERB 模板
【发布时间】:2016-10-04 05:41:15
【问题描述】:

我正在尝试从 Ruby 中的多个对象插入 ERB 模板。如果变量的来源是一类,它工作得很好。当 ERB 包含不同类中存在的变量时,进行插值的最佳方法是什么。

这是我想要实现的精简版:

#!/usr/bin/ruby

require 'erb'
require 'pp'

class Person
  attr_reader :first_name, :last_name

  def initialize(first_name, last_name)
    @first_name = first_name
    @last_name = last_name
  end

end

class Animal
  attr_reader :animal_type

  def initialize(type)
    @animal_type = type
  end

end

person = Person.new("John", "Doe")
animal = Animal.new("doggie")

template = "<%=first_name%> <%=last_name%> has a <%=type%>"

puts ERB.new(template).result(person.instance_eval { binding })

上述失败,undefined local variable or method 'type' 是正确的,因为该属性属于 Animal 类的对象。

我发现的一种解决方法是创建哈希并使用合并将它们合并为一个,但这意味着对现有代码进行大量更改。有没有更好的方法来实现这一目标?

【问题讨论】:

    标签: ruby erb


    【解决方案1】:

    您可以使用 openstruct 使合并属性更友好一点,因此不必过多地重写模板。

    # in config/application.rb
    require 'ostruct'
    
    # in the file where you compile ERB
    person = OpenStruct.new Person.new("John", "Doe").attributes
    person.type = animal.type
    

    使用 OpenStruct,您的对象将是一个哈希,但像 person.first_name 这样的方法仍然可以工作。您可以添加任意键值,因此您可以使person.type 返回您想要的任何值。

    【讨论】:

    • 感谢一个不错的替代品。如果我必须单独编写每个哈希属性,我不确定这会有多大的可扩展性。例如,如果我有 10 个属性而不是 1 个 animal_type。
    • 也许是OpenStruct.new(person.attributes.merge(animal.attributes)),但问题是如果你有同名的属性(如 id 或 created_at)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多