【Rails】ストロングパラメーターについて徹底解説!

Rails

ストロングパラメーターとは

フォームから入力された情報を指定して、安全に受け取るための仕組みです。
設定しておくことにより不正な情報を受け取ることを防ぎます。

なぜ使う必要があるのか
リンクをコピーしました

投稿フォームに入力された情報はparamsによって取得できます。
その際、不正に投稿された内容がparamsに含まれているとその情報まで保存されてしまいます。

そこでストロングパラメーターというものを設定しておきます。
ストロングパラメータを設定しておくと指定したカラムの情報だけを受け取ることができます。

ストロングパラメータの定義の仕方
リンクをコピーしました

以下のようなコードがストロングパラメーターです。

ruby
1
2
3
def tweet_params
  params.permit(:title, :text)
end

この中で使っているpermitメソッドはparamsで取得したキーのうち、データベースに保存してもいいものを許可するメソッドです。

上の例ではtitleカラムとtextカラムの値だけデータベースに保存されることを許可しています。
ですので、たとえparamsの中に他のカラムのパラメーターがあってもデータベースには保存されません。
この「tweet_params」の返り値は「{title: "入力した値, text: "入力した値"}となります。

設定する理由
リンクをコピーしました

createアクションの引数に下記のようにparamsとするとエラーが出て保存できません。

ruby
1
Hoge.create(params)

これはもし不正なパラメーターが入っていた場合、それまで取り出してデータベースに保存されるのを防ぐためです。
どのような仕組みでエラーが出るのでしょうか?それを確認してみましょう。

paramsでパラメーターを取得すると下記のようなコードになっています。

shell
1
2
3
4
5
6
7
8
[1] pry(#<UsersController>)> params
=> <ActionController::Parameters 
{"utf8"=>"✓", 
"authenticity_token"=>"hogehoge==",
 "name"=>"プログラマン2号",
 "job_id"=>2,
 "controller"=>"users",
 "action"=>"create"} permitted: false>

最後の行を見ると「permitted: false」というコードがあります。
この状態でcreateアクションの引数にparamsを指定するとエラーが出てしまうというわけです。

では次にストロングパラメーター内に書いたpermitメソッドを使った返り値を確認してみましょう。

shell
1
2
3
4
pry(#<UsersController>)> params.permit(:name,:job_id)
Unpermitted parameters: :utf8, :authenticity_token
=> <ActionController::Parameters
 {"name"=>"プログラマン2号", "job_id"=>2} permitted: true>

最後の行が「 permitted: true」になっているのが確認できますね。
そしてpermitで指定していないparamsで取得した他のパラメータは「Unpermitted parameters」となっています。
このようにストロングパラメーターを定義するとエラーなく保存ができるというわけです。

ストロングパラメーターはclass内でprivateメソッドを使い定義します。

privateメソッド
リンクをコピーしました

クラスを定義するときにprivateメソッドを呼び出すとそれ以降に定義されるインスタンスメソッドはそのクラス中でしか呼び出されなくなります。
privateメソッドを使っておけばクラス外部で呼び出されるとエラーが起きるようなメソッドが使われるのを防ぐことができたり、コードの可読性が上がるなどのメリットがあります。

ストロングパラメーターはクラス内部でしか使わないので、そういうメソッドはprivate以下に定義しておきましょう。

実際のアプリでストロングパラメーターを定義してみよう
リンクをコピーしました

下記のコマンドを順に実行してみましょう。
①git clone -b strong_parameters https://github.com/miyagit/programan_dojo.git

② cd programan_dojo

③ bundle install
→ rbenv: version ‘2.4.1’ is not installed と表示された場合は、ruby -v と実行してください。

ruby -vと実行し出てきたversion(例: 2.3.1)と出てきたら、

vim .ruby-versionとし、
ruby -vで出てきた値(例: 2.3.1)に書き換えてください。

続いてvim Gemfileとし、ruby 2.4.1と書いてある部分をruby -vで出てきた値(例: 2.3.1)に書き換えてください。

④ rails db:create && rails db:migrate && rails db:seed

環境構築が完了しました。と表示されると、
本当にrails applicationが動作するかrails sコマンドで起動しましょう。

rails sを起動し、ブラウザでlocalhost: 3000と入力して下記のような画面が出てくれば環境構築完了です!

環境構築

createアクションを確認してみよう
リンクをコピーしました

まず現在のusersコントローラーのcreateアクションがどのように書かれているか確認してみましょう。

ruby
1
2
3
4
def create
  User.create(params[:user])
  redirect_to root_path
end

投稿フォームはform_forで記述しているのでparamsはparams[:user]と指定する必要があります。
これで投稿フォームの内容はparamsで取得できるので、このようにかけば投稿フォームの内容がデータベースに保存されるはずです。
それではトップページから「ユーザー登録」をクリックし、実際に投稿をしてみましょう。

params
フォームに入力し、送信ボタンを押すと下のようなエラーが出てしまいました。

エラー画面
これはストロングパラメーターを使っていないと出るエラーです。
このようにparamsに対してpermitメソッドを使い、保存してもいいカラムを指定しないとこのようなエラーが出てデータベースに保存されないようになっています。

それではusersコントローラーにストロングパラメーターを定義してみましょう。

ruby
1
2
3
4
private
def tweet_pramas
    params.require(:user).permit(:name, :job_id)
end

これでnameカラムとjob_idカラムのみparamsで取得できるようになりました。
もう一度投稿をしてみましょう。

投稿画面
するとこのようにしっかりとデータベースに保存されました。

データ書き換えの危険性を確認しよう
リンクをコピーしました

ストロングパラメーターを設定すればこのように保存されたくない情報はparamsに入りません。
ではもしストロングパラメーターを設定しなかったとしたらどのようなことがおきてしまうでしょうか?
検証モードで実行してみましょう。

投稿フォームに下記のように入力してください。

投稿フォーム
今回はこのフォームを書き換えてみます。
右クリックで検証モードを選択し、検証モードを表示させてください。

検証モード
検証モードではソースを書き換えることができます。
下記のように編集をしてみましょう。

編集
user[name]の部分をuser[job_id]に、下のuser[job_id]の部分をuser[name]に変更してください。
本来であればnameカラムに「3」が、job_idには「1」が保存されるはずです。
それでは投稿をしてみましょう。

投稿
このようにjob_idで指定した「1」という数字が保存されてしまいました。
これがもしユーザーの情報に管理者か一般ユーザーかを識別するカラムがあったとして、管理者が「0」、一般ユーザーが「1」で登録できた場合、ここでカラムを書き換え管理者として保存されてしまうことができます。

そんな時でもストロングパラメーターを設定しておけば、paramsの中に許されているカラムの情報しか入らないので、データベースには保存されなくて済みますね。

まとめ

ストロングパラメーターはデータベースに保存するカラムを指定し、paramsで安全な情報を受け取らせる仕組みです。
railsではストロングパラメーターを設定しないとエラーになってしまいますので、忘れずに設定するようにしましょう。