hello-world.jp.net
webエンジニアのメモ。とりあえずやってみる。

[rails]Strong Parametersでhashを許可する場合のやり方

公開日時

Rails4.1.7, Ruby2.1.4 で確認。

Rails4より導入されたMass Assignment脆弱性を防ぐための仕組みがStrong Parametersです。

def create
  @user = User.new(permitted_params)
end

private

def permitted_params
  params.permit(:name, :email)
end

こんな感じでコントローラで許可したパラメータのみをmodelに渡すことができます。

なお、許可されていないパラメータを渡した場合は無視されます。

(例外を投げるように変更することも可能) このStrong Parametersでhashを許可する場合、2通りのやり方がありました。

例として

location = { x: 10, y: 20 }

というhashをパラメータとして送った場合、

1. hashの内容も厳密にチェックする場合

def permitted_params
  params.permit(:name, :email, location: [:x, :y])
end

というようにlocationをキーにして、許可するパラメータ(x, y)のシンボルを配列に記述します。

この場合は、新たにzキーを追加して

location = { x: 10, y: 20, z: 30 }

としてリクエストを行っても、zの値は無視されてしまうので注意が必要です。

p permitted_params[:location]
=> {"x"=>10, "y"=>10}

2. hashであれば内容自体はチェックしない場合

hashではあるけどhashのキーに何がくるかは厳密にチェックしなくてもいい、という場合はホワイトリストに追加することで対応できました。

def permitted_params
  params.permit(:name, :email).tap do |whitelisted|
    whitelisted[:location] = params[:location] if params[:location].is_a?(Hash)
  end
end

Object#.is_a?(Hash) でhashかどうかのチェックをして、hashだったらそのまま許可しています。

この場合は、新たにzキーを追加して

location = { x: 10, y: 20, z: 30 }

としてリクエストを行った場合は、zの値も取得できます。

p permitted_params[:location]
=> {"x"=>10, "y"=>10, "z"=>30}

以上、Strong Parametersでhashを許可する場合のやり方でした。

参考


Related #Rails

railsとsinatraの使い分け

sinatraでアプリを作っていたら、色々機能が足りなかったので継ぎ足し継ぎ足しで色々増やしていったら結局railsのようなもの、になってしまいました。

[mysql][rails]Character set 'utf8mb4' is not a compiled character set and is not specified in the '/usr/share/mysql/charsets/Index.xml' file

mysql5.1が動いていた環境をmysql5.6にアップデートした後、rake db:createで utf8mb4のDBを作成しようとしたところ以下のエラーが発生

[rails]omniauth-twitterで大きいサイズ(bigger)のプロフィール画像を取得する

ruby2.1, rails4.1.1で確認 omniauth-twitterを使ってtwitter認証を行った際にプロフィール画像を取得したかったのですが、デフォルト設定だと、`auth['info']['image']` に入ってくる画像URLの画像サイズが小さいので、大きい画像を取得するようにしました。

[rails]erbとunderscore.jsを一緒に使ったらundefined local variables in templatesエラーが発生

erbのテンプレート内にunderscore.js用のテンプレートを記述していたら