It looks like you're trying to write your own template parser, which is asking for a lot more trouble that it's worth considering those already exist.
However, this is the basic idea for such a thing:
erb = <<EOT
Owner: <%= name %>
Location: <%= address %>
EOT
FIELD_DATA = {
name: 'Olive Oyl',
address: '5 Sweethaven Village'
}
FIELD_RE = Regexp.union(FIELD_DATA.keys.map(&:to_s)).source # => "name|address"
puts erb.gsub(/<%=\s+(#{FIELD_RE})\s+%>/) { |k|
k # => "<%= name %>", "<%= address %>"
k[/\s+(\S+)\s+/, 1] # => "name", "address"
FIELD_DATA[k[/\s+(\S+)\s+/, 1].to_sym] # => "Olive Oyl", "5 Sweethaven Village"
}
Which, when run, outputs:
Owner: Olive Oyl
Location: 5 Sweethaven Village
This works because gsub
can take a regular expression and a block. For every match of the expression it passes in the match to the block, which is then used to return the actual value being substituted in.
If you have a lot of target values, rather than use Regexp.union
, instead use the RegexpTrie gem. See "Is there an efficient way to perform hundreds of text substitutions in Ruby?" for more information.
Again, template parsers exist, they've been around a long time, they're very well tested, and they handle edge cases you haven't thought about, so don't write a new partially-implemented one, instead reuse an existing one.