|
[Ruby]
Object templates in Ruby
[
Aslak Hellesoy
]
The concept of templates are very common in many contexts of programming. A boiler-plate representation of something can be turned into a concrete instance by supplying some extra data. The important point is that the supplied data can vary, and that has an impact on the structure of the concrete instance of the template. In HTML programming, common template techniques are JSP, PHP, ERB and ASP. By passing some extra data to a template engine, a template can be turned into an HTML page that displays the data, using the layout from the template. In OO programming, the most common concept of a template is a Class. A piece of a program can supply some data to a class' constructor and get a new object. Sometimes, instantiating a new object by simply calling a constructor with some extra data is not the optimal way to create an object though. Consider the common situation where the desired object is composed of an aggregation of several other objects. -A complex graph of objects. One way to approach this is to design classes (aka templates) to honour Dependency Injection (DI), and use a DI container supporting a configuration file (in XML or other format). NanoContainer or Spring are two frameworks that use this approach to instantiate complex graphs of objects composed of "variable data" from a configuration file. Assuming you want the ability to create object graphs that are configured in an external file, and your language is Java, then it doesn't get much simpler than with NanoContainer or Spring. But in Ruby... A similar effect that is radically simpler and extremely easy to use can be achieved with a dash of Ruby magic using YAML and eval under the covers. Consider this object template: codehaus_project_template = Project.new codehaus_project_template.home_page = "http://\#{unix_name}.codehaus.org" jabber_publisher = JabberPublisher.new jabber_publisher.id_resource = "damagecontrol@jabber.codehaus.org/#{unix_name}" codehaus_project_template.publishers << jabber_publisher project = codehaus_project_template.dupe("unix_name" => "mooky")
assert_equal("http://mooky.codehaus.org", project.home_page);
assert_equal("damagecontrol@jabber.codehaus.org/mooky", project.publishers[0].id_resource);module ObjectTemplate
def dupe(variables)
template_yaml = YAML::dump(self)
b = binding
variables.each { |key, value| eval "#{key} = variables[\"#{key}\"]", b }
new_yaml = eval(template_yaml.dump.gsub(/\\#/, "#"), b)
YAML::load(new_yaml)
end
endTo follow your XStream suggestion, I would clone() the template and use Commons JXPath for the substitutions with XPath notation. It's not complicated but is weird. --B. K. Oxley (binkley), March 9, 2005 04:38 PM
Post a comment
|