【Ruby on Rails】コントローラの基本:アクションとストロングパラメータ

Ruby

こんにちは、かつコーチです。

「フォームを送信したのに、エラーが出て保存できない」。
Rails初心者がコントローラを書き始めたときによく経験するつまずきです。
この記事では、コントローラの作り方・アクションの書き方に加えて、初心者がつまずきやすいストロングパラメータの仕組みを解説します。
読み終える頃には、安全にデータを受け取るコントローラを書けるようになります。

コントローラの生成

rails generate controllerコマンド

コントローラは、rails generateコマンド(省略形rails g)を使って生成できます。

bin/rails g controller Posts

このコマンドを実行すると、app/controllers/posts_controller.rbが自動的に作成されます。
コントローラ名は複数形で指定するのが規約です。
前々回の記事で紹介した「設定より規約(CoC)」がここでも活きています。

生成される基本の形

生成直後のコントローラは、次のような空のクラスです。

# app/controllers/posts_controller.rb
class PostsController < ApplicationController
end

ApplicationControllerを継承することで、Railsが用意している便利な機能を使えるようになります。
この中に、これから紹介するアクションを追加していきます。

アクションの書き方

基本の7つのアクション

前回の記事で紹介したresources :postsは、次の7つのアクションを想定して作られています。

アクション役割
index一覧を表示する
show詳細を表示する
new新規作成画面を表示する
createデータを新規作成する
edit編集画面を表示する
updateデータを更新する
destroyデータを削除する

これらのアクションは、コントローラ内でメソッドとして定義します。

class PostsController < ApplicationController
  def index
    @posts = Post.all
  end

  def show
    @post = Post.find(params[:id])
  end
end

params[:id]は、URLに含まれるIDの値を取得するための書き方です。
たとえば/posts/3にアクセスすると、params[:id]には"3"という値が入ります。

createアクションでデータを保存する

フォームから送信されたデータを保存するには、createアクションを使います。

def create
  @post = Post.new(post_params)

  if @post.save
    redirect_to @post, notice: "投稿を作成しました"
  else
    render :new, status: :unprocessable_entity
  end
end

saveが成功すれば詳細ページへ、失敗すれば新規作成画面を再表示するという分岐です。
post_paramsというメソッドがここで登場していますが、これが次に説明するストロングパラメータです。

ストロングパラメータとparams.require

なぜストロングパラメータが必要なのか

フォームから送られてくるデータは、paramsという形でコントローラに渡ってきます。
しかし、paramsをそのままモデルに渡してしまうと、想定していない項目まで一括で保存されてしまう危険があります。

たとえば「管理者権限フラグ」のような項目があった場合、悪意のあるリクエストによって不正に書き換えられてしまう可能性があるのです。
この問題を防ぐための仕組みがストロングパラメータです。
受け取ってよい項目を明示的に指定し、それ以外は受け付けないようにする安全対策です。

params.requireとpermitの書き方

ストロングパラメータは、requirepermitという2つのメソッドを組み合わせて書きます。

private

def post_params
  params.require(:post).permit(:title, :body)
end

params.require(:post)は「postというキーの中身を必須とする」という意味です。
.permit(:title, :body)は「titlebodyという項目だけを受け取ってよい」という意味です。

このメソッドをprivate(外部から呼び出せない領域)に定義し、createupdateアクションの中から呼び出すのが一般的な書き方です。

つまずきやすい設定・注意点

permitに項目を入れ忘れるとデータが保存されない

permitに指定していない項目は、フォームで入力しても保存時に無視されます。
新しいカラムを追加したのに保存されない、という場合はpermitの指定漏れを疑いましょう。

フォームのname属性とpermitの対応

フォームのinputタグのname属性がpost[title]のような形になっている場合、Railsはこれをparams[:post][:title]として受け取ります。
require(:post):postは、このフォームの構造と対応させる必要があります。

よくあるつまずきポイント・エラー対処

Before/After:permitを書かずに保存しようとするケース

ストロングパラメータの仕組みを知らずに、paramsをそのままモデルに渡してしまうのは典型的な失敗パターンです。
私が初めてcreateアクションを書いたとき、permitを書かずにparams[:post]をそのまま渡してしまい、次のエラーに遭遇しました。

❌Before:paramsを直接モデルに渡してしまう

def create
  @post = Post.new(params[:post])  # ストロングパラメータを使っていない
  @post.save
end

このコードを実行すると、次のようなエラーが表示されます。

ActionController::ForbiddenAttributesError

これは「許可されていないパラメータを、そのままモデルに渡そうとしている」というエラーです。
Rails 4以降、セキュリティ対策としてこの仕組みが標準で組み込まれており、permitを通さないデータは受け付けない設計になっています。

✅After:requireとpermitで明示的に許可する

def create
  @post = Post.new(post_params)
  @post.save
end

private

def post_params
  params.require(:post).permit(:title, :body)
end

このようにpost_paramsメソッドを経由させることで、titlebodyだけが安全に渡されるようになります。
エラーメッセージにForbiddenAttributesErrorと表示されたら、まずストロングパラメータの書き忘れを疑うとよいでしょう。

まとめ

この記事のポイント

  • コントローラはrails g controllerコマンドで生成し、app/controllersに配置する
  • indexshowcreateなど、目的ごとにアクションをメソッドとして定義する
  • ストロングパラメータはparams.require(:モデル名).permit(:項目名, ...)という形で書く
  • permitを書き忘れるとForbiddenAttributesErrorが発生し、データを保存できない

次に読むべき記事

コントローラの基本が身についたら、次はユーザーに見せる画面の作り方を学びましょう。
「ビュー(ERB)の基本とレイアウト」で、画面表示の仕組みを確認してみてください。

タグ: Ruby on Rails, 初心者向け, フレームワーク基礎

タイトルとURLをコピーしました