こんにちは、鈴木です。
Rails4 の新機能である Strong Parameters を試してみました。
※2013/10/03 TECHSCORE 本体の記事になりました!「StrongParameters | TECHSCORE(テックスコア)」
Strong Parameters は個別の Gem ライブラリでしたが、Rails4 のコア機能として取り込まれました。
Strong Parameters を使用すると、ホワイトリスト形式でリクエストパラメータを検証することができます。
Rails3 では Mass-assignment (モデルの複数属性への一括代入)を防ぐために attr_accessible を使用していましたが、Rails4 からは Strong Parameters を用いて Mass-assignment に対応することができます。
Strong Parameters を試す
Rails4 beta のプロジェクトを作成する方法は「Hello Rails4 beta」をご参照ください。
ここではプロジェクトは作成済みとして話を進めます。
scaffold でコード生成
まずは scaffold で User モデルと関連ファイル一式を作成します。
1 |
rails generate scaffold user name:string email:string |
実は scaffold を使用すると、Strong Parameters の機能を使用したコードが生成されます。
コントローラ (app/controllers/users_controller.rb) を開くと、以下のようになっています(Strong Parameters に関係する部分以外は省略しています)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
class UsersController < ApplicationController ... # POST /users # POST /users.json def create @user = User.new(user_params) ... end ... private ... # Never trust parameters from the scary internet, only allow the white list through. def user_params params.require(:user).permit(:name, :email) end end |
user_params という private メソッドの中に注目してください。
「params.require(:user).permit(:name, :email)」となっています。
このコードは「params が :user というキーを持ち、params[:user] は :name 及び :email というキーを持つハッシュであること」を検証します。
例えば、params[:user] が {:name => 'taro', :email => '[email protected]'} のようなハッシュである場合に検証 OK となります。
マイグレーション及びサーバ起動
次にマイグレーションを実行します。
1 |
rake db:migrate |
あとでブラウザからアクセスして動作確認するので、サーバを起動しておきます。
1 |
rails server |
ブラウザで動作確認
それでは「http://localhost:3000/users」にアクセスしましょう。
ユーザ一覧画面ですが、まだデータが登録されていないので一覧には何も表示されません。
ユーザ登録画面に移動し、適当な値を入力して、登録してみましょう。
処理に成功しました。
それでは、コントローラのコードを修正し、今までのように(Rails3 時代のように)params[:user] をそのまま返すように修正してみます。
1 2 3 4 5 6 |
# Never trust parameters from the scary internet, only allow the white list through. def user_params # 試に変更する. # params.require(:user).permit(:name, :email) params[:user] end |
もう一度、ユーザ登録してみましょう。
今度はエラーとなりました。Rails3 の頃と比較してエラー画面が綺麗になりましたね。
これが Strong Parameters の動作です。
許可するパラメータをホワイトリスト形式で準備しておき、それを基に検証を行います。
検証エラーの場合は例外 ActiveModel::ForbiddenAttributesError が raise されます。
許可していないパラメータの扱い
許可していないパラメータが渡された場合はどうなるのでしょうか。
デフォルトでは無視される
試に user_params の内容を以下のように修正してみます。
1 2 3 4 5 6 |
# Never trust parameters from the scary internet, only allow the white list through. def user_params # 試に :email の指定を消す. # params.require(:user).permit(:name, :email) params.require(:user).permit(:name) end |
この状態で再度ユーザ登録を行うと、リクエストパラメータとして名前(name)とメールアドレス(email)が渡されますが、メールアドレス(email)は無視されます。
ログを確認すると以下のようなメッセージが出力されていました。
1 |
Unpermitted parameters: email |
許可しないパラメータが渡された場合に例外を発生させる
許可しないパラメータが渡された場合の動作は config/application.rb で変更することができます。
試に例外を発生させるように変更してみます。
1 2 |
# デフォルトは :log で, 許可されていないパラメータは無視されたうえでログ出力されます. config.action_controller.action_on_unpermitted_parameters = :raise |
この状態で再びユーザ登録を行うと(リクエストパラメータに name と email が渡されると)、ActionController::UnpermittedParameters という例外が raise されました。
ネストしたパラメータ
Strong Parameters のドキュメントを読むと、permit メソッドの引数を以下のように指定することで、ネストしたパラメータに対応することができるようです。
1 2 3 4 |
params.permit(:name, {:emails => []}, :friends => [:name, {:family => [:name]}]) |
まとめ
Rails3 の attr_accessible は、画面ごとに受け付けるパラメータが異なる場合にモデルのコードが膨れ上がってしまうという問題がありました。
Rails4 でコア機能として取り込まれた Strong Parameters を用いると、そのあたりのコードがスッキリすることが分かりました。
Trackbacks
[...] Rails4 の Strong Parameters でリクエストパラメータを検証する [...]