erbサポート

Amrita2は、eRubyをサポートしています。

  include Amrita2::Runtime
  specify "simple erb" do
    t = Amrita2::Template.new <<-'END'
      <%= 1 + 2 %>
    END
    t.render_with(binding).should_be == " 3 "
  end

eRubyを使用する時は、render_withにBindingオブジェクトを渡してください。Bindingオブジェクトが渡された場合は、対応する変数をテンプレート内に展開していきます。

コンテキストデータ

eRubyの処理内から、$_という変数によって、Amrita2の展開しているデータを参照することができます。

  specify "erb using model data" do
    t = Amrita2::Template.new <<-'END'
    <<ul<
      <<:list<
        <li><%= $_ * 10 %></li>
      >>>
    >>>
    END
    list = [1, 2, 3]
    t.render_with(binding).should_be_samexml_as <<-END
      <ul>
        <li>10</li>
        <li>20</li>
        <li>30</li>
      </ul>
    END
  end

この例では、<<:list< の時点で、ローカル変数の listの内容が取り出されます。listは配列なので、このタグが閉じるまでの内容は、配列要素の数だけ、繰り返し展開されます。そして、その中にある<%= ... %> に来た時点では、$_ には、配列要素が設定されています。

たとえば、最初のループの時には、$_には配列の最初の要素である「1」が設定されています。これを利用して

        <li><%= $_ * 10 %></li>

を展開すると、結果は

        <li>10</li>

となります。これを三回繰り返して、上記の結果が得られます。

この$_のことを、Amrita2では、「コンテキストデータ」と呼びます。

eRuby内でコンテキストデータを設定する

eRubyの処理の中で、$_ の内容を設定することができます。

  specify "erb providing model data" do
    t = Amrita2::Template.new <<-'END'
    <<ul<
      <%
         list = (1..3).collect { |n| n*10 }
       %>
      <<li:list>>
    >>>
    END
    t.render_with(binding).should_be_samexml_as <<-END
      <ul>
        <li>10</li>
        <li>20</li>
        <li>30</li>
      </ul>
    END
  end

このようにすると、<>は、あたかも最初に list = [10, 20, 30] というデータが与えられていたかのような動きをして、上記の結果になります。

この機能を利用して、eRubyでデータを作り、Amrita2形式で指定したXMLテンプレートの中にそのデータを展開することができます。

eRubyでコンテキストデータを変更する

  specify "erb filtering model data" do
    t = Amrita2::Template.new <<-'END'
    <<ul<
      <<li:list<
        <% $_[:no_times10] = $_[:no] * 10 %>
        <<:no>> * 10  = <<:no_times10>>
      >>>
    >>>
    END
    
    list = (1..3).collect do |n|
      { :no => n }
    end
    
    t.render_with(binding).should_be_samexml_as <<-END
      <ul>
        <li>1 * 10 = 10</li>
        <li>2 * 10 = 20</li>
        <li>3 * 10 = 30</li>
      </ul>
    END
  end

この場合は、コンテキストデータとして渡されるのは、ハッシュの配列です。外側では、:no に対応する要素だけを渡して、テンプレートの内部のeRubyで、それに対応した、:no_times10のデータを作成してハッシュの別の要素として設定しています。その結果の二つの要素を持つハッシュが、計3回

        <<:no>> * 10  = <<:no_times10>>

という所に渡されます。その結果、上記の出力が得られます。

AmXMLでeRubyを記述する

AmXMLには、このようなeRubyの記述を簡単にする機能も含まれています。

  specify "erb filtering model data with amxml" do
    t = Amrita2::Template.new <<-'END'
    <<ul<
      <<:list <
        <<li ?[($_[:no]%2) != 0 ] <
          <<{
             :no => $_[:no],
             :no_times10 => $_[:no] * 10
            } <

             <<:no>> * 10  = <<:no_times10>>

          >>>
        >>>
      >>>
    >>>
    END
    
    list = (1..3).collect do |n|
      { :no => n }
    end
    
    t.render_with(binding).should_be_samexml_as <<-END
      <ul>
        <li>1 * 10 = 10</li>
        <li>3 * 10 = 30</li>
      </ul>
    END
  end

「<< ?[.....] < .... >>>」 は、?[]内の式をRubyの式として評価して、その結果がnilかfalseであれば、そのブロック全体を出力しないという意味です。

「<<{...}< .... >>>」は、そのブロック内のコンテキストデータとして、新しく生成したハッシュを使用するという意味です。