J
John W. Long
Hi,
This idea for the next generation of CGI has me thinking (see
http://rubygarden.org/ruby?NextGenerationCGI). It seems that CGI would be
best if it were broken in two. One side handled generating html, and the
other handled all the other stuff (params, headers, etc...).
Last night I started prototyping some of my ideas and came up with the
following:
class HtmlGenerator
def render(klass, &blk)
hg = klass.new
hg.render(&blk)
end
end
class Html4
attr_accessor :encoding
def render(&blk)
"<html>#{self.instance_eval(&blk)}\n</html>"
end
def head(&blk)
"\n<head>#{self.instance_eval(&blk)}\n</head>"
end
def title(&blk)
"\n<title>#{self.instance_eval(&blk)}</title>"
end
def meta(hash = {})
"\n" + '<meta name="' + hash[:name] + '" content="' + hash[:content] +
'">'
end
def body(&blk)
"\n<body>#{self.instance_eval(&blk)}\n</body>"
end
def h1(&blk)
"\n<h1>#{self.instance_eval(&blk)}</h1>"
end
def h2(&blk)
"\n<h2>#{self.instance_eval(&blk)}</h2>"
end
def p(&blk)
"\n<p>#{self.instance_eval(&blk)}</p>"
end
def b(&blk)
"<b>#{self.instance_eval(&blk)}</b>"
end
def i(&blk)
"<i>#{self.instance_eval(&blk)}</i>"
end
end
hg = HtmlGenerator.new
puts hg.render(Html4) {
encoding = "US/English"
head {
title { "My Document" } +
metaname => "description", :content => "this is a description of this
document")
} +
body {
h1 { "Heading 1" } +
p { "A small paragraph." } +
h2 { "Heading 2" } +
p { b { "Bold" } + " " + i { "Italic" } }
}
}
I like the syntax of this very much, but I would like input on two things.
The first this would require heavy use of instance_eval. Would this be a
good thing? It strikes me that the main problem with instance_eval is that
you can begin to change the interface of the class. However, as this is
implemented above you can see that changes to the implementation would only
effect an instance of the HtmlXX class, which would go into never never land
as soon as the render call is completed.
The second, a bit harder, I would like to remove the need for the pluses in
order to chain the results together. Any Ruby gurus that would like to try
and take a stab at it? I can think of one possible solution, but I'm not
sure if the results would really be satisfactory.
This idea for the next generation of CGI has me thinking (see
http://rubygarden.org/ruby?NextGenerationCGI). It seems that CGI would be
best if it were broken in two. One side handled generating html, and the
other handled all the other stuff (params, headers, etc...).
Last night I started prototyping some of my ideas and came up with the
following:
class HtmlGenerator
def render(klass, &blk)
hg = klass.new
hg.render(&blk)
end
end
class Html4
attr_accessor :encoding
def render(&blk)
"<html>#{self.instance_eval(&blk)}\n</html>"
end
def head(&blk)
"\n<head>#{self.instance_eval(&blk)}\n</head>"
end
def title(&blk)
"\n<title>#{self.instance_eval(&blk)}</title>"
end
def meta(hash = {})
"\n" + '<meta name="' + hash[:name] + '" content="' + hash[:content] +
'">'
end
def body(&blk)
"\n<body>#{self.instance_eval(&blk)}\n</body>"
end
def h1(&blk)
"\n<h1>#{self.instance_eval(&blk)}</h1>"
end
def h2(&blk)
"\n<h2>#{self.instance_eval(&blk)}</h2>"
end
def p(&blk)
"\n<p>#{self.instance_eval(&blk)}</p>"
end
def b(&blk)
"<b>#{self.instance_eval(&blk)}</b>"
end
def i(&blk)
"<i>#{self.instance_eval(&blk)}</i>"
end
end
hg = HtmlGenerator.new
puts hg.render(Html4) {
encoding = "US/English"
head {
title { "My Document" } +
metaname => "description", :content => "this is a description of this
document")
} +
body {
h1 { "Heading 1" } +
p { "A small paragraph." } +
h2 { "Heading 2" } +
p { b { "Bold" } + " " + i { "Italic" } }
}
}
I like the syntax of this very much, but I would like input on two things.
The first this would require heavy use of instance_eval. Would this be a
good thing? It strikes me that the main problem with instance_eval is that
you can begin to change the interface of the class. However, as this is
implemented above you can see that changes to the implementation would only
effect an instance of the HtmlXX class, which would go into never never land
as soon as the render call is completed.
The second, a bit harder, I would like to remove the need for the pluses in
order to chain the results together. Any Ruby gurus that would like to try
and take a stab at it? I can think of one possible solution, but I'm not
sure if the results would really be satisfactory.