There are so many ways to build an HTML table in Ruby. I think everyone has built one like this:
html = "".tap do |str|
str << '<table>'
str << '<tr>'
str << '<td>'
str << 'a'
str << '</td>'
str << '<td>'
str << 'b'
str << '</td>'
str << '</tr>'
str << '</table>'
end
Not only is that repetitious, it’s also an eye sore. We can do much better. How about a DSL?
module HTMLMethods
def wrap(tag)
concat "<#{tag}>"
yield
concat "</#{tag}>"
end
end
html = "".tap do |s|
s.extend HTMLMethods
s.wrap :table do
s.wrap :tr do
s.wrap(:td) { s << 'a' }
s.wrap(:td) { s << 'b' }
end
end
end
puts html # => <table><tr><td>a</td><td>b</td></tr></table>
Ahh, much better. Don’t like calling wrap on the s variable? No problem. Let’s make a class to get rid of it:
class HTMLFactory
def self.make(&block)
new.instance_eval(&block)
end
attr_reader :str
def initialize
@str = ""
end
def wrap(tag)
str.concat "<#{tag}>"
yield
str.concat "</#{tag}>"
end
end
html = HTMLFactory.make do
wrap :table do
wrap :tr do
wrap(:td) { str << 'a' }
wrap(:td) { str << 'b' }
end
end
end
puts html # => <table><tr><td>a</td><td>b</td></tr></table>
Enjoy!
Source code: https://gist.github.com/773952