2013-04-28 22:55

アクションメソッドの実装

アクションメソッドとは?

Controllerが受け取ったクライアントからのリクエストの処理方法を具体的に定義しているのがアクションメソッドです。
アクションと呼んだりもします。

アクションはControllerクラスに記述します。
rails generate controllerをした直後であればこんな感じになっているハズです。
rails generate controllerに関してはこちら ⇒ Controllerクラスの生成

articlesコントローラを生成したとして、

app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
end

この2行の間にアクションを記述していきます。

7つの基本アクション

ここではまず7つある基本的なアクションについて記していきます。

indexアクション

原則的にリクエストの HTTPメソッドが「GET」 で、 URLが「/コントローラ名」のときに呼び出されます。
テーブルのレコード一覧を表示する。

app/controllers/articles_controller.rb
  def index
    @articles = Article.order("posted_at DESC")
  end

Viewに引き渡す変数@articlesを定義。

ここでは、app/models/articleに記述したArticleクラス(テーブル)を呼び出し、orderメソッドで属性posted_atが降順になるようにソートしています。

showアクション

原則的にリクエストの HTTPメソッドが「GET」 で、 URLが「/コントローラ名/:id」のときに呼び出されます。
個別のレコードの詳細表示画面を表示する。

app/controllers/articles_controller.rb
  def show
    @article = Article.find(params[:id])
  end

Viewに引き渡す変数@articleを定義。

Articleクラス(テーブル)からリクエストURLのパラメータ:idに該当するオブジェクト(レコード)を呼び出して変数に格納しています。

newアクション

原則的にリクエストの HTTPメソッドが「GET」 で、 URLが「/コントローラ名/new」のときに呼び出されます。
新規データの登録画面を表示する。

app/controllers/articles_controller.rb
  def new
    @article = Article.new(posted_at: Time.current)
  end

Viewに引き渡す変数@articleを定義。

Articleクラス(テーブル)に新しいオブジェクト(レコード)を作成して変数に格納しています。
この際、posted_atの初期値として現在日時を設定しています。

createアクション

原則的にリクエストの HTTPメソッドが「POST」 で、 URLが「/コントローラ名」のときに呼び出されます。
newアクションによって作られた新規データ登録画面の入力内容を受けて登録処理を行う。

app/controllers/articles_controller.rb
  def create
    @article = Article.new(params[:article])
    if @article.save
      redirect_to @article, notice: "記事を作成しました。"
    else
      render "new"
    end
  end

Modelに保存する新しいオブジェクト(レコード)としての変数@articleを定義。

Articleクラス(テーブル)に新しいオブジェクト(レコード)を作成して変数に格納しています。
このときに、リクエストで受け取ったパラメータ(newアクションによって作られた新規データ登録画面の入力内容)をオブジェクトの属性値としています。

if @article.save以降では、@articleをテーブルに保存してその結果に応じて保存後の処理を行っています。
保存が成功した場合にredirect_to @article, notice: "記事を作成しました。"を、失敗した場合にrender "new"です。

redirect_to @article, notice: "記事を作成しました。"では、保存した@articleを/app/views/articles/show.html.erbで表示しています。
また、オプションnoticeで無事登録が成功した旨のメッセージを表示させています。
ダブルクォーテーションで囲われた文章では日本語でも構いませんが、マジックコメントを書くなどしてUTF-8で保存できるようにしておきましょう。

render "new"では保存に失敗した場合にデータを再度編集できるように新規データ登録画面を表示しています。

editアクション

原則的にリクエストの HTTPメソッドが「GET」 で、 URLが「/コントローラ名/:id/edit」のときに呼び出されます。
既存データの編集画面を表示。

app/controllers/articles_controller.rb
  def edit
    @article = Article.find(params[:id])
  end

Viewに引き渡す変数@articleを定義。

Articleクラス(テーブル)からリクエストURLのパラメータ:idに該当するオブジェクト(レコード)を呼び出して変数に格納しています。
変数を受け取ったViewでは、既存データとしてフォームに変数の値を表示します。

updateアクション

原則的にリクエストの HTTPメソッドが「PUT」 で、 URLが「/コントローラ名」のときに呼び出されます。
editアクションによって編集された編集画面の入力内容を受けて登録処理を行う。

app/controllers/articles_controller.rb
  def update
    @article = Article.find(params[:id])
    @article.assign_attributes(params[:article])
    if @article.save
      redirect_to @article, notice: "記事を更新しました。"
    else
      render "edit"
    end
  end

内容の編集を行う既存のオブジェクト(レコード)としての変数@articleを定義。

Articleクラス(テーブル)からリクエストURLのパラメータ:idに該当するオブジェクト(レコード)を呼び出して変数に格納しています。
その後に変数@articleに対してassign_attributesメソッドを実行しています。
assign_attributesメソッドは引数で受け取った内容でオブジェクトの属性値を更新するメソッドです。
ここでは、editアクションで編集した内容をparams[:article]として受け取り、@articleに上書きしています。

if @article.save以降に関しては、createアクションと同じです。
保存に成功した場合は、/app/views/articles/show.html.erbにリダイレクトし、失敗した場合は再度編集できるように編集画面をレンダリングします。

destroyアクション

原則的にリクエストの HTTPメソッドが「DELETE」 で、 URLが「/コントローラ名/:id」のときに呼び出されます。
選択されたオブジェクト(レコード)を削除する。

app/controllers/articles_controller.rb
  def destroy
    @article = Article.find(params[:id])
    @article.destroy
    redirect_to :articles, notice: "記事を削除しました。"
  end

削除の対象となる既存のオブジェクト(レコード)として変数@articleを定義。

destroyメソッドでオブジェクトを削除した後、/app/views/articles/index.html.erbにリダイレクトしている。
その際に、オプションnoticeで削除が成功した旨のメッセージを表示させています。

全体像の確認

以上の7つのアクションを実装したarticles_controller.rbを記しておきましょう。

app/controllers/articles_controller.rb
# -*- coding: utf-8 -*-

class ArticlesController < ApplicationController
  def index
    @articles = Article.oreder("posted_at DESC")
  end

  def show
    @article = Article.find(params[:id])
  end

  def new
    @article = Article.new(posted_at: Time.current)
  end

  def edit
    @article = Article.find(params[:id])
  end

  def create
    @article = Article.new(params[:article])
    if @article.save
      redirect_to @article, notice: "記事を作成しました。"
    else
      render "new"
    end
  end

  def update
    @article = Article.find(params[:id])
    @article.assign_attributes(params[:article])
    if @article.save
      redirect_to @article, notice: "記事を更新しました。"
    else
      render "edit"
    end
  end

  def destroy
    @article = Article.find(params[:id])
    @article.destroy
    redirect_to :articles, notice: "記事を削除しました。"
  end
end

こんな感じかな。

noticeで日本語を使用しているので、最初の行にマジックコメント入れときました。

レイアウトの修正

noticeが機能するようにレイアウトを修正します。
レイアウトについては ⇒ アプリケーション共通のレイアウトを作成する

app/views/layouts/application.html.erbのheader部分とcontent部分の間に次のコードを加えます。

app/views/layouts/application.html.erb
  <div id="header">
<%= render "shared/header" %>
  </div>

<%# ここから追加==================== %>
<% if flash.notice %>
<p class="notice"><%= flash.notice %></p>
<% end %>
<%# ここまで追加==================== %>

  <div id="content">
<%= yield %>
  </div>

noticeがあればそれを表示するように指示しています。

これでOK。

ここで作成したControllerの他に、Model、Viewの作成とroute設定が済んでいればブラウザで確認できます。
Modelの作成がまだなら ⇒ Modelクラスの自動生成
Viewの作成がまだなら ⇒ アプリケーション共通のレイアウトを作成する