Path: | README_FOR_1.0_USERS |
Last Update: | Fri Dec 17 13:39:08 JST 2004 |
amrita2 has two level API.
* active template API ( which is 80% compatible with amrita 1.0) * passive template API (a new one with more flexiblity)
template
<html> <body> <h1 id='title'>title will be inserted here</h1> <p id='body'>body text will be inserted here</p> </body> </html>
code
require "amrita2/template" include Amrita2 tmpl = TemplateFile.new("template.html") data = { :title => "hello world", :body => "Amrita is a html template libraly for Ruby" } tmpl.expand(STDOUT, data)
result
<html> <body> <h1>hello world</h1> <p>Amrita is a html template libraly for Ruby</p> </body> </html>
require "amrita2/template" include Amrita2 tmpl = TemplateFile.new("template.html") tmpl.expand(STDOUT) do |m| # amrita2 passes a Module compiled from the template # with methods for dynamic elements. m.title("hello world") m.body("Amrita is a html template libraly for Ruby") end
will produce same result
These codes are picked up from unit test code. So it may be too complicated for summary but they work now.
With passive template API, you can specify ‘TEMPLATE SPEC’ which controls compilation from HTML to Ruby.
# template spec spec = Amrita2::define_tempalte_spec do dynamic_element(:aaa) end # XML document doc = REXML::Document.new "<x id='aaa'>111</x>" # create template object from spec and document t = spec.create_template(doc) # use template out = "" t.expand_template(out) do |m| m.aaa('hello amrita2') end assert_equal("<x id='aaa'>hello amrita2</x>", out)
You can set attributes in any element if you set replace_attr flag in the template spec for the element.
spec = Amrita2::define_tempalte_spec do # With :replace_attr option on, you can control attributes of # element with id 'aaa' dynamic_element(:aaa, :replace_attr=>true) end doc = REXML::Document.new "<a id='aaa' class='abc'><b id='bbb'>xxx</b></a>" t = spec.create_template(doc) out = "" t.expand_template(out) do |m| # set attribute value m.aaa(:class=>'xyz') do |m2| m2.bbb('yyy') end end assert_equal("<a class='xyz' id='aaa'><b id='bbb'>yyy</b></a>", out)
spec = Amrita2::define_tempalte_spec do dynamic_element(:link, :use_original_element=>true) end doc = REXML::Document.new "<p>See <a id='link' href='http://www.ruby-lang.org/'>Ruby</a> for detail</p>" t = spec.create_template(doc) t.expand_template(out="") do |m| m.link('Ruby homepage') end assert_equal("<p>See <a href='http://www.ruby-lang.org/' id='link'>Ruby homepage</a> for detail</p>", out) t.expand_template(out="") do |m| m.link do |e| # e is a REXML::Element object. You can modify it with REXML API e.attributes["href"] += 'ja/' e.attributes.delete("id") e.text += '(Japanese)' e end end assert_equal("<p>See <a href='http://www.ruby-lang.org/ja/'>Ruby(Japanese)</a> for detail</p>", out)
amrita2 do well with tables like this than amrita 1.0.
amrita2 can generate different lines for odd line and even line automatically.
tmpl = REXML::Document.new <<END <table border='1'> <tr><th></th><th></th></tr> <tr class='detail1'><td></td><td></td></tr> <tr class='detail2'><td></td><td></td></tr> </table> END
The magic is ‘mach_many’ option.
include HtmlTag spec = Amrita2::define_tempalte_spec(:direct_define=>true) { table(:matcher=>TABLE) { header(:matcher=>TR) { item1(:matcher=>TH) item2(:matcher=>TH) } # the element 'detail' is suposed to match two 'TR' element # of template with :match_many option detail(:matcher=>TR, :match_many=>true) { name(:matcher=>TD) author(:matcher=>TD) } } } data = [ [ "Ruby", "matz" ], [ "perl", "Larry Wall" ], [ "python", "Guido van Rossum" ] ] spec.create_template(tmpl).expand_template(STDOUT) do |m| m.table do |mt| mt.header do |mh| mh.item1('name') mh.item2('author') end data.each_with_index do |data, i| # produce result with (i%2)th TR element automatically mt.detail(i) do |md| md.name(data[0]) md.author(data[1]) end # And if template has three TR elements, this code will # produce result with (i%3)th line with no modification end end end
result
<table border='1'> <tr><th>name</th><th>author</th></tr> <tr class='detail1'><td>Ruby</td><td>matz</td></tr> <tr class='detail2'><td>perl</td><td>Larry Wall</td></tr> <tr class='detail1'><td>python</td><td>Guido van Rossum</td></tr> </table>
‘TEMPLATE SPEC’ can validate HTML Template. So, once you wrote a spec and pass it to your designer, he can make a beautiful template freely. Only he must do is validating his work with the ‘TEMPLATE SPEC’.
And if you have a programmer for you, you can tell her to make the logic. She can check her code with ‘TEMPLATE SPEC’ only. She doesn’t need the template.
require 'amrita2/test' spec = Amrita2::define_tempalte_spec do dynamic_element(:aaa) end # create dummy template object from spec without template. t = spec.create_dummy_template # the behavior of dummy template is same as real one. t.expand_template(nil) do |m| m.aaa('123') end # dummy template remembers values assigned to it. # You can test it assert_equal('123', t[:aaa])
So they both can do their job concurrently. You should only say to them, ‘Check your work against my TEMPLATE SPEC’. And the logic and presentation will go well with each other.