RESTful なインターフェースを備えた Web アプリケーション(その 3)

これでおしまいだと思った ? 残念さやかちゃんでした ! w

せっかくだからアプリケーションっぽくどんどん作り込みましょう。今度は新規登録フォームを作ります。その前に、自動生成されたテストコード用のファイルを修正しておきます。
sample/test/functional/customers_controller_test.rb

require 'test_helper'

class CustomersControllerTest < ActionController::TestCase
  test "should get index" do
    get :index
    assert_response :success
  end

  test "should get show" do
    get :show
    assert_response :success
  end

  test "should get new" do
    get :new
    assert_response :success
  end

  test "should get create" do
    post :create
    assert_response :success
  end

end

index と show に関する部分は既に出来上がっているはずですので new と create に関する部分を追加してください。もっとも今回はテストコードは書かないので、あまり気にしなくてもいいです(最悪修正しなくても大丈夫かも)。

View の修正と新規作成

既存の View も少し修正します。
sample/app/views/customers/index.html.erb

<h1>顧客一覧</h1>
<table border>
  <thead>
    <tr>
      <th>顧客 ID</th>
      <th>顧客名</th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    <% @customers.each { |c| %>
    <tr>
      <td><%= c.id %></td>
      <td><%= c.name %></td>
      <td><%= button_to '詳細', customer_path(c.id), :method => :get %></td>
    </tr>
    <% } %>
  </tbody>
</table>
<%= button_to '新規登録', new_customer_path, :method => :get %>

一番下に新規登録用のボタンを付けました。ここでも Url Helper をつかって /customers/new へのリンクを付けています。new アクションには GET メソッドでアクセスするのでしたね。

sample/app/views/customers/show.html.erb (再掲)

<h1>顧客詳細</h1>
<table border>
  <tr><th>顧客 ID</th><td><%= @customer.id %></td></tr>
  <tr><th>顧客名</th><td><%= @customer.name %></td></tr>
  <tr><th>連絡先</th><td><%= @customer.phone %></td></tr>
</table>
<p><%= link_to '一覧に戻る', customers_path %></p>

sample/app/assets/stylesheets/customers.css.scss

h1 {
  text-align : center;
  font-size : x-large
}

table { margin : 2em auto }

p, div { text-align : center }

ここまでできたら、新たに sample/app/views/customers 直下に new.html.erb と create.html.erb を作ります。

sample/app/views/customers/new.html.erb

<h1>新規登録</h1>
<%= form_for(@customer) { |f| %>
<table>
  <tr>
    <th>顧客名</th>
    <td><%= f.text_field :name, { :size => 20, :required => true } %></td>
  </tr>
  <tr>
    <th>連絡先</th>
    <td><%= f.text_field :phone, { :size => 20, :required => true } %></td>
  </tr>
</table>
<p><%= f.submit '登録' %></p>
<% } %>
<p><%= link_to '一覧に戻る', customers_path %></p>

Model に対応したフォームを作る Form Helper である form_for を使います。action の URL は Model オブジェクトの状態で自動で判断されるので省略できます。また、未入力の項目が残っている場合は送信ができないようにしています*1

sample/app/views/customers/create.html.erb

<p><%= @msg %></p>
<table border>
  <tr><th>顧客名</th><td><%= @customer.name %></td></tr>
  <tr><th>連絡先</th><td><%= @customer.phone %></td></tr>
</table>
<p><%= link_to '一覧に戻る', customers_path %></p>

@msg は後で Controller から送られてくるメッセージの表示用の変数です。メッセージと登録した内容の確認画面になっています。

Controller の修正

sample/app/controllers/customers_controller.rb

# coding: utf-8

class CustomersController < ApplicationController
  layout 'customers'

  def index
    @customers = Customer.all
  end

  def show
    @customer = Customer.find(params[:id])
  end

  def new
    @customer = Customer.new
  end

  def create
    @customer = Customer.create(params[:customer])

    if !@customer.new_record?
      @msg = '登録されました'
    else
      @msg = '登録に失敗しました'
    end
  end
end

新たに new アクションと create アクションの動作を定義します。マルチバイト文字も含まれているので先頭のマジックコメントを忘れずに。

create アクションの Customer.create メソッドに対して渡している引数に注目してください。params で引き渡されたパラメータを受け取れるのですが、params[:customer] と書くことで、Model に紐づいているフォームの入力内容をまとめて受け取ることができます。create メソッドは引数を受け取って新しい Model オブジェクトを作り、データベースに格納します。登録に成功したかどうかを new_record? メソッドの返り値で判断させています(登録に成功すると new_record? は false を返す)。さてどんな出来になるのかな ? それはまた後程。

*1:Validation のチェックはしないのか、というツッコミが来そうですが、それは複雑になるので今回はパスということでw