Amrita2を快適に利用する

gem戦記さんの記事を読んで、Rails2.0.2環境の中で、Amrita2をより快適に利用する設定が分かってきた。これでもう.erbファイルを残す理由は全くなくなってしまった。すべてのファイルを.a2ファイルに変換して、ERbも利用しつつ、AmXML記法の恩恵も受けながら作業できるようになった!

レイアウトファイルの設定

<<%<記法を覚えて、ほとんどの.erbファイルを.a2ファイルに置き換えてしまったが、レイアウトファイルだけうまく行かなかった...。どうやら、yeildのところで以下のエラーが発生しているようだ。

LocalJumpError in Slips#index

Showing layouts/slips.html.a2 where line # raised:

no block given
  • 付属のサンプルコードで確認すると、yeildは<<:content_for_layout | NoSanitize>>に置き換える(下から2行目)ことで、正常に描画されるようだ。
<%(BeforeCompile) opt[:process_xhtml]=true %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" : | Tidy<
  <head>
    <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
    <title>Slips: <%= controller.action_name %></title>
    <%= stylesheet_link_tag 'scaffold', 'will_paginate' %>
    <%= javascript_include_tag :defaults %>
  </head>
  <body>

  <p style="color: green"><%= flash[:notice] %></p>

  <%#= yield  %>
  <<:content_for_layout | NoSanitize>>

  </body>
  • DOCTYPE宣言を有効にする<%(BeforeCompile) opt[:process_xhtml]=true %>も追記(1行目)した。(追記しないと直後のDOCTYPE宣言(以下の部分)が反映されず、見た目が変わってしまう...。)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  • さらに「 : | Tidy」を追記(4行目)して、development環境の時だけ、HTMLソースの整形を有効にする設定をしておいた。
    • environment.rbで、Tidyは以下のように定義しておく。
# 環境設定: config/environment.rb
...(中略)...
if ENV['RAILS_ENV'] == "development"
  Tidy = Amrita2::Filters::CommandFilter['tidy -q -xml -indent -utf8']
else
  Tidy = nil
end
    • これで、ファイルごとに<<div : | CommandFilter['tidy -utf8 -q -xml -indent']<を追記する手間が省ける。
    • そして、development環境の時だけ整形されるので、本番のproduction環境では多少描画が早くなるのかもしれない。

Ruby-GetTextに_( )は不要

  • Amrita2でRuby-GetTextが有効になっている場合、文字列は常に翻訳された結果が描画されるのだ!(だから_( )で囲う必要はない。)
# 今までERbコードとして_( )で囲っていたが...
<<h1<
  %= _('Listing slips')

# シンプルに以下のように書いても翻訳される。
<<h1<
  Listing slips
  • ただし、ERbコードの中では、_( )が必要になる。(以下は例)
%= link_to _('Show'), :action=>:index
利用環境
設定
  • Amrita2環境でRuby-GetTextを利用するため、以下の設定に変更した。(オレンジ色の部分)
# 設定: config/environment.rb

# 文字列処理で日本語を考慮した処理メソッドを利用可能にする。
# http://www.ruby-lang.org/ja/man/html/jcode.html
require 'jcode'

...(中略)...
Rails::Initializer.run do |config|
...(中略)...
end

# Amrita2でRuby-GetTextを有効にする。
require 'gettext/rails'
require 'amrita2/gettext'
require 'amrita2/macro'

# Amrita2でRuby-GetTextを利用する時のテキストドメイン名(init_gettextで指定する名前)
Amrita2View::Base.text_domain = "test_slip"

# RadRailsでmsgmergeを有効にして、rake updatepoを実行するために必要
ENV['MSGMERGE_PATH'] = '/usr/local/bin/msgmerge'
コントローラー: app/controllers/application.rb
# Filters added to this controller apply to all controllers in the application.
# Likewise, all the methods added will be available for all controllers.

class ApplicationController < ActionController::Base
  helper :all # include all helpers, all the time

  # See ActionController::RequestForgeryProtection for details
  # Uncomment the :secret if you're not using the cookie session store
  #protect_from_forgery # :secret => '62131e8be3a35fd28465e41d6cd97cf9'
  
  init_gettext 'test_slip'
end
翻訳文字列の抽出
  • 翻訳文字列を抽出するrakeファイルupdatepoは、以下のように設定してみた。(オレンジ色がAmrita2用に追記した部分)
# lib/tasks/gettext.rake

desc "Update pot/po files."
task :updatepo do
  $: << 'vendor/plugins/amrita2/lib'
  require 'gettext/utils'
  require 'amrita2/gettext'
  require 'amrita2/macro'
  
  # Tell ruby-gettext's ErbParser to parse .erb files as well
  # See also http://zargony.com/2007/07/29/using-ruby-gettext-with-edge-rails/
  # Rails2.0から必要
  GetText::ErbParser.init(:extnames => ['.rhtml', '.erb', '.a2html', '.a2'])

  GetText.update_pofiles(
    "test_slip",  #テキストドメイン名(同じ名前のファイルが生成される。init_gettextで指定する。) 
    Dir.glob("{app,config,components,lib}/**/*.{rb,rhtml,rjs,erb,a2html,a2}"),  #ターゲットとなるファイル(文字列内は余分なスペース無しで指定する)
    "test_slip 1.0.0")  #アプリケーションのバージョン
end

desc "Create mo-files"
task :makemo do
  require 'gettext/utils'
  GetText.create_mofiles(true, "po", "locale")
end
  • .a2拡張子に対応するため、gettext.rbにオレンジ色の部分を追記した。
# vendor/plugins/amrita2/lib/amrita2/gettext.rb 89~96行目付近

require 'amrita2/template'
require 'gettext/rgettext'

module Amrita2 
...(中略)...
  module GetTextParser # :nodoc: all
    include Amrita2
    include Amrita2::GetTextBridge

    module_function
    def target?(file)
      File.extname(file) == '.a2html' || File.extname(file) == '.a2'
    end
...(中略)...
  • コメントタグ<!-- -->があると、rake updatepoの時エラーが発生する。<!-- -->を削除してしまえば、正常に抽出処理される。

以上の設定をすると、_( )無しで、Ruby-GetTextが利用可能になる。快適だ!

テーブル略記法の研究

  • 最初に感動したテーブル略記法は...
<<table<
  <<tr<----------------------------------------------------------------------------------------------------------------------------------------
    | ||<%= _("Slip\|Number") %>||<%= _("Slip\|Executed on") %>||<%= _("Slip\|Total yen") %>|| || || ||
    ---------------------------------------------------------------------------------------------------------------------------------------------
  <<tr :slips<---------------------------------------------------------------------------------------------------------------------------------
    |align||left       |left            |right         |                       |                           |                                    |
    |class||           |                |              |action_link            |action_link                |action_link                         |
    |     ||<<:number>>|<<:executed_on>>|<<:total_yen>>|<%= link_to _('Show'), |<%= link_to _('Edit'),     |<%= link_to _('Destroy'),           |
    |     ||           |                |              |    $_ %>              |      edit_slip_path($_) %>|    $_,                             |
    |     ||           |                |              |                       |                           |    :confirm => _('Are you sure?'), |
    |     ||           |                |              |                       |                           |    :method => :delete %>           |
    ---------------------------------------------------------------------------------------------------------------------------------------------
  • 書き方を試行錯誤した結果、以下のように書いてもOKのようだ。
    • Ruby-GetTextで_( )は不要。
    • trは省略して良い。(<<<tr<---- → <<<----、<<tr:slips<---- → <<:slips<----)
    • 属性の指定が無いときは、「|||」で始めてもOK。(「| ||」 → 「|||」)
    • body属性、filter属性も分解して指定可能。(am:src、am:filter)
    • 長いコードもハッシュキーに代入すれば、表全体の見通しが良くなる。
      • 例: % $_[:show] = link_to(_('Show'), $_)
<<table<
  <<<-------------------------------------------------------------------------------------
    |||Slip\|Number ||Slip\|Executed on ||Slip\|Total yen || || || ||
    --------------------------------------------------------------------------------------
  <<:slips<-------------------------------------------------------------------------------
    % $_[:price_yen] = number_with_delimiter($_[:total_yen])
    % $_[:show]   = link_to(_('Show'), $_)
    % $_[:edit]   = link_to(_('Edit'), edit_slip_path($_))
    % $_[:delete] = link_to(_('Destroy'), $_, :confirm=>_('Are you sure?'), :method=>:delete)

    |am:src   ||number |executed_on |price_yen |show        |edit        |delete      |
    |am:filter||       |            |          |NoSanitize  |NoSanitize  |NoSanitize  |
    |align    ||left   |left        |right     |            |            |            |
    |class    ||       |            |          |action_link |action_link |action_link |
    --------------------------------------------------------------------------------------

横幅を抑えてコンパクトに表現できるようになった!

    • 略記法と通常記法を混在させても大丈夫。
<<table<
  <<<-------------------------------------------------------------------------------------
    |||Slip\|Number ||Slip\|Executed on ||Slip\|Total yen || || || ||
    --------------------------------------------------------------------------------------
  <<:slips<-------------------------------------------------------------------------------
    % $_[:price_yen] = number_with_delimiter($_[:total_yen])

    |am:src   ||number |executed_on |price_yen |
    |align    ||left   |left        |right     |
    --------------------------------------------------------------------------------------
    <<td.action_link<
      %= link_to _('Show'), $_
    <<td.action_link<
      %= link_to _('Edit'), edit_slip_path($_)
    <<td.action_link<
      %= link_to _('Destroy'), $_, :confirm => _('Are you sure?'), :method => :delete