LoginSignup
23
10

More than 3 years have passed since last update.

paramsとwrap_parameters

Last updated at Posted at 2020-02-24

JSONでデータを送るとき、コントローラ名と送信するパラメータのキー名(name属性のプレフィクス)の関係についての話です。

UsersControllerというコントローラがあるとします。このコントローラに対して、Ajaxを使いJSON形式かつPOSTメソッド(またはPUT、PATCH)でデータを送ります。パラメータには"user"のようなキーを付けません。

Axios.post('/users.json', { name: 'Taro', email: 'taro@example.com' });

すると、コントローラのparamsには、"user"というキーが自動的に付きます(値がラップされます)。これが、ActionController::ParamsWrapperの機能です。

{"name"=>"Taro", "email"=>"taro@example.com", "user"=>{"name"=>"Taro", "email"=>"taro@example.com"}}

次のようにストロングパラメータを使っていても大丈夫、というわけです。

def user_params
  params.require(:user).permit(:name, :email)
end

しかし、コントローラ名とは違うキー名を使いたい場合があります。次の例では"member"です。

Axios.post('/users.json', { member: { name: 'Taro', email: 'taro@example.com' }});

すると、コントローラのparamsには、"user"というキーが付き、中は空となります。

{"member"=>{"name"=>"Taro", "email"=>"taro@example.com"}, "user"=>{}}

これが気になるときは、wrap_parametersメソッドでキー名を指定します。このコントローラでラッピングに使われるキー名が"member"になります。

class UsersController < ApplicationController
  wrap_parameters :member

あるいは、次のようにすると、JSON形式ではラップしなくなります。

class UsersController < ApplicationController
  wrap_parameters format: []

コントローラすべてに適用するには、initializers下の設定ファイルで指定します。配列[:json]を空にします。

config/initializers/wrap_parameters.rb
ActiveSupport.on_load(:action_controller) do
  wrap_parameters format: []
end

実際のプロジェクトでは

一番上のサンプル(キーを付けない場合)では、値が配列やハッシュの場合はラップしてくれません。ActionController::ParamsWrapperの設定をデフォルトにしたままだと混乱を招きそうです。

新規プロジェクトではinitializers下の設定でJSONを外しておくのがいいと思います。既存のプロジェクトでは、デフォルトでオフにするのはちょっとこわいので、コントローラごとに指定しておくことにします。

そのうえで、「AjaxでPOST、PATCHするときは、パラメータにキーを付けて値をラッピングして、ストロングパラメータを使うこと」というガイドラインを作っておくとよいかと。

補足

この機能いつからあったっけと調べたら、だいぶ昔で、2011年のRails 3.1からでした

23
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
10