0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Rails の Strong Parameters が不要なパターン

Last updated at Posted at 2022-06-10

はじめに

最近 Rails に触れる機会があり、Strong Parameters について調べた際にタイトルの内容が知りたかったのですが、書かれている記事を見つけられなかったのでそのことを。

Ruby 自体も含め、しっかり絡んだことがなかったので用語などが Ruby 界隈と合っていなかったりしたらご容赦ください。

先に Strong Parameters について簡単に触れますが、不要な場合は「Strong Parameters が不要なパターン」からお読みください。

Strong Parameters とは

詳しいところは検索すればいろいろ出てくるので割愛しますが、ざっくりいうと

Post されたデータ( params )に対し、マスアサインメントを利用する際に意図しないパラメーターが使用されないようにする仕組み

です。

マスアサインメントは、複数カラムを一括で指定する仕組み。

元々はモデル側で attr_accessible を使って許可を与えていたようですが、脆弱性を作りやすいことから Rails4 で Strong Parameters が導入されたようです。
このため、Rails4 では attr_accessible が廃止されています。

Strong Parameters の例

Personname, age, isAdmin あったとして、isAdmin を更新させたくない場合、

people_controller.rb
def create
    @person = Person.new(person_params)
    @person.save
end

private
def person_params
    params.require(:person).permit(:name, :age)
end

という感じで、nameage だけ許可を与えます。

@person = Person.new(params.require(:person).permit(:name, :age))

という書き方もできますが、Strong Parameters を処理する部分は private にすることが推奨されています(可読性、視認性もよくないですし)。

参考: https://railsguides.jp/action_controller_overview.html#strong-parameters

Strong Parameters を使用しなかった場合、どうなるか

マスアサインメントを利用しつつ、Strong Parameters を使用しなかった場合、ForbiddenAttributesError が発生します。

ForbiddenAttributesError

Post されたデータは params という ActionController::Parameters のインスタンスに格納されていますが、この params には permitted: false というのが付与されていて、このままマスアサインメントに利用すると「許可されていない(permitted: false)」、つまり「禁止されている(Forbidden)」ということでエラーになります。

前述の例のように permit を行うことで permitted: true に変わり、マスアサインメントに利用できるようになります。

Strong Parameters が不要なパターンは?

本題です。

Strong Parameters が不要なパターンはあるのだろうか、というのが気になったのですが、そのことに触れている記事や書き込みを見つけることができませんでした。

マスアサインメントを使わなければ不要なんだろう、というのは推察できますが、明確に書かれたものがない以上自分で確認するしかありません。

ということで以下のパターンで確認しました。

Strong Parameters が不要なパターン

いずれもマスアサインメントを利用していないため、permit をしなくてもエラーになりません。

パターン1:それぞれのパラメーターを引数で指定する( params を直接使用)

people_controller.rb
def create
    @person = Person.new(name: params[:person][:name], age: params[:person][:age])
    @person.save
end

パターン2:それぞれのパラメーターを引数で指定する( params の値を変数に格納)

people_controller.rb
def create
    name = params[:person][:name]
    age = params[:person][:age]
    @person = Person.new(name: name, age: age)
    @person.save
end

パターン3:Person オブジェクトの各パラメーターに代入

people_controller.rb
def create
    @person = Person.new
    @person.name = params[:person][:name]
    @person.age = params[:person][:age]
    @person.save
end

パターン4:params[:person] をいったん変数に格納後、個別に設定

people_controller.rb
def create
    person = params[:person]
    @person = Person.new(name: person[:name], age: person[:age])
    @person.save
end

パターン5:params[:person] の各値を別のハッシュに格納し、引数に使用

people_controller.rb
def create
    person = {}
    person[:name] = params[:person][:name]
    person[:age] = params[:person][:age]
    @person = Person.new(person)
    @person.save
end

このパターンはマスアサインメントを使用していることになりますが、personActionController::Parameters のインスタンスではないため permitted 属性がついておらず、permit をしなくてもエラーになりません。

エラーになるパターン

一応、エラーになるパターンも書いておきます。
これらのパターンでは ForbiddenAttributesError が発生します。

パターン1

people_controller.rb
def create
    @person = Person.new(params[:person])
    @person.save
end

パターン2

people_controller.rb
def create
    person = params[:person]
    @person = Person.new(person)
    @person.save
end

この場合でも personpermitted: false がついたままなのでエラーになります。

パターン3

people_controller.rb
def create
    para = ActionController::Parameters.new({
               name: "", age: -1
           })
    para[:name] = params[:person][:name]
    para[:age] = params[:person][:age]
    @person = Person.new(para)
    @person.save
end

params からは個別に取り出していますが、 para の方にも permitted: false がついているので permit しないとエラーになります。

おまけ

本末転倒パターン

people_controller.rb
def create
    @person = Person.new(person_params)
    @person.save
end

private
def person_params
    params.require(:person).permit(:name, :age, :isAdmin)
end

Strong Parameters を使おうと使うまいと、余計なパラメーターを指定しては元も子もないので注意したいところ。

マスアサインメントを使用したほうがコード量が少なく、 person_params を見ればどれが許可されているかもわかりやすいので、可能な限り Strong Parameters を使用したほうがいいかもしれません。

0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?