indexアクションが完成したら、次はコンソールではなくブラウザーでデータを登録できるようにしましょう。
ここでは冒頭で紹介した7つのアクションのうち、フォームを表示するための「new」と、フォームから投稿されたデータを登録する「create」を用意します。
ただし、ビューを用意するのはnewアクションだけです。createアクションは実行後、データの登録が成功したらindexアクションにリダイレクトし、失敗したらnewアクションのビューを再レンダリングするようにします。
以下にnewアクションのビューを示します。
<h1>新規利用者</h1> <%= form_for(@user) do |f| %> <div class="field"> <%= f.label :name %><br> <%= f.text_field :name %> </div> <div class="field"> <%= f.label :department %><br> <%= f.text_field :department %> </div> <div class="actions"> <%= f.submit %> </div> <% end %> <%= link_to 'Back', users_path %>
「form_for」メソッドは引数に取ったモデルオブジェクトのための<form>タグを生成します。このメソッドはモデルオブジェクトが未保存のデータであれば、createアクションに向けた宛先の情報を生成し、保存済みのデータであればその更新のためのアクションに向けた宛先の情報を生成してくれます。
さらにform_forはブロックを取り、そのブロック変数(ここでは「f」)は第1引数に渡したオブジェクトの属性への<input>タグを生成するメソッドを呼び出せます。
次に、コントローラーでアクションのメソッドを定義します。
class UsersController < ApplicationController def index @users = User.all end def new @user = User.new end def create @user = User.new(user_params) if @user.save redirect_to users_url else render 'new' end end private def user_params params.require(:user).permit(:name, :department) end end
コントローラーのnewメソッドではインスタンス変数@userに引数なしで初期化したUserオブジェクトを代入しておきます。これはビューのform_forメソッドの引数となります。
コントローラーのcreateメソッドはやや複雑ですが、モデルの各メソッドは「『rails console』コマンドで各コンポーネントの連携を切り離して機能を確認」節で説明したものと同じものです。
ここで注目すべきものはUserモデルのnewメソッドに返り値を渡している「user_params」メソッド(上記コード21行目)です。
form_forからモデルに基づくデータがパラメーターに与えられたとき、例えば「params[:user]」というオブジェクトがパラメーターをハッシュとして保持しています。
しかし、このままだと「mass assignment脆弱性」といって、悪意のユーザーによるパラメーターの改ざんによる攻撃を受ける危険性があります。
それを防止するために、Rails 3まではモデル属性へ一括代入する要素はモデル内で宣言するようになっていましたが、柔軟性がなく扱いづらいものでした。しかし、Rails 4からはコントローラでフィルタリングして許可したキーの「ハッシュ」だけを返す「Strong Parameters」という仕組みがコントローラーに導入されました。
具体的には、フォームから投稿されたデータはリクエストパラメーターの"user"キーの値としてハッシュになっています。「params.require(:user)」は、そのハッシュを参照しており、そのハッシュに含まれていて良いキーだけを「permit」メソッドの引数として、指定した要素だけを持つハッシュを取り出します。
そしてsaveメソッドを呼び出してデータベースに保存します。ただし、保存前に値が適切かどうかのバリデーションチェックが行われますので、不適切な値が含まれているとsaveメソッドの返り値はfalseとなり、未保存のデータを@userに格納したままnewアクションのビューをレンダリングします。つまり、ユーザーに入力をやり直すよう促せます。
作成したアクションに対するルーティングを準備しましょう。「config/routes.rb」の「:user」を引数に取る「resources」メソッドのonlyオプションにnewとcreateを追加します。
resources :users, only: %i(index new create)
このようにして「rake routes」コマンドを実行すると新しく以下のルーティングが追加されています。
POST /users(.:format) users#create new_user GET /users/new(.:format) users#new
これに従い、「http://localhost:3000/users/new」にアクセスすると、新規ユーザー登録のためのフォームを含むページが表示されています。そのフォームを埋め、投稿ボタンを押すと、createアクションにPOSTリクエストし、ユーザーが登録されます。
今回からscaffoldの機能を自分たちの手で作り始めました。長くなりましたので、残念ながら今回は特定のレコードを指定しないアクションの実装までとします。
次回はscaffoldのshow、edit、update、destroyといった特定のレコードを指定する機能のアクションを実装します。
林 慶(Rails技術者認定シルバー試験問題作成者)
平成2年大阪生まれ。2006年から高専で情報工学を学んでいたが当時は所謂プログラミングができない工学生だった。卒業後、高専の専攻科に上がったもののマンネリ化したキャンパスライフに飽きたため休学して渡豪。そこでプログラミングに対するコンプレックスを克服するためにRuby on Railsなどでアプリケーションを作ることを覚える。
帰国後から現在までは復学し推薦システムに関する研究を行いながら、アジャイルウェアでRuby on Railsアプリケーションの開発業務に従事している。
好きなメソッドはinject。
山根 剛司(Ruby業務開発歴7年)
兵庫県生まれ。1997年からベンチャー系のパッケージベンダーで10年間勤務。当時、使用していた言語はJavaとサーバーサイドJavaScript。
2007年よりITコンサル会社に転職し、Rubyと出会って衝撃を受ける。基幹システムをRuby on Railsで置き換えるプロジェクトに従事。それ以来Ruby一筋で、Ruby on Railsのプラグインやgemも開発。
2013年より、株式会社アジャイルウェアに所属。アジャイルな手法で、Ruby on Railsを使って企業向けシステムを構築する業務に従事。
Ruby関西所属。好きなメソッドはtap。
Twitter:@spring_kuma、Facebook:山根 剛司
Copyright © ITmedia, Inc. All Rights Reserved.