2.0の機能を利用してみる

引き続き、Rails2.0.2環境でのscaffoldからの作業を淡々と続ける...。

フォームヘルパーlabelを使う

  • Rails2.0ではフォームヘルパーにlabelメソッドが追加された。
<p>
  <label for="slip_number">Number</label><br/>
  <%= text_field 'slip', 'number'  %>
</p>
  • 上記は、labelヘルパーを利用して、以下のように書くことができる。
<p>
  <%= label :slip, :number %><br/>
  <%= text_field 'slip', 'number'  %>
</p>
  • コードを書く手間は大差ないようだが、以下のCSSと組み合わせてsubmitボタンを押してみる...
<p>
  <%= label :slip, :number, nil, :style=>"display:table %>
  <%= text_field 'slip', 'number'  %>
</p>
...(中略)...
.fieldWithErrors {
  background-color: pink;
  display: table;
}
.fieldWithErrors * {
  background-color: pink;
}

  • 検証エラー発生時に、text_field等のフィールドヘルパーと同じく、強調表示の対象になる。(クラス属性fieldWithErrorsで囲まれる。よって、cssで指定した通り、ラベル文字列の背景もピンク色になる。)
  • :style=>"display:tableは、検証エラー発生時に無駄な改行の発生を抑えるため。(デフォルトのdisplay:inlineのままbrタグで改行すると、検証エラー発生時はdisplay:tableの状態になるため、無駄な改行になってしまう...。)
  • 検証エラー発生時、CSSはdisplay:tableの状態が一番見栄えが良かった。
    • display:blockでは、1行全体がピンク色になってしまう...。
    • display:inlineでは、周囲に隙間が発生してしまう...。

フィールド名としてRuby-GetTextの翻訳対象にする

  • 以前は、リスト表示で列タイトルを表示する部分は以下のようになっていた。column.human_nameを呼び出すと、GetTextは翻訳したフィールド名を返してくれた。
<% for column in Slip.content_columns %>
  <th><%= column.human_name %></th>
<% end %>
  • ところが、Rails2.0.2では直接フィールド名の文字列が生成される。これだとGetTextはフィールド名として認識しないので、_("文字列")で翻訳対象として抽出しない限り翻訳してくれない...。
  • 以前のようにforループを使ったcolumn.human_nameに変更すれば翻訳されるのだが、表示順序も気になってくると直接フィールド名を書きたくなる。
  • _("文字列")メソッドで抽出すれば済むことなのだが、翻訳作業が繰り返しになるので面倒だ。
<th>Number</th>
<th>Executed on</th>
<th>Total yen</th>
  • そんな時は、human_attribute_nameメソッドを使えば、GetTextはちゃんと翻訳してくれる。それにしてもメソッド名が長〜い...。
<th><%= Slip.human_attribute_name('number') %></th>
<th><%= Slip.human_attribute_name('executed_on') %></th>
<th><%= Slip.human_attribute_name('total_yen') %></th>
  • 最近気付いたが、シンプルに以下で良いのでした。GetTextは、_('msgidと同じ文字列')が見つかると、翻訳してくれるのでした。
<th><%= _("Slip|Number") %></th>
<th><%= _("Slip|Executed on") %></th>
<th><%= _("Slip|Total yen") %></th>

labelメソッドの翻訳

  • Rails2.0で追加されたlabelメソッドのラベル文字列なんかも、よくフィールド名として翻訳対象にしたくなる。
<%= label :slip, :number, _('Slip|Number') %>
  • さっそく覚えたてのmsgid記法を使いたくなるが、そもそも翻訳しなければ<%= label :slip, :number %>だけで良かったはず。同じslipとnumberを繰り返すのは良くない...。
  • labelヘルパーの中で解決してしまうのが良いと考え、アプリケーションヘルパーに再定義してしまった。(ソースコードをコピーして一部変更しただけ)
# ヘルパー: app/helpers/application_helper.rb

module ActionView
  module Helpers
    class InstanceTag #:nodoc:
      def to_label_tag(text = nil, options = {})
        name_and_id = options.dup
        add_default_name_and_id(name_and_id)
        options["for"] = name_and_id["id"]
        content = (text.blank? ? nil : text.to_s) || object_class.human_attribute_name(method_name) #<---||より右側を変更
        content_tag("label", content, options)
      end

      # オブジェクト名からクラスを取得する
      def object_class
        Object.const_get(@object_name.to_s.classify)
      end
    end

  end
end
  • これで<%= label :slip, :number %>も翻訳してくれる!

form_for、fields_forのオプション指定がシンプルに

  • 2.0のscaffoldからやり直した時にもちょっと触れたが、新旧を比較してみると...
    • 旧: Rails1.2.6以前
    • 新: Rails2.0.2
旧: <% form_for :slip, :url=>{:action=>'create'} %>
新: <% form_for @slip %>

旧: <% fields_for :journal, form %>
新: <% fields_for form %>
  • 特に、form_forでRESTなurlであれば、:urlオプションまで省略できてしまうところが素晴らしい!(まだ仕組みはちゃんと理解できていないが...。)