jascaffoldで日本語表示。

softwarebook2のデータベースをそのまま利用して、jascaffoldを使ってみた。

見た目の比較

エラー表示
before

after
list表示
before

after

今日の作業

jascaffoldまで
  1. 新規Railsプロジェクトの作成。
  2. config/database.ymlの設定。
  3. config/environment.rbに$KCODE = 'u'の追加。
  4. jascaffoldプラグインのインストール。
  5. script/generate jascaffold softwareの実行。
  6. script/generate jascaffold keywordの実行。

以上の処理を手早く実行した。

日本語化

script/generate jascaffoldを実行すれば、それだけでエラー表示は日本語になる。

class Software < ActiveRecord::Base
  validates_presence_of :title, :description, :url, :keyword_id
  validates_format_of :url, :with => URI.regexp(['http', 'https', 'ftp'])
end

日本語化は、以下の.yml設定ファイルでカスタマイズできる。

.yml 日本語化する内容
config/localize.yml ページタイトル、リンクやボタン、メッセージなど
db/localized/softwares.yml softwaresテーブルのフィールド名、表示属性
db/localized/keyword.yml keywordsテーブルのフィールド名、表示属性

対応する日本語を設定するだけなので、とても分かり易い。些細なことだが、オレンジ色の箇所を自分流に修正してみた。

config/localize.yml
    • model:のsoftwareをソフトウェアに変更。
    • リンクボタン等のshowを「参照」から「詳細」に変更。
    • エラーや警告のメッセージに「。」が無いのが気になったので追加。
# Model の日本語名
model:
  software : ソフトウェア
#  recipe          : レシピ
#  category        : カテゴリ

# ページタイトル
title:
  new             : の新規作成
  list            : の一覧
  show            : の詳細
  edit            : の編集
  destroy         : の削除
  confirm_create  : の作成確認
  confirm_update  : の修正確認
  confirm_destroy : の削除確認

# リンクボタン等
label:
  new             : 新規作成
  list            : 一覧
  show            : 詳細
  edit            : 編集
  destroy         : 削除
  update          : 更新
  confirm         : 確認
  confirm_destroy : 本当に削除しますか?
  back            : 戻る
  cancel          : キャンセル
  create          : 作成
  has_many        : "(%d)"

message:
  ajax_loading    : "Loading..."
  ajax_created    : "保存しました。リロードすると表示内容が更新されます。"

# アクション実行後のメッセージ
command:
  successfully_created : を作成しました
  successfully_updated : を更新しました

common:
  error_header        : "<h2>エラーが発生しました</h2>"
  notice_header       : ''

error_messages_for:
  options_header_tag  : "h2"
  errors_occurred     : "個のエラーが発生しました"
  there_were_problems : "次の項目に問題があります"
  label_class         : "label"
  label_error_class   : "labelWithErrors"

error_messages:
  inclusion           : "はリストに含まれてません"
  exclusion           : "はリストに含まれてます"
  invalid             : "は不正な値です"
  confirmation        : "は確認されませんでした"
  accepted            : "は許可されていません"
  empty               : "を入力して下さい"
  blank               : "を入力して下さい"
  too_long            : "は%d文字以下で入力して下さい"
  too_short           : "は%d文字以上で入力してください"
  wrong_length        : "は%d文字でなければなりません"
  taken               : "はすでに存在します"
  not_a_number        : "は数字で入力して下さい"

ipe:
  options             :
    :save_text        : "保存"
    :cancel_text      : "取消"
db/localize/softwares.yml
    • column_names:で、列タイトルの日本語を設定した。
    • property_フィールド名:で、データを表示する時の属性を設定出来る。今回はcreated_on、updated_onの表示形式を'%Y-%m-%d %H:%M:%S'にした。
column_names:
  id          : Id
  title       : タイトル
  description : メモ
  url         : URL
  created_on  : 作成日時
  updated_on  : 更新日時
  keyword_id  : キーワード


property_id:
#  :format  : "%s points"
  :options :
    :size   : 10
  :masters :
#    - 1  : "item1"
#    - 2  : "item2"


property_title:
  :options :
    :size   : 60
  :masters :
#  :format  : "%s"

property_description:
  :options :
    :rows   : 5
    :cols   : 60
#  :column_type : :string
  :ipe_options :
    :rows   : 3
    :cols   : 30


property_url:
  :options :
    :size   : 60
  :masters :
#  :format  : "%s"

property_created_on:
  :time_format : '%Y-%m-%d %H:%M:%S'
  :options     :
    :include_blank     : true
    :use_month_numbers : true
#    :start_year        : 2000


property_updated_on:
  :time_format : '%Y-%m-%d %H:%M:%S'
  :options     :
    :include_blank     : true
    :use_month_numbers : true
#    :start_year        : 2000


property_keyword_id:
#  :format  : "%s points"
  :options :
    :size   : 10
  :masters :
#    - 1  : "item1"
#    - 2  : "item2"
非表示のフィールドの指定

表示したくないフィールドは、以下のように指定すると、簡単に非表示に出来る。

app/controllers/softwares_controller.rb
class SoftwaresController < ApplicationController
  include SoftwaresHelper

  hide_field :id, :url, :only => [:index, :list, :list_by_keyword, :list_in_order]
  hide_field :id, :created_on, :updated_on, :only => [:new, :confirm_create, :create, :edit, :onfirm_update, :update]
...(以下省略)...
list表示もパーシャルで部分描画するようにしてみた。

jascaffoldでは、未使用だが_list.rhtmlも用意されていた。それに触発されて、最近ごちゃごちゃしてきたtable表示に関する部分をパーシャル化してみた。

app/views/softwares/list.rhtml

before

<h1>Listing softwares</h1>

<table>
  <tr>
  <% for column in Software.content_columns %>
    <th><%= link_to "#{@direction_mark if @order_field==column.name}#{column.human_name}", 
                    :action => 'list_in_order', 
                    :keyword_id => @keyword_id, 
                    :order_field => column.name,
                    :order_direction => @order_next_direction unless column.name == 'url' %></th>
  <% end %>
    <th><%= link_to "#{@direction_mark if @order_field=='keyword_id'}Keyword", 
                    :action => 'list_in_order', 
                    :keyword_id => @keyword_id, 
                    :order_field => 'keyword_id', 
                    :order_direction => @order_next_direction %></th>
  </tr>
  
<% for software in @softwares %>
  <tr>
  <% for column in Software.content_columns %>
    <td><%= link_to_if column.name == 'title',
                       h(software.send(column.name)), 
                       URI.encode(software.send('url')) unless column.name == 'url'  %></td>
  <% end %>
  
  <td><%= link_to h(software.keyword.name), 
                 :action => 'list_by_keyword', 
                 :keyword_id => software.keyword_id, 
                 :order_field => @order_field, 
                 :order_direction => @order_direction unless software.keyword_id == nil %></td>
                   
    <td><%= link_to 'Show', :action => 'show', :id => software %></td>
    <td><%= link_to 'Edit', :action => 'edit', :id => software %></td>
    <td><%= link_to 'Destroy',
                    { :action => 'destroy', :id => software },
                      :confirm => "#{software.title} is deleted. Are you sure?",
                      :post => true %></td>
  </tr>
<% end %>
</table>
...(以下省略)...


after

<h1><%= localize(:model, :software) %><%= localize(:title, :list) %></h1>

<div class="indent">
<table class="confirm">
<%= render :partial => 'models/softwares/listh' %>  
<%= render :partial => 'models/softwares/listd', :collection => @softwares %>
</table>
...(以下省略)...

render :partial => 'models/softwares/listd', :collection => @softwaresで、@softwaresが示す配列の件数分、繰り返し描画してくれる。render :partial => 'listd'で呼び出すと、変数listdに1件ごとの内容が代入される。(呼び出したファイル名と同じ変数名になるようだ)以下のforループと同じことを1行でやってくれる。

<% for listd in @softwares %>
  <%= render :partial => 'models/softwares/listd' %>
<% end %>
app/views/models/softwares/_listh.rhtml

Software.content_columnsでは、idフィールド、または_idや_countで終わるフィールドは、無視される。jascaffoldでは、hide_fieldで簡単に非表示の設定が出来るので、<% for column in Software.columns %>を利用して、すべてのフィールドを取り出すようにした。

<%= localized_error_messages_for 'software' %>

<!--[:]-->
<tr>
<% for column in Software.columns %>
  <% unless @controller.class.hidden_field?(@action_name, column.name) %>
    <th><%= link_to "#{@direction_mark if @order_field==column.name}#{human_attribute_name(Software, column.name)}", 
                    :action => 'list_in_order', 
                    :keyword_id => @keyword_id, 
                    :order_field => column.name,
                    :order_direction => @order_next_direction %></th>
  <% end %>
<% end %>
  <th><br></th>
</tr>
<!--[:]-->
    • human_attribute_name()で、日本語化した列タイトルに変換してくれるようだ。
app/views/models/softwares/_listd.rhtml

forループで繰り返すのはやめて、面倒だがすべての列を個別に書いた。列ごとに表示方法が異なる場合は、この方が細かな制御をし易いし、後で読み易いのではないかと考えて。ただし、データベースフィールドを追加、削除、変更した場合は、_listd.rhtmlもそれに合わせて変更する必要がある...。forループを使っていれば、変更する必要は無いんだが...。どちらも一長一短だ。

<!--[:]-->
    <tr>
      <%- unless @controller.class.hidden_field?(@action_name, 'title') -%>
        <td><%= link_to h(human_attribute_value(listd, 'title')), 
                  URI.encode(listd.send('url'))  %></td>
      <%- end -%>

      <%- unless @controller.class.hidden_field?(@action_name, 'description') -%>
        <td><%=h human_attribute_value(listd, 'description') %></td>
      <%- end -%>

      <%- unless @controller.class.hidden_field?(@action_name, 'url') -%>
        <td><%=h human_attribute_value(listd, 'url') %></td>
      <%- end -%>

      <%- unless @controller.class.hidden_field?(@action_name, 'created_on') -%>
        <td><%=h human_attribute_value(listd, 'created_on') %></td>
      <%- end -%>

      <%- unless @controller.class.hidden_field?(@action_name, 'updated_on') -%>
        <td><%=h human_attribute_value(listd, 'updated_on') %></td>
      <%- end -%>

      <%- unless @controller.class.hidden_field?(@action_name, 'keyword_id') -%>
        <td><%= link_to h(listd.keyword.name), 
                  :action => 'list', 
                  :keyword_id => listd.keyword_id, 
                  :order_field => @order_field, 
                  :order_direction => @order_direction unless listd.keyword_id == nil %></td>
      <%- end -%>

      <td><%= link_to localize(:label, :show), :action => 'show', :id => listd %>
          <%= link_to localize(:label, :edit), :action => 'edit', :id => listd %>
          <%= link_to localize(:label, :destroy), {:action => 'confirm_destroy', :id => listd}, :confirm => localize(:label, :confirm_destroy) %></td>
    </tr>
<!--[:]-->
    • unless @controller.class.hidden_field?()で、hide_fieldで指定したフィールドは非表示にしてくれるようだ。
    • human_attribute_value()で、db/localized/*.ymlのproperty_*で設定した表示方法を適用してくれるようだ。
グーグルみたいなページ切り替え


こんなページ切り替えの表示にしてみた。pagination_linksを使うと簡単に実現できた。

app/views/softwares/list.rhtml

<%= link_to localize(:label, 'Previous page'), { :page => @software_pages.current.previous } if @software_pages.current.previous %> <%= pagination_links @software_pages %> <%= link_to localize(:label, 'Next page'), { :page => @software_pages.current.next } if @software_pages.current.next %>

config/localized.yml
# リンクボタン等
label:
  new             : 新規作成
  list            : 一覧
  show            : 詳細
  edit            : 編集
  destroy         : 削除
  update          : 更新
  confirm         : 確認
  confirm_destroy : 本当に削除しますか?
  back            : 戻る
  cancel          : キャンセル
  create          : 作成
  has_many        : "(%d)"
  Next page       : 次へ
  Previous page   : 前へ