Reputation: 77085
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
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