SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

サンプルコードで学ぶRuby on Rails 5実践入門

scaffoldで生成されたコードから紐解くRails 5の基本構成

サンプルコードで学ぶRuby on Rails 5実践入門 第3回

  • X ポスト
  • このエントリーをはてなブックマークに追加

scaffoldを利用したRailsアプリケーションの基本動作確認(続き)(2)

Userモデルのデータベースへの作成(createアクション)

 Userモデルインスタンス生成(edit)画面から実際にusersテーブルへレコードを作成します。先ほどアクセスした画面でまずはform_forヘルパーで実際に生成されたformタグの中身をhtmlで覗いてみましょう。

 ブラウザの検証ツールを用いてフォームタグを確認できます。以下の例ではブラウザにGoogle Chromeを用いています。nameのテキストフィールド付近で右クリックし、検証を選択すると検証ツールでフォームタグを確認できます。その様子が図3です。

図3 ブラウザの検証ツールでフォームタグを確認
図3 ブラウザの検証ツールでフォームタグを確認

 フォームタグの通り、ここでCreate Userボタンをクリックしてsubmitすると、POSTメソッドで/usersパスにアクセスすることが分かります。前回で参照したルーティングを確認すると、POSTメソッド、/usersに該当するアクションはcreateであることが分かります。

 コントローラーのcreateメソッドを確認します。

リスト6 app/controllers/users_controller.rb
class UsersController < ApplicationController
…(中略)…
  def create
    @user = User.new(user_params)

    respond_to do |format|
      if @user.save
        format.html { redirect_to @user, notice: 'User was successfully created.' }
        format.json { render :show, status: :created, location: @user }
      else
        format.html { render :new }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end
…(中略)…
  private
…(中略)…
    def user_params
      params.require(:user).permit(:name, :email)
    end
end

 createメソッドではまず、user_paramsというprivateメソッドを引数にしてUserモデルインスタンスをnewしています。Railsではフォームから送信されるデータはparamsという変数に格納されます。user_paramsメソッドではフォームからPOST送信されたデータが格納されているparams変数のうち、更新が許可された値であるname、emailのみを取得しています。具体的にはparams[:user][:name]、params[:user][:email]をPOST送信されたデータとして受け付けるソースコードとなります。これをparams.require(:user).permit(:name, :email)のように表現できるようになっています。これらの仕組みは、Strong Parametersといわれ、Rails 4より導入された機能です。

 respond_toはRailsが提供するメソッドで、クライアントからのリクエストに応じてサーバーから返却するフォーマットによってレスポンスを定義します。respond_toのブロック内でformatタイプによって処理を分けることができます。scaffoldで自動生成したコードでは、リクエストがhtmlとjsonの場合でそれぞれレスポンスを定義しています。今回のようにhtmlフォームからアクセスした場合はクライアントからのリクエストがhtmlなので、form.htmlの行が実行されます。respond_toの後の行では、if文で@userインスタンス変数をsaveした実行結果によって処理を分岐しています。ActiveRecordが提供するsaveメソッドは成功すればtrue、失敗すればfalseを返却します。つまりsaveが成功した場合は上の行、失敗した場合は下の行が実行されます。

図4 createメソッドの動作定義
図4 createメソッドの動作定義

 特にデータベースまわりの問題が発生しなければ、Create Userボタンをクリックするとsaveメソッドが成功するはずです。成功した場合はredirect_toによって生成した@userを表示する画面に遷移します。

[解説]createメソッドは対応するビューを持たない

 createメソッドはPOSTでアクセスされた後、リダイレクトまたは直接別のメソッドに対応するビューファイルがrenderされます。例えば、saveメソッドが失敗した場合はrender :editとなっています。これはeditメソッドに対応するビューファイルであるapp/views/edit.html.erbを呼び出しています。

 つまりcreateメソッドは対応するビューを持ちません。実際にls app/views/users/とすると分かりますがcreate.html.erbは存在しません。

$ ls app/views/users/

 ↓

_form.html.erb       edit.html.erb   index.json.jbuilder  show.html.erb
_user.json.jbuilder  index.html.erb  new.html.erb         show.json.jbuilder

既存のUserモデルの表示(showアクション)

 それでは実際にname、emailをテキストフィールドに入力してCreate Userボタンをクリックしてみましょう。ここではnameに「rails5_sample_user」、emailに「rails5_sample_user@test.com」と入力しました。Create Userボタンをクリックした後に表示される画面は以下の通りです。

図5 http://localhost:3000/users/1
図5 http://localhost:3000/users/1

 アクセスされたURLに注目してみてください。このURLはルーティングを確認するとGETアクセスでURIが/users/:idの形式なので対応するアクションはshowアクションとなります。:idの部分がURLによると1となっているので、createメソッドのredirect_to @userの前の行でsaveメソッドが呼ばれます。その結果、usersテーブルにid=1のレコードがinsertされ、その後にusers.id=1のレコード内容を表示するshowメソッドにリダイレクトする、という動作になっています。

 showメソッドの中身を見てみましょう。

リスト7 app/controllers/users_controller.rb
class UsersController < ApplicationController
  before_action :set_user, only: [:show, :edit, :update, :destroy]
…(中略)…
  def show
  end
…(中略)…
  private
    # Use callbacks to share common setup or constraints between actions.
    def set_user
      @user = User.find(params[:id])
    end
…(中略)…

 showメソッドには何も処理が書いてありません。しかし実際にはusers.id=1のレコードの情報が表示されていますので何もしていないわけではありません。ソースコードをよく見てみると、2行目にbefore_actionという定義にshowがシンボルで記述されていることに気が付いたでしょうか。このように、before_actionによって指定したアクションメソッドがコールされる前に、特定の前処理をはさむことができます。このソースコードでは、show、edit、update、destroyメソッドが呼び出される前に、set_userメソッドが呼び出されます。set_userメソッドはprivateメソッドとしてコントローラー下部に記述されています。set_userメソッドでは、@userインスタンス変数にUserモデルをクライアントから送信されたparams[:id]変数でfindしています。このshowメソッドのケースでは、params[:id]=1ですので、User.find(1)の結果が@userインスタンス変数に代入されます。このようにActiveRecordのfindメソッドは引数のIDに一致するレコードをデータベースから取得します。

 showアクションに対応するビューファイルを見てみましょう。

リスト8 app/views/users/show.html.erb
…(中略)…
<p>
  <strong>Name:</strong>
  <%= @user.name %>
</p>

<p>
  <strong>Email:</strong>
  <%= @user.email %>
</p>
…(中略)…

 ビューファイルの通り、@user.nameと@user.emailを画面に表示しています。createメソッドからリダイレクトされたshowメソッドで、直前にsaveされたUserモデルのレコードのnameとemailが表示されることの理由が明らかになりました。

 なお、Backリンクをクリックすると、Usersリソース一覧(indexアクション)へ遷移します。以下の通り、追加されたusers.id=1のデータが表示されているでしょう。

図6 http://localhost:3000/users
図6 http://localhost:3000/users

既存のUserモデルの削除(destroyアクション)

 一覧画面のDestroyリンクをクリックすると「Are you sure?」という確認ダイアログが出ます。OKをクリックするとレコードが削除されたメッセージとともに一覧画面が表示されます。既にレコードは削除されているので一覧画面にはUserモデルのレコードが消えていることが分かります。

図7 http://localhost:3000/users
図7 http://localhost:3000/users
リスト9 app/controllers/users_controller.rb
class UsersController < ApplicationController
…(中略)…
  def destroy
    @user.destroy
    respond_to do |format|
      format.html { redirect_to users_url, notice: 'User was successfully destroyed.' }
      format.json { head :no_content }
    end
  end
…(中略)…

 @user.destroyのdestroyメソッドはActiveRecordが提供するメソッドです。データベース上ではレコードを物理削除するdelete文が発行されます。レコード削除後、一覧画面のURLにリダイレクトしていることが読み取れます。

その他のアクション

 既存のUserモデルの編集はeditアクション、更新はupdateアクションです。説明は割愛しますが、同様に対応するweb上での操作とソースコードを確認してみてください。editはshow同等、updateはcreate同等のコードであることが見て取れるでしょう。

まとめ

 今回は、scaffoldで自動生成したソースコードと実際の動作を関連付けて各アクションについて解説しました。

 次回はscaffoldで自動生成したユーザー登録機能をより実践的に拡張していきます。

参考文献

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
サンプルコードで学ぶRuby on Rails 5実践入門連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 竹馬 力(チクバ ツトム)

WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/9914 2017/01/16 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング