jaypal singh
jaypal singh

Reputation: 77085

Bind ERB Template from more than one class

I am trying to interpolate ERB template from multiple objects in Ruby. It works fine if the source of variables is one class. Whats the best way of doing the interpolation when the ERB contains variables present in different classes.

Here is a strip down version of what I am trying to achieve:

#!/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 })

The above fail with undefined local variable or method 'type' which is correct, since that attribute belongs to object of Animal class.

One work around I have found is to create hashes and use merge to collapse them in to one, but that would be mean a lot of changes to the existing code. Is there a better way to achieve this?

Upvotes: 1

Views: 398

Answers (1)

max pleaner
max pleaner

Reputation: 26758

You can use openstruct to make merging attributes a little more friendly so do don't have to rewrite your templates as much.

# 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

With OpenStruct your object will be a hash but methods like person.first_name will still work. And you can add arbitrary key-vals, so you can make person.type return any value you want.

Upvotes: 2

Related Questions