7. StrongParameters
2013/10/03 シナジーマーケティング(株) 鈴木 圭
[Rails 4.0] 第7章 StrongParameters
- 7.1. StrongParameters とは
- 7.2. require と permit
- 7.3. permit に関する設定
- 7.4. 配列やネストしたパラメータの扱い
- 7.5. コントローラ以外で StrongParameters を使う方法
- 7.6. まとめ
7.1. StrongParameters とは
StrongParameters はモデルへの Mass-assignment (一括代入)をコントローラ層で制御するために、リクエストから受け取るパラメータをホワイトリスト形式で指定する機能を提供します。これは、Rails3 で多用されてきた attr_accessible/attr_protected の代替となるものです。
StrongParameters を使うにあたり重要となるのは、
- StrongParameters はコントローラで使用するもの。
- attr_accessible/attr_protected はモデルで使用するもの。
- どちらも Mass-assignment による意図しない値の書き換えを防ぐもの。
ということであり、
- Mass-assignment を許可する属性とはつまり画面の入力項目である(ことが多い)。
- MVC (Model-View-Controller) における Model は画面の入力項目が何であるかを知らない。
- つまり Mass-assignment の制御はモデルではなくコントローラで行うことが適切である。
ということです。
これが今まで使用してきた attr_accessible/attr_protected から StrongParameters に変更することの理由です。
7.2. require と permit
それでは StrongParameters を使ってみましょう。
例として記事 (Article) を登録する画面を作成しているとします。
Rails3 であればコントローラ(ArticlesController)の実装は以下のようになると思います。
class ArticlesController < ApplicationController def create @article = Article.new(params[:article]) ... end end
これを StrongParameters を使うように書き換えると次のようになります。
class ArticlesController < ApplicationController def create @article = Article.new(params.require(:article).permit(:user_id, :title, :body)) ... end end
「params[:article]」の部分が「params.require(:article).permit(:user_id, :title, :body)」に変わりました。
StrongParameters では require と permit メソッドによって、受け取るリクエストパラメータの制御を行います。
require はハッシュに指定したキーが存在することを検証し、キーが存在すればその値を返します。つまり、「params.require(:user)」とした場合、:user がキーとして存在すれば「params[:user]」の値が返されます。そして、指定したキーが存在しない場合は例外 ActionController::ParameterMissing を raise します。
permit はハッシュから指定したキーだけを取り出します。指定しなかったキーがハッシュに含まれていても、戻り値にそれらの値は含まれません。
以上を整理すると、params が {user: {title: ‘タイトル’, body: ‘本文’, bad_key: ’xxx’}} とすると、
- params.require(:user) は {title: ‘タイトル’, body: ‘本文’, bad_key: ’xxx’}
- params.require(:user).permit(:title, :body) は {title: ‘タイトル’, body: ’本文’}
となります。
7.3. permit に関する設定
permit は許可するパラメータのみを取り出すためのメソッドですが、その動作は以下の設定で変更することができます。
- config.action_controller.permit_all_parameters
- true を指定するとデフォルトで全てのパラメータが許可されたものとして扱われるようになります(デフォルトは false)。既存アプリケーションを Rails4.0 にバージョンアップするようなときに一時的に true を指定することはあるかもしれませんが、通常はデフォルトの false から変更することは無いでしょう。 - config.action_controller.action_on_unpermitted_parameters
- 許可していないパラメータが存在する場合の動作を指定します。:log を指定するとログ出力されるのみですが、:raise を指定すると ActionController::UnpermittedParameters が raise されます。
7.4. 配列やネストしたパラメータの扱い
permit では配列やネストしたパラメータを扱うことができます。
配列を許可したい場合は、「permit(emails: [])」のように空の配列を指定します。
# 配列の場合. params.require(:user).permit(:name, emails: [])
こうすることで「{user: {name: ‘taro’, emails: [‘[email protected]’, ‘[email protected]’]}}」のような配列を含むパラメータを受け付けることができます。
ネストしたパラメータを許可したい場合は、次のように指定します。
# ネストしたパラメータの場合. params.require(:user).permit(:name, friend: [:name, :email])
この場合は「{user: {name: ‘taro’, friend: {name: ‘jiro’, email: ‘[email protected]’}}}」のようなネストした値を含むパラメータを受け付けることができます。
7.5. コントローラ以外で StrongParameters を使う方法
StrongParameters はコントローラとは独立して使用することもできます。
ActionController::Parameters というクラスがコントローラにおける params をラップしているクラスなので、これを直接使うことでコントローラ以外の場所でも StrongParameters を使うことができます。
raw_params = {user: {name: 'taro', email: '[email protected]'}} params = ActionController::Parameters.new(raw_params) params.require(:user).permit(:name, :email)
7.6. まとめ
StrongParameters は Mass-assignment に関する問題を正しい場所(=コントローラ)で解決するための機能です。「新機能だから使いましょう」という話ではなく、問題を正しい場所で解決するための新機能であることに価値があるのだと思います。
次回は ActionController::Live について解説します。