Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
RubyonRails4アプリケーションプログラミング_読書メモ

1.イントロダクション

Railsというフレームワーク

  • Model-View-Controllerパターンを採用
  • アプリケーション開発のレールを提供
    • DRY(Don't Repeat Yourself)・・・同じ記述を繰り返さない
    • Coc(Convention over Configuration)・・・設定よりも規約
  • フルスタックのフレームワーク
    • アプリケーション開発のためのライブラリ
    • コード生成のためのツール
    • 動作確認のためのサーバ
    • 等々をひとまとめにしたフルスタックなフレームワーク
  • 最新の技術トレンドにいち早く対応
    • HTML5対応
    • 控えめなJavaScript
      • HTMLの中にJavaScriptのコードを混在させるべきではない、という思想
    • RESTfulなインタフェース
      • ネットワーク上のコンテンツを全て一意なURLで表現する
      • リソースに対するCRUD操作は全てHTTPメソッドで表現する

2.Ruby on Railsの基本

アプリケーションの作成

以下のコマンドを実行することで、スケルトンを作れる

rails new appName [options]

RailsはWEBrickというシンプルなHTTPサーバを標準で提供している
起動するには、アプリケーションルートで以下のコマンドを実行する

rails server [name] [options]

コントローラの基本

コントローラクラスは個々のリクエストに応じた処理を行う
コントローラクラスを作成するには、以下のコマンドを実行する

rails generate controller name [options]

コントローラクラスの基本構文

  • ApplicationControllerクラスを継承する
  • 具体的な処理を実装するのはアクションメソッド
    • クライアントからのリクエストに対して、具体的な処理を実行するメソッドのこと
    • publicにすることでアクションメソッドになる

ルーティング設定は、/config.routes.rbに定義する
コントローラの命名規則は以下の通り

  • コントローラクラス・・・先頭は大文字で、接尾辞に「Controller」
  • コントローラクラス(ファイル名)・・・コントローラクラスの小文字スネークケース
  • ヘルパーファイル名・・・コントローラ名に接尾辞「_helper.rb」
  • テストスクリプト名・・・コントローラ名に接尾辞「_controller_test.rb」

ビューの基本

最終的な出力には、ERB(Embedded Ruby)テンプレートを利用する
ERBテンプレートとは、HTMLにRubyスクリプトを埋め込むための仕組み

  • 条件分岐や繰り返し構文などの記述が容易
  • ビューヘルパを利用することで、データベースから取得した値に基づいたリンクやフォーム要素などをシンプルなコードで生成できる

テンプレート変数を利用することで、アクションメソッドとビューでデータを受け渡しできる
コントローラクラスの実装例

class HelloController < ApplicationController
  def view
    @msg = 'Hello World!'
  end
end

テンプレートファイルの実装例

<%= @msg %>

テンプレートファイルは、/app/viewsフォルダ配下に、「コントローラ名/アクション名.html.erb」という名前で保存する必要がある
<% ... %>または<%= ... %>のようなブロックを使うことでRubyスクリプトを埋め込める

<% 任意のコード %>
<%= 何らかの値を返す式 %>

Railsではデフォルトで、application.html.erbの「<%= yeild %>」に個別のテンプレートを埋め込んだ上で、最終的な出力を生成する
application.html.erbのことをレイアウトテンプレート、あるいはレイアウトと呼ぶ

モデルの基本

モデルとは、データベースや外部サービスへのアクセスをはじめ、ビジネスロジック全般を担当するコンポーネントのこと
Rails標準をO/RマッパーはActive Record
config/database.ymlに対して接続設定を定義することで使用可能になる

  • database.ymlはYAML形式で記述する
    • YAMLは構造化データの記述に適したファイル形式
    • 「YAML Ain't Markup Language(YAMLはマークアップ言語ではない)」
    • 構造をインデントや記号で表現する
  • Railsは目的に応じて環境を使い分ける
    • development(開発)、test(テスト)、production(本番)が用意されている

以下のコマンドを実行することで、モデルクラスを作れる

rails generate model name field:type [...] [options]

コマンド例はこんな感じ

rails generate model book isbn:string title:string price:integer publish:string published:date cd:boolean

モデル関連の命名規則

  • モデルクラス・・・先頭は大文字で単数形
  • モデルクラス(ファイル名)・・・先頭は小文字で単数形
  • テーブル・・・先頭は小文字で複数形
  • テストスクリプト・・・xxxxx_test.rb(先頭は小文字で単数形)

Railsでは、マイグレーションという機能でテーブルの作成や修正を行う
マイグレーションを実行するためのファイルはgenerateコマンドを実行することで自動生成される
マイグレーションのコマンドは下記の通り

rake db:migrate

Railsでは、フィクスチャという機能でテストデータをDBに流し込む
/test/fixtureフォルダ配下にYAML形式のファイルを用意することで実行可能

rake db:fixtures:load FIXTURE=books

以下のコマンドでデータベースクライアントを起動できる

rails dbconsole

Railsでテーブルを作成した場合、以下のフィールドも自動生成される

  • id・・・主キー
  • created_at・・・レコードの新規作成日時
  • updated_at・・・レコードの更新日時

作ってみよう

データ取得の実装サンプル(コントローラ)

class HelloController < ApplicationController
  def list
    @books = Book.all
  end
end

データ取得の実装サンプル(テンプレートファイル)

<table border="1">
  <tr>
    <th>ISBNコード</th><th>書名</th><th>価格</th>
    <th>出版社</th><th>刊行日</th><th>CD-ROM</th>
  </tr>
<% @books.each do |book| %>
  <tr>
    <td><%= book.isbn %>></td>
    <td><%= book.title %></td>
    <td><%= book.price %></td>
    <td><%= book.publish %></td>
    <td><%= book.published %></td>
    <td><%= book.cd %></td>
  </tr>
<% end %>
</table>

3.Scaffolding機能によるRails開発の基礎

Scaffoldingは、定型的なCRUD機能を持ったアプリケーションを構築するための機能

  • まずは動作するアプリケーションを作成したい
  • マスタメンテナンスなど、簡単な機能を大量に生成したい
  • Railsによる基本的なCRUD実装を理解したい

といったケースで役立つので便利
以下のコマンドで必要なファイルがまとめて生成される

rails generate scaffold name field:type [...] [options]

DBのマイグレーションはやってくれないので、手動で実行する
ルーティングがどうなってるかの確認は、以下のコマンドが便利

rake routes

一覧画面の作成

books#indexメソッドと、index.html.erbテンプレートが作成される
ビューヘルパとは、テンプレートファイルを記述する際に役立つメソッドの総称
例えば、link_toメソッドを使うことでハイパーリンクを生成できる

link_to(body, url[, html_options])

引数urlにモデルオブジェクトを渡すことで、次の画面にidを引き継ぐことができる
下記の例の場合、「/books/1」のようなパスが生成されることになる

<%= link_to 'Show', book %>

route.rbにresourcesメソッドを定義した場合、以下のビューヘルパが自動生成される

  • books_path・・・/books
  • book_path(id)・・・/books/:id
  • new_book_path・・・/books/new
  • edit_book_path(id)・・・/books/:id/edit

ビューヘルパを利用することで、対応するパスが簡単に取得できる

<%= link_to 'Edit', edit_book_path(book) %>
<%= link_to 'New Book', new_book_path %>

引数html_optionsにdata-confirmを指定することで、リンククリック時に確認ダイアログを表示できる
「data-〜」で始まる属性は、Railsが提供するJavaScript絡みの処理、と覚えておく

<%= link_to 'Destroy', book, method: :delete, data: { confirm: 'Are you sure?' } %>

methodオプションを利用することで、HTTP GET以外のリクエストを生成できる

詳細画面の作成

books#showメソッドと、show.html.erbテンプレートが作成される
コントローラ内では、befoe_actionメソッドを使うことで、アクションメソッドの実行前に必要な値をセットしている

before_action method, only: action

実装例はこちら

before_action :set_book, only: [:show, :edit, :update, :destroy]
(中略)
def show
end
(中略)
private
  def set_book
    @book = Book.find(params[:id])
  end

新規登録画面の作成

books#new、createメソッドと、new.html.erbテンプレートが作成される
新規登録画面と編集画面はレイアウトが同じなので、部分テンプレートを使って共通化している
new.html.erb側の実装

<%= render 'form' %>

_form.html.erb側の実装

<%= form_for(@book) do |f| %>
  (中略)    
  <div class="field">
    <%= f.label :isbn %><br>
    <%= f.text_field :isbn %>
  </div>
  <div class="field">
    <%= f.label :title %><br>
    <%= f.text_field :title %>
  </div>
  <div class="field">
    <%= f.label :price %><br>
    <%= f.number_field :price %>
  </div>
  <div class="field">
    <%= f.label :publish %><br>
    <%= f.text_field :publish %>
  </div>
  <div class="field">
    <%= f.label :published %><br>
    <%= f.date_select :published %>
  </div>
  <div class="field">
    <%= f.label :cd %><br>
    <%= f.check_box :cd %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

部分テンプレートの場合、ファイルの先頭に「_」を付ける
form_forメソッドで、モデルに関連づいたフォームを生成できる

form_for(model) do |f|
  ...フォームの本体...
end

入力フォームを表示するためのnewアクション
インスタンス変数をnewして入力値をしまうための器を作る

def new
  @book = Book.new
end

フォームからの入力値をまとめて取得

private
  def book_params
    params.require(:book).permit(:isbn, :title, :price, :publish, :published, :cd)
  end

入力値を受け取って、登録処理を行うためのcreateアクション

  • 入力値を使ってインスタンス変数を再生成
  • saveメソッドでDBへの永続化と処理の分岐を行う
    • 処理の成否と、どのフォーマットが要求されたかによって処理を分けている

    • 処理に成功した場合、redirect_toで登録後画面に遷移させ、noticeオプションでメッセージを表示

    • 失敗した場合は、new.html.erbを再描画する

    • JSON形式の場合は、HTTPステータスとロケーションを指定して返す

      • 200 OKとか、201 CREATEDとか

      def create @book = Book.new(book_params)

      respond_to do |format| if @book.save format.html { redirect_to @book, notice: 'Book was successfully created.' } format.json { render :show, status: :created, location: @book } else format.html { render :new } format.json { render json: @book.errors, status: :unprocessable_entity } end end end

編集画面の作成

books#edit、updateメソッドと、edit.html.erbテンプレートが作成される
編集フォームを表示するためのeditアクション

  • before_actionでset_bookを呼んでいるので、キーに紐づく入力値を取得できる

    def edit end

入力値を受け取って、登録処理を行うためのupdateアクション

def update
  respond_to do |format|
    if @book.update(book_params)
      format.html { redirect_to @book, notice: 'Book was successfully updated.' }
      format.json { render :show, status: :ok, location: @book }
    else
      format.html { render :edit }
      format.json { render json: @book.errors, status: :unprocessable_entity }
    end
  end
end

削除機能の確認

books#destroyメソッドが作成される

  • headメソッドはHTTPステータスのみを通知し、コンテンツ本体は出力しない

  • 処理は成功したが、特に返すべきコンテンツがない場合に使う

    def destroy @book.destroy respond_to do |format| format.html { redirect_to books_url, notice: 'Book was successfully destroyed.' } format.json { head :no_content } end end

4.ビュー開発

フォーム関連のビューヘルパ

フォーム関連のビューヘルパは、

  • フォームを生成するためのヘルパが2種類
    • form_tag
    • form_for
  • 個別の入力フィールドを生成するためのヘルパが3種類
    • FormTagヘルパ
    • Formヘルパ
    • t.Formヘルパ

に分類できる

form_tagメソッド

汎用的なフォームを出力する

form_tag([url_opts [,opts]]) do
  ... body ...
end

form_forメソッド

モデル編集のためのフォームを生成する

form_for(var [,opts]) do |f|
  ... body ...
end

その他入力フォーム部品

  • text_field・・・テキストフィールドを生成する
    • password_field・・・パスワード入力用のフォームを生成する
    • hidden_field・・・hiddenを生成する
  • text_area・・・テキストエリアを生成する
  • radio_button・・・ラジオボタンを生成する
  • check_box・・・チェックボックスを生成する

Rails4では、HTML5対応のxxxx_fieldヘルパも用意している

選択ボックスの生成方法いろいろ

一番シンプルなやり方は、selectメソッドを使う

<%= form_for(@book) do |f| %>
  <%= t.select :publish ['技術評論社' => 1, '翔泳社' => 2, 'マイナビ' => 3] %>
<% end %>

データベースの値を元に生成したい場合は、collection_selectメソッドを使う

<%= form_for(@book) do |f| %>
  <%= f.collection_select :publish, @books, :publish, :publish %>
<% end %>

<optgroup>タグを使ってグループ化したい場合は、grouped_collection_selectメソッドを使う

<%= form_for(@book) do |f| %>
  <%= f.grouped_collection_select :book_id, @authors, :books, :name, :id, :title %>
<% end %>

モデルと関連づかない選択ボックスを生成する場合は、select_tagを使う
select_tagでは、第2引数にoptions_xxxxメソッドを使うことで選択肢を動的に生成できる

  • options_for_select・・・配列とハッシュから生成
  • options_from_collection_for_select・・・データベースから動的に生成
  • option_groups_from_collection_for_select・・・グループ分けされた選択肢を生成

日付/時刻の入力に特化した選択ボックスも生成できる

  • datetime_select
  • date_select
  • time_select

データベースの情報を元に、ラジオボタン、チェックボックスの生成もできる

  • collection_radio_buttons
  • collection_check_boxes

その他のフォーム系ヘルパー

  • label・・・ラベルテキストを生成する
  • submit・・・サブミットボタンを生成する
  • fields_for・・・form_forブロックの配下で異なるモデルを編集できる
    • 複数のモデルを対象とした複合フォームを作れて便利
  • field_set_tag・・・fieldsetとlegendでフォーム要素をグループ化できる

文字/数値関連のビューヘルパ

  • simple_format・・・改行文字を<p>、<br>で置き換える
  • truncate・・・文字列を指定した桁で切り捨てる
    • 切り捨てた部分は「...」で表示される(options引数で変更可能)
  • excerpt・・・文字列から特定の部分のみを抜粋する
  • cycle・・・テーブルやリストの背景色をn行おきに変更する
  • highlight・・・特定のキーワードをハイライト表示する
  • concat・・・スクリプトブロックの中に出力コードを埋め込む
  • sanitize・・・文字列からタグを除去する
  • number_xxxxx・・・数値を様々な形式で加工する
    • number_to_currency・・・通貨形式に変換
    • number_to_human・・・100,100,1000の単位に変換
    • number_to_human_size・・・KB、MBの単位に変換
    • number_to_percentage・・・パーセント形式に変換
    • number_with_delimiter・・・桁区切り文字を追加
    • number_with_precision・・・特定の桁数で丸める

リンク関連のビューヘルパ

link_to

ハイパーリンクを生成するには、link_toメソッドを使う
例えば、こんな風に実装すると、

<%= link_to 'トップ',{ controller: :hello, action: :index } %>

以下の通りレンダリングされる

<a href="/hello">トップ</a>

その他リンク関連メソッド

  • url_for・・・ルート定義から動的にURLを生成する
  • link_to_if・・・条件に当てはまる場合にリンクを生成する
    • link_to_unlessを使うと、条件に当てはまらない場合にリンクを生成する
  • link_to_unless_current・・・指定のページの場合はリンクを無効にする
    • リンク先が現在のページの場合はテキストを出力、といったことをしたい場合に便利
  • mail_to・・・メールアドレスへのリンクを生成する

外部リソース指定のためのビューヘルパ

  • image_tag・・・イメージタグを生成する
    • 引数srcで相対パスが指定された場合、/app/assets/imagesの中からファイルを探しに行く
    • 「/」で始まるパスを指定すると「/public」フォルダ配下の任意のフォルダを探しに行く
  • audio_tag・・・音声をブラウザで再生する
  • video_tag・・・動画をブラウザで再生する
  • auto_discovery_link_tag・・・ブラウザのフィード検出機能を有効にする
  • favicon_link_tag・・・ファビコンを定義する
  • path_to_xxxxx・・・・外部リソースのパスを取得する
    • path_to_javascript・・・JavaScriptファイルのパスを取得
    • path_to_stylesheet・・・スタイルシートのパスを取得
    • path_to_audio・・・音声ファイルへのパスを取得
    • path_to_video・・・動画ファイルへのパスを取得
    • path_to_image・・・画像ファイルへのパスを取得

その他のビューヘルパ

  • debug・・・構造化データをダンプ出力する
  • capture・・・出力結果を変数に格納する
  • tag・・・本体持たない任意のタグを生成する
  • content_tag・・・本体をもつ任意のタグを生成する

ビューヘルパの自作

ビューヘルパは/app/helpersフォルダ配下のxxxxx_helper.rbに記述するのが基本
ヘルパクラスにメソッド定義するとビューヘルパとして扱える
ビューヘルパの結果として、HTML文字列を返したい場合、content_tagやtagメソッドを使う

module viewHelper
  def list_tag(collection, prop)
    content_tag(:ul) do
      collection.each do |element|
        concat content_tag(:li, element.attributes[prop])
      end
    end
  end
end

アプリケーション共通のデザインを定義する - レイアウト

Railsでは、特に何も指定しない場合、/app/views/layoutsフォルダ配下のapplication.html.erbをレイアウトとして適用しようとする

  • コントローラ単位にレイアウトを設定する
    • /app/views/layoutsフォルダ配下に、「コントローラ名.html.erb」という名前で保存する
    • layoutメソッドを使って明示的にレイアウトを指定する
  • アクション単位にレイアウトを設定する
    • renderメソッドでlayoutオプションを指定する

レイアウトに複数のコンテンツ領域を設置したい場合は、yeildメソッドの引数として領域名を指定する

<html>
  <head> ... </head>
  <body>
    <%= yield :extend_menu %>
    <%= yield %>
  </body>
</html>

このようなレイアウトに対してコンテンツを埋め込むには、テンプレートファイルでcontent_forメソッドを使う

content_for(name) do
  content
end

テンプレートの一部をページ間で共有する - 部分テンプレート

断片的なページの共通領域を定義するために使う
部分テンプレートを保存する場合には、ファイル名の先頭には「_」を付けなければならない
部分テンプレートの保存先ルールは以下の通り

  • 特定のコントローラのみで共有・・・/views/コントローラ名
  • アプリケーション全体で共有・・・/views/application
  • リソースに強く関連づいた部品・・・/views/リソース名(複数形)

定義された部分テンプレートを取り込むには、renderメソッドを使う

<%= render 'books/book' %>

コレクションに繰り返し部分テンプレートを適用することもできる

<%= render partial: 'book/books', collection: @books, locals: {type: :details} %>

省略して以下のように書くこともできる

<%= render @books, type: :details %>

5.モデル開発

findメソッド

引数に主キーを渡すことで、合致するレコードを取り出せる

find(keys)

任意の列をキーにテーブルを検索し、ヒットした最初の一件を取得する

find_by key: value [,...]

クエリメソッド

クエリメソッドでは、findやfind_byなどのメソッドと違って、その場ではデータベースにアクセスしない
結果をActiveRecord::Relationとして返すだけ
結果が必要になって初めて、データベースへの問い合わせを行う(遅延ロード)

where

whereメソッドでは、プレイスホルダを使用できる
名前なしパラメータでの呼び出し例

@books = Book.where('publish = ? AND price >= ?',
         params[:publish], params[:price])

名前付きパラメータでの呼び出し例

@books = Book.where('publish = :publish AND price >= :price',
         publish: params[:publish], price: params[:price])

実行する前であれば、一度追加した条件式を取り外すこともできる
取り外しにはunscopeメソッドを使う

  • not・・・否定の条件式を表す

order

取得したデータを特定のキーで並び替えるには、orderメソッドを使う

@books = Book.where(publish: '技術評論社').order(published: :desc)
  • reorder・・・ソート式を上書きする

select

Active Recordでは、デフォルトで全ての列を取得しようとする
selectメソッドを使うことで取得する列を明示的に指定できる

  • distinct・・・重複のないレコードを取得する

limitとoffsetを組み合わせることで、特定範囲のレコードだけを抽出できる
limitで取得する件数、offsetでデータの取得位置を指定できる

@books = Book.order(published: :desc).limit(3).offset(4)
  • first・・・結果セットの先頭レコードを取得する
  • last・・・結果セットの末尾レコードを取得する

group

特定のキーで結果をグループ化する

  • having・・・集計結果をもとにデータを絞り込む

none

noneメソッッドを呼び出すことで、空の結果セットを取得できる
リストにデータを0件表示したいとき等に使う(nilを代入するとエラーになるため)

データ取得のためのその他のメソッド

  • pluck・・・指定した列の配列を取得する
  • exists?・・・データの存在を確認する
  • count・・・検索結果の行数を取得する
  • 検索条件に合致するレコードの平均や最大/最小を求める
    • average
    • minimum
    • maximum
    • sum
  • find_by_sql・・・生のSQLを直接指定する

名前付きスコープ

特定の条件式やソート式などをあらかじめモデル側で名前付けしておける仕組みのこと
以下のように定義すると、

scope :whats_new -> {
  where(publish: pub).order(published: :desc).limit(5)
}

以下のように使える

@books = Book.whats_new

モデル呼び出しの際に、デフォルトで適用されるデフォルトスコープという機能もある

レコードの登録/更新/削除

  • レコードを更新する
    • 複数のレコードをまとめて更新する場合は、update_all
  • レコードを削除する
    • いったんオブジェクトを取得してから削除する場合は、delete
    • そもそも不要ならば、destroy
    • まとめて削除するなら、destroy_all

トランザクション処理

トランザクションを貼りたい場合は、transactionメソッドを使う
save!メソッドは保存に失敗した場合に例外を返すので、rescueでキャッチする

def transact
    Book.transaction do
      b1 = Book.new({isbn: '9784774142230',
                     title: 'Rubyポケットリファレンス',
                     price: 2000,
                     publish: '技術評論社,
                     published: '2011-01-01'})
      b1.save!
      raise '例外発生!'
      b2 = Book.new({isbn: '9784774142232',
                     title: 'Tomcatポケットリファレンス',
                     price: 2500,
                     publish: '技術評論社,
                     published: '2011-01-01'})
      b2.save!
    end
    render text: 'トランザクションは成功しました。'
  rescue => e
    render text: e.message
end

Rails4では、トランザクション分離レベルを指定できる
分離レベルが高ければ、それだけデータの整合性が高まるが、同時実効性は低下する

オプティミスティック同時実行制御

Active Recordには、標準で楽観ロック制御の仕組みがある

  • テーブルにlock_version列を追加する
  • lock_version列の値をhiddenとして定義し、受け渡しする
  • 例外検出時のコードを記述する
    • 楽観ロックエラー時は、ActiveRecord::StaleObjectErrorが発生する

検証機能の実装

モデルクラスに検証ルールを定義する

class Book < ActiveRecord::Base
  validates :isbn,
    presence: true,
    uniqueness: true,
    length: { is: 17 }
  validates :title,
    presence: true,
    length: { minimum: 1, maximum: 100 }
  validates :price,
    numericality: { only_integer: true, less_than: 10000 }
  validates :publish,
    inclusion: { in: ['技術評論社', '翔泳社', '秀和システム', '日経BP社', 'ソシム'] }
end

検証エラーを表示する

<% if @book.errors.any? %>
  <div id="error_explanation">
    <h2><%= pluralize(@book.errors.count, "error") %>prohibited this book from being saved:</h2>
    <ul>
      <% @book.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
    </ul>
  </div>
<% end %>

検証エラーの発生時には、対象要素を表すlabel、input要素がdivが囲まれる
divにはclass="field_with_errors"が付与されるため、ここめがけてスタイルを適用できる

その他の検証クラス

  • acceptance・・・ユーザが利用規約などに同意しているかを検証する
    • データベースに対応するフィールドを用意する必要はない
  • confirmation・・・パスワードなどを二回入力させる場合に、両者が等しいかを検証する
    • 検証を有効にした場合、もとにフィールド名に「_confirmation」を加えた仮想的な属性が追加される
  • uniqueness・・・指定されたフィールドが一意かどうかを検証する

検証クラス共通のパラメータ

  • allow_nil・・・nilの場合、検証をスキップ
  • allow_blank・・・nilと空白の場合、検証をスキップ
  • message・・・エラーメッセージ
  • on・・・検証のタイミング(デフォルトはsave時)
  • if・・・条件式がtrueの場合のみ検証を実施
  • unless・・・条件式がfalseの場合のみ検証を実施

自作検証クラスの定義

検証クラスは、ActiveModel::EachValidatorの派生クラスとして、「(検証名)Validator」の形式で命名する
検証の実処理は、validate_eachメソッドに定義する
検証時に発生したエラー情報は、errors.addメソッドを介してモデルオブジェクトrecordに登録する

class IsbnValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    pattern = '\A[0-9]{3}-[0-9]{1}-[0-9]{3,5}-[0-9]{4}-[0-9X]{1}\z'
    record.errors.add(attribute, 'は正しい形式ではありません。') unless value =~ /#{pattern}/
  end
end

検証クラスの末尾から「validator」を取り除いて、スネークケース化した名前で呼び出し可能
パラメータ情報には、「options[パラメータ名]」でアクセスできる
検証クラスを定義せず、モデルの中でプライベートメソッドとして検証ルールを定義することもできる

class Book < ActiveRecord::Base
  validate :isbn_valid?

  private
  def isbn_valid?
    errors.add(:isbn, 'は正しい形式ではありません。') unless value =~ /\A[0-9]{3}-[0-9]{1}-[0-9]{3,5}-[0-9]{4}-[0-9X]{1}\z/
  end
end

定義したメソッドは、validateメソッドで呼び出すことができる

ActiveModel::Modelモジュール

ActiveModelとは、モデルの基本的な構造や規約を決定するコンポーネント
Rails4では、ActiveModelの機能を直接利用することで、データベースと対応関係にないモデルを実装することもできる
実装時のルールは以下の通り

  • ActiveModel::Modelモジュールをインクルードすること

  • モデルとして管理すべき項目をアクセサ(attr_accessorメソッド)で定義すること

    class SearchKeyword include ActiveModel::Model

    attr_accessor :keyword
    
    validates :keyword, presence: true
    

    end

アソシエーションによる複数テーブルの処理

アソシエーションとは、テーブル間のリレーションシップをモデル上の関係として操作できるようにする仕組みのこと
複数のテーブルにまたがる操作を直感的にできるようになる
Railsでリレーションシップを表現するには、命名規則を守る必要がある

  • 外部キー列は「参照先のモデル名_id」の形式であること
  • 中間テーブルは参照先のテーブル名を「_」で連結したものであること
    • ただし、連結順は辞書順とする

belongs_toアソシエーションの実装例を以下に示す
参照元のモデルクラスにアソシエーションを付与して、

class Review < ActiveRecord::Base
  belongs_to :book
end

参照元のコントローラで値を取得すると、

def belongs
  @review = Review.find(3)
end

参照先のオブジェクトにわかりやすくアクセスできる

<h2><%= @review.book.title %>のレビュー</h2>
<hr />
<p><%= @review.body %>(<%= @review.updated_at %>)</p>

アソシエーションには以下のようなものがある

  • belongs_to・・・参照元テーブルから参照先テーブルの情報にアクセスする
  • has_many・・・1:nの関係を表現する
  • has_one・・・1:1の関係を表現する
  • has_and_belongs_to_many・・・m:nの関係を表現する
    • 単純な中間テーブルをもつ場合はこちらを使う
  • has_many_through・・・m:nの関係を表現する
    • 中間テーブルの要素にもアクセスしたい場合はこちらを使う

アソシエーションで利用できるオプション

標準の動作で賄えないケースが出てきた場合、オプション指定で対応できる
例えば以下のような感じ

class Author < ActiveRecord::Base
  has_many :comments , -> { where(deleted: false) }, class_name: 'FanComment', foreign_key: 'author_no'
end
  • クラス名と異なる関連名をつけることも可能
    • その場合、class_nameオプションでクラス名を指定する必要がある
  • foreign_keyオプションで外部キーの指定が可能
  • ラムダ式を渡すことであらかじめ結果をフィルタリングすることも可能

カウンターキャッシュ

子モデルの件数を親モデルで管理するための仕組み

  • カウンター管理のための列を作成する
    • 親テーブルに「子テーブル名_count」という名前でinteger型の列を準備する
    • ActiveRecordではこのカウンター列に対して、関連モデルの件数を記録する
  • カウンターキャッシュを有効にする
    • counter_cache: true を子モデルに定義する

ポリモーフィック関連

一つのモデルが複数の親モデルに紐づく関連のこと
ポリモーフィック関連では、外部キーだけでは紐付けを表現できないため、

  • XXXXX_type(紐付けするモデル)
  • XXXXX_id(外部キー)

のような列をテーブルに準備しておく必要がある
モデル側では、以下のような宣言が必要となる

  • 親モデル側でasオプション付きのhas_manyメソッドを宣言
  • 子モデル側でpolymorphicオプション付きのbelongs_toメソッドを宣言

その他テーブル結合

アソシエーションを使わずにテーブル結合する方法もある

  • join・・・関連するモデルと結合する
  • includes・・・関連するモデルをまとめて取得する

コールバック

ActiveRecordによる検索、登録、更新、削除、及び検証処理のタイミングで実行されるメソッドのこと
モデル操作のタイミングでまとめて実行すべき処理は、コールバックとして定義することで、同じようなコードが分散するのを防げる
コールバックを利用することで、関連する一連の処理を、1トランザクションの中に収められる

class Book < ActiveRecord::Base
  after_destroy :history_book

  private
  def history_book
    logger.info('deleted: '+ self.inspect)
  end
end

コールバックを複数のモデルで共有するようなケースでは、コールバッククラスとして外部化すると良い

マイグレーション

Railsでは、テーブルレイアウトを作成、変更するための仕組みとしてマイグレーションという機能を提供している
マイグレーション機能を利用した場合、schema_migrationsテーブルに実行済みマイグレーションファイルのタイムスタンプが記録される
schema_migrationsテーブルとdb/migrateフォルダ配下のファイルを比較して、未実行のマイグレーションの有無を判定する

マイグレーションファイルの作成

マイグレーションファイルを作成する方法は以下の二種類

  • rails generate modelコマンドでモデルと合わせて作成する
  • rails generate migrationコマンドを使ってマイグレーションファイル単体で作成する

すでに存在するテーブルを修正したい場合は、後者を使う
フィールドの追加/削除の際には、

  • AddXxxxxTo テーブル名
  • RemoveXxxxxFrom テーブル名

の形式に則っておくと、コードが自動生成されるので便利

マイグレーションファイルで利用できる主なメソッド

  • change_table・・・テーブル定義を変更する
  • add_index・・・インデックスを追加する
    • インデックス名はデフォルトで「テーブル名_フィールド名_index」となる
  • remove_index・・・インデックスを削除する
  • execute・・・任意のSQL命令を実行する
  • create_join_table・・・HABTM中間テーブルを作成する
    • has_and_belong_to_many(m:nの関係)

マイグレーションファイルの実行

主な実行時コマンドは以下の通り

  • db:migrate・・・指定されたバージョンまで移行(未指定の場合、最新にする)
  • db:rollback・・・指定ステップだけバージョンを戻す
  • db:migrate:redo・・・指定ステップだけバージョンを戻して再実行
  • db:migrate:reset・・・データベースを削除し、再作成して、最新バージョンになるようマイグレート

rakeコマンドでは、database.ymlで定義された開発データベースに対して処理を行う
テスト環境や本番環境に対して処理を行いたい場合は、RAILS_ENVオプションを指定する

rake db:migrate RAILS_ENV=test

リバーシブルなマイグレーションファイル

Rails4では、スキーマのバージョンアップ、バージョンダウンに対応している
ほとんどのコマンドは標準でロールバック可能だが、一部、ロールバックできないものもある
対処方法は下記の通り

  • remove_column、drop_tableメソッド
    • 削除すべき列の情報を引数で明記しておくことでロールバック可能になる
  • reversibleメソッド
    • changeメソッドの中でバージョンアップ時の処理とバージョンダウンじの処理を分岐して記述できる
  • up、downメソッド
    • changeメソッドの代わりに、up、downメソッドで処理を明記することもできる

データベースを一から構築したい場合は、スキーマファイル(db/schema.rb)を使う

rake db:schema:load

データの初期化

Railsでは、データを初期化するためにシードファイルとフィクスチャを提供している

  • シードファイル
    • マスタテーブルなどの初期データを投入するのに使う
    • Ruby(ActiveRecord)でデータを生成/保存するコードを書くだけ
    • 作成したファイルは「rake db:seed」で実行可能
  • フィクスチャ
    • テストデータを投入するのに使う
    • YAML形式で作成する
    • 作成したファイルは「rake db:fixtures:load」で実行可能

6.コントローラ開発

リクエスト情報

Railsでは、クライアントから送信された値を一つにまとめて、params[:パラメータ名]という形式でアクセスできるようにしている リクエスト情報は下記の通り

  • ポストデータ・・・フォームから送信された情報
  • クエリ情報・・・URLの末尾「?」以降に「key=value& ... 」の形式で付与された情報
  • ルートパラメータ・・・ルートで定義されたパラメータ(「/books/1」の「1」の部分など)

マスアサイメント脆弱性を回避する

マスアサイメントとは、ActiveRecordにもともと備えられている機能の一つ
モデルに対して値をまとめて設定できて便利だが、ポストデータを改ざんすれば値を好きに変更できてしまう
StrongParametersを設定することで回避可能

def create
  @book = Book.new(book_params)
  ...中略...      
end

def book_params
  params.require(:book).permit(:isbn, :title, :price, :publish, :published, :cd)
end

requireメソッドは、まず指定されたモデルに対応するキーが存在するかを確認する
存在する場合はその値を返す
permitメソッドは、モデルへの一括設定を許可するプロパティを指定する
StrongParametersの挙動は

  • /config/application.rb
  • /environments/*.rb

から指定できる

リクエストヘッダを取得する

Railsでリクエストヘッダにアクセスするには、request.headersメソッドを利用する
よく利用するヘッダ情報については、専用のメソッドがあるのでそちらを使う

レスポンスの操作

Railsでは、アクションでの処理結果を出力するためのメソッドを提供している

  • render・・・テンプレートの呼び出しやテキスト/スクリプトの出力など、汎用的な結果出力の手段
  • redirect_to・・・指定されたページに処理をリダイレクトする
  • send_file・・・指定されたパスに存在するファイルを読み込み、その内容をクライアントに送信する
  • send_data・・・指定されたバイナリデータを受け取り、ブラウザに出力する

renderのやり方いろいろ

アクション名と異なるテンプレートを呼び出す
現在のコントローラが「ctrl」でctrl/index.html.erbを呼び出したい場合、

render action: 'index'

異なるフォルダのテンプレートを呼び出す

render template: 'hello/view'

アプリケーション外のテンプレートを呼び出す

render file: 'data/template/list'

上記のいずれの場合も、オプション名を省略して以下の通り記述できる

render 'index'
render 'hello/view'
render 'data/template/list'

文字列を直接出力することもできる

render text: '今日はいい天気ですね。'

空のコンテンツを出力する

空のコンテンツを出力したい場合(Ajax通信でサーバ側の処理結果のみを返したい、等)、nothingオプションを使う

render nothing: true, status: 404

headメソッドでも同様のことができる

head 404

HTML以外のレスポンス処理

renderメソッドにxml/jsonオプションを指定すると、変換して出力される

def get_xml
  @books = Book.all
  render xml: @books
end

JSON/XMLデータについても、テンプレート経由で出力するのが望ましい
JSONデータの生成はJBuilder、XMLデータの生成にはBuilderでやると良い
簡易的なエラーメッセージを出力するなど、テンプレートを用意するまでもない場合、ヘッダだけを出力したい場合は、respond_toメソッドで対応する

def create
  @book = Book.new(book_params)

  respond_to do |format|
    if @book.save
      format.html { redirect_to @book, notice: 'Book was successfully created.' }
      format.json { render action: 'show', status: :created, location: @book }
    else
      format.html { render action: 'new' }
      format.json { render json: @book.errors, status: :unprocessable_entity }
    end
  end
end

状態管理

Railsでは状態管理の実装手段として、クッキー、セッション、フラッシュを提供している

クッキー

クッキーを設定するには、cookiesメソッドを利用する

cookies[:email] = params[:email]

既存のクッキーを削除するには、cookies.deleteメソッドを利用する
ただし、domain、pathオプションで制約されたクッキーは、削除に際してもdomain、pathを使う必要がある

セッション

Railsのセッションでは、デフォルトでクッキーにすべての情報を保存する
設定を変更すれば、キャッシュやデータベースにも保存できる
セッションを設定するには、sessionメソッドを使う

session[:email] = params[:email]

既存のセッションを破棄する場合は、

  • キー単位での破棄ならnilを設定する
  • 全てのセッションを破棄する場合はreset_sessionメソッドを使用する

セッションに関わる設定は、/config/initializersフォルダ配下の初期化ファイルで設定する

フラッシュ

現在のリクエストと次のリクエストでのみデータを維持する
redirect_toメソッドでnoticeオプションとして指定された文字は、リダイレクト先にフラッシュ経由で引き継がれる

respond_to do |format|
  if @book.save
    format.html { redirect_to book, notice: 'Book was successfully created.' }
    .. 中略 ..
  end
end

notice、alertオプションを利用する他、flashメソッドを使うことでもフラッシュを設定できる

format.html {
  flash[:msg] = 'Book was successfully created.'
  redirect_to @book
}

フィルタ

アクションメソッドの前、後などで付随的な処理を実行するための仕組み
アクセスログや認証、アクセス制御などをアクション個別に記述しなくてよくなる
アクションの直前、または直後で実行すべき処理は、before/after、フィルタに記述する

class CtrlController < ApplicationController
  before_action :start_logger
  after_action :end_logger

  private
  def start_logger
    logger.debug('[Start]' + Time.now.to_s)
  end

  def end_logger
    logger.debug('[Finish]' + Time.now.to_s)
  end
end

アクション前後の処理をまとめて記述する場合はaroundフィルタを使う
どのタイミングで処理を呼び出すかはyieldメソッドで決める

class CtrlController < ApplicationController
  around_action :around_logger

  private
  def around_logger
    logger.debug('[Start]' + Time.now.to_s)
    yield
    logger.debug('[Finish]' + Time.now.to_s)
  end
end

フィルタの適用範囲をカスタマイズする

  • onlyオプション・・・指定したアクションに対してのみ実行
  • exceptオプション・・・指定したアクションを除いて実行

継承したフィルタを除外したい場合は、skip_xxxxx_actionメソッドを使う

  • skip_before_action
  • skip_after_action
  • skip_around_action

アプリケーション共通の挙動を定義する

Applicationコントローラは、アプリケーションにデフォルトで用意されているコントローラ
すべてのコントローラの基底クラスなので、アプリケーション共通の機能実装するのに適している

  • ログイン機能
  • 共通的な例外処理
    • rescue_fromメソッドで共通的なものをまとめる
  • クロスサイトリクエストフォージェリ対策
    • protect_from_forgery with: :exception を入れると有効になる
    • 開発者が留意すべきポイントは、
      • HTTP GETによるリンクではデータ操作を行わない
      • データ操作のリクエストは、form_for/form_tag、link_toなどのビューヘルパ経由で生成する
      • レイアウトを自分で作成する場合は、csrf_meta_tagsの呼び出しを忘れない(application.html.erbには記述済み)

7.ルーティング

RESTfulインタフェースを定義する

RESTfulなインタフェースを定義するには、routes.rbでresourcesメソッドを呼び出す

Railbook::Application.routes.draw do
  resources :users
end

上記の通り定義すると、以下のルートが生成される

  • /users・・・index
  • /users/:id・・・show
  • /users/new・・・new
  • /users・・・create
  • /users/:id/edit・・・edit
  • /users/:id・・・update
  • /users/:id・・・destroy

resourceメソッドで定義すれば、単一リソースの定義もできる

  • /config・・・show
  • /config/new・・・new
  • /config・・・create
  • /config/edit・・・edit
  • /config・・・update
  • /config・・・destroy

http://localhost:3000/rails/info/routes」にアクセスすると、定義済みのルートを一覧表示できる

RESTfulインタフェースのカスタマイズ

デフォルトのルートだけでは全てを賄えないため、カスタマイズ手段も用意している

ルートパラメータの制約条件

constraintsオプションで「パラメータ名: 正規表現」の形式で指定できる

Railbook::Application.routes.draw do
  resources :books, constraints: { id: /[0-9]{1,2}/ }
end

より複雑な制約条件を定義したい場合は、制約クラスを利用する
制約クラスであることの条件はmatches?メソッドを実装していること
matches?メソッドは、

  • 引数としてリクエスト情報(requestオブジェクト)を受け取り
  • 戻り値としてルートを有効にすべきかどうか(true/false)を返す 必要がある

formatオプション

複数のフォーマットに対応したくない場合、formatオプションをfalseにする
これによって、URLパターンから「(:format)」が除去されたルートが生成される

controller/asオプション

controller/asオプションを指定することで、マッピングすべきコントローラや、生成するUrlヘルパの名前を変更できる

namespace/scopeブロック

モジュールを利用してコントローラを特定のサブフォルダ配下にまとめる場合、

rails generate controller Admin::Bookd

上記のようなコマンドを実行すると、controllers/adminフォルダ配下にコントローラを作成できる
このようなモジュール対応のコントローラに対して、RESTfulインタフェースを定義するには、namespaceブロックを利用する

namespace :admin do
  resources :books
end

これで、 /admin/books や /admin/books/:id のようなURLパターンを生成できる
URLヘルパも、admin_books_path や admin_book_path(id)のような形で生成される
モジュールを認識したいだけで、URLパターンやUrlヘルパに影響を出したくない場合は、scopeを使う

scope module: :admin do
  resources :books
end

RESTfulインタフェースの拡張

resources/resourceで生成されるルートに対して、自前のアクションを追加できる

  • collection・・・複数のオブジェクトを扱うアクション
  • member・・・単一のオブジェクトを扱うアクション

実装例はこんな感じ

resources :reviews do
  collection do
    get :unapproval
  end
  member do
    get :draft
  end
end

デフォルトで生成されるアクションの一部を無効化したい場合、exceptオプションを指定する
一部を有効化したい場合は、onlyオプションを指定する

resources :users, except: [ :show, :destroy ]

階層構造を持ったリソースを表現する

リソース同士の親子関係をURLで表現したい場合、resources/resourceをネストさせる

resources :books do
  resources :reviews
end

逆に、階層を浅くしたい場合は、shallowオプションを指定する

resources :books do
  resources :reviews, shallow: true
end

shallowオプションによって、

  • :idパラメータを受け取らないindex、new、createアクションは、:book_idを付与したURL
  • それ以外のアクションは、ネストされないURL

が生成される

ルート定義を再利用可能にする

concernメソッドを利用することで、複数のルート定義で共通する内容を切り出せる

非RESTfulなルートの定義

非RESTfulなルートを定義するには、matchメソッドを利用する
ルートに対して、ルートを設定するには、rootメソッドを利用する

8.テスト

Railsでは、以下のテストをサポートしている

  • Unitテスト・・・モデルやビューヘルパ単体の動作をチェック
  • Functionalテスト・・・コントローラ/テンプレートの呼び出し結果をチェック
  • Integrationテスト・・・複数のコントローラにまたがる、ユーザの実装の操作をチェック

Unitテスト

アプリケーションを構成するライブラリが正しく動作するかをチェックするためのテスト
テストを実施するためのメソッドは、testメソッドで定義する

require 'test_helper'

class BookTest < ActiveSupport::TestCase
  test "book save" do
    book = Book.new({
      isbn: '978477414466X',
      title: 'Ruby on Rails本格入門',
      price: 3100,
      publish: '技術評論社',
      published: '2014-02-14',
      cd: false
    })
    assert book.save, 'Failed to save'
  end
end

モデルクラスのテストは、/test/modulesに配置する
コマンドは下記の通り

rake test:models

ビューヘルパのテストは、/test/helpersに配置する
コマンドは下記の通り

rake test:helpers

テストの準備、後始末はsetupメソッド、teardownメソッドで定義すると便利

Functionalテスト

コントローラの動作やテンプレートの出力をチェックするためのテスト
HTTPリクエストを擬似的に作成して、アクションメソッドを実行し、その結果が期待通りかを確認する

  • HTTPステータス
  • テンプレート変数
  • 最終的な出力結果
  • ルート定義の妥当性

実装例は以下の通り

require 'test_helper'

class HelloControllerTest < ActiveController::TestCase
  test "list action" do
    get :list
    assert_equal 10, assigns(:books).length, 'foud rows is wrong.'
    assert_response :success, 'list action failed.'
    assert_template 'hello/list'
  end
end

コントローラのテストは、/test/controllersに配置する
コマンドは下記の通り

rake test:controllers

Integrationテスト

複数のコントローラに跨って、ユーザの実際の操作を追跡するような用途で使う
Integrationテストは、rails generateコマンドで生成する

rails generate integration_test admin_login

実行用のコマンドは下記の通り

rake test:integration

9.クライアントサイド開発

JavaScript/スタイルシートのインポート

Rails4では、アセットを読み込むためにSprocketsというライブラリを利用する
Sprocketsでは、あらかじめ用意されたリスト(マニフェスト)を元に、アセットを読み込む
デフォルトで用意しているマニフェストは以下の通り

  • application.js
  • application.css

Railsでは、クライアントサイド開発の言語としてCoffeeScript/SCSSを標準サポートしている

Asset Pipeline

Sprocketsライブラリによって提供される仕組み
JavaScript、スタイルシート、画像などのアセットをまとめて管理し、効率的に返す機能を提供する
CoffeeScript/SCSSのコードは実行するためにコンパイルが必要だが、Asset Pipelineはそれを自動化してくれる

Ajax開発

Railsでは、link_to、form_tagなどのビューヘルパがAjax通信のための機能を提供している
link_toメソッドをAjax対応させるには、remoteオプションをtrueにする

<%= link_to '更新', { action: :upanel }, remote: true %>

Ajax呼び出しでは、テンプレートとして、(.html.erbではなく).js.erbが呼び出される
form_tag、form_forを利用した場合もほぼ同じような実装で対処できる

<%= form_tag({ action: 'result' }, remote: true) do %>
  <%= select_tag(:publish,
                 options_from_collection_for_select(@books, :publish, :publish, '技術評論社')) %>
  <%= submit_tag '検索' %>
<% end %>

Turbolinks

ページ遷移に関して、(ページ全体ではなく)タイトルと本文だけを置き換える仕組み
Turbolinksを利用することで、ページ全体を更新する手間が省け、特にJavaScriptやスタイルシートの再取得/解析が不要になるため、ページ移動時のオーバヘッドを軽減できる

10.Railsの高度な機能

電子メールを送信する - ActionMailer

Railsでは、メール送信のための標準モジュールとしてActionMailerが提供されている
ActionMailerを使うことで、標準的なテキストメール、HTMLメール、添付ファイルつきメールまでを作成できる

メール送信の基本

rails generateコマンドでメーラーを生成する

rails generate mailer NoticeMailer sendmail_confirm

生成されたメーラークラスに対して、具体的なメール送信のためのコードを書いていく
defaultメソッドでヘッダ情報を設定し、mailメソッドでメールを生成する

class NoticeMailer < ActionMailer::Base
  .. 中略 ..
  default from: 'webmaster@wings.msn.to',
          cc: 'CQW15204@nifty.com'
          
  def sendmail_confirm(user)
    @user = user
    mail(to: user.email,
         subject: 'ユーザ登録ありがとうございました')
  end
end

メール本文を「.text.erb」ファイルにデザインする

<%= @user.username %>さま
この度は、本サイトへユーザ登録をいただきましてありがとうございました。
...
サイトをご利用いただくには、以下のページからログインをおこなってください。
<%= url_for(host: 'www.example.com', controller: :books, action: :index) %>

メーラーを呼び出すためのアクションを作成する

def sendmail
  user = User.find(6)
  @mail = NoticeMailer.sendmail_confirm(user).deliver
  render text: 'メールが正しく送信できました。'
end

メール送信前に任意の処理を実行したい場合は、インターセプタ機能を利用すると良い
インターセプタであることの条件は、delivering_emailメソッドを実装していること

class TestMailtoInterceptor
  def self.delivering_email(mail)
    mail.to = [ 'tester@wings.msn.to' ]
  end
end

キャッシュ機能の実装

Railsでは、フラグメントキャッシュという機能を提供している
フラグメントキャッシュとは、ページの断片をキャッシュするための仕組み

  • ページの中にキャッシュしたい領域と、キャッシュできない領域が混在していても、適切なキャッシュポリシーを設定できる
  • 階層的なページ構造でも、効率よくキャッシュを管理できる

フラグメントキャッシュを利用するには、cacheでキャッシュしたい領域を囲む

<% cache([key]) do %>
  content
<% end %>

キャッシュデータは/tmp/cacheフォルダ配下に保存される

アプリケーションの国際化対応 - I18n API

Railsでは、標準的な国際化対応の仕組みとして、I18n(Internationalization) APIを提供している
I18nを利用することで、ブラウザの言語設定に応じて、地域固有のテキストを動的に差し替え可能になる

国際化対応の手順

辞書ファイルを/config/localesフォルダ配下に「言語名.yml」の形式で保存する

ja:
  general:
    greeting:
      morning: 'おはようございます。'
      hello: 'こんにちは、%{name}さん!'

application.rbで、i18n.default_localeパラメータを編集する

module Railbook
  class Application < Rails::Application
    .. 中略..
    config.i18n.default.locale = :ja
    .. 中略..
  end
end

テンプレートファイルにて、ビューヘルパ「t」を使って辞書ファイルの内容を呼び出す

<%= t 'general.greeting.morning' %><br />
<%= t 'general.greeting.hello', name: 'yyamada' %>

ApplicationControllerクラスで、ロケールを動的に設定することもできる
テンプレートそのものをローカル対応することもできる

Rails標準の翻訳情報を追加する

Railsでは、ActionModelによる検証メッセージをはじめ、数値や日付/時刻関係のビューヘルパなどが国際化対応しており、辞書ファイルを設定するだけで日本語化できる
すでに有志が翻訳済みのリソースがあるので、そちらを活用するのが良さそう

https://github.com/svenfuchs/rails-i18n
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment