1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Rails 8: strong parametersの新しい`params.expect`の使い方を読んだのでアウトプットをする

Posted at

背景

  • Rails8が登場してparams.expectを使用する機会があったので、色々調べたアウトプットをします

params.expectとは

Rails7ではparams.requireparams.permitを使用して、ストロングパラメータの実装を行なっていましたが、params.expectはそれよりコード短いし、セキュリティ的にも良さげだよ

というメソッドです

使い方

従来のRailsでは、ストロングパラメータをコントローラの中で定義するときに下記の感じで書いてました

users_controller.rb
  def create
    @user = User.new(user_params)

    if @user.save
      redirect_to users_path
    else
      render :new, status: :unprocessable_entity
    end
  end

  private

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

Rails8ではこんな感じでかけます

users_controller.rb
  def create
    @user = User.new(user_params)

    if @user.save
      redirect_to users_path
    else
      render :new, status: :unprocessable_entity
    end
  end

  def update
    # 省略
  end

  private

  def users_params
    params.expect(user: [:name, :email])
  end

短いすね

なぜexpectの方が良いのか

1.パラメータを改ざんされた時、返すエラーが違う

従来通りparams.requireparams.permitを使用した場合

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

パラメータを少しいじって、こんな感じのリクエストをサーバーに送信したとします。

# 更新
PATCH /user/1?user=hoge

"500 Internal Server Error"が返ってきます

Rails8から出たparams.expectの場合は

  def users_params
    params.expect(user: [:name, :email])
  end

400 Bad Requestを返します。

400と500どっちもエラーなのに、500はなぜゆえダメなのか

  • 500エラーがダメな理由
  1. ユーザー体験の低下: サーバー内部の問題を示すため、クライアントに対して具体的なエラーメッセージを提供されない。どこで何が起きてるかわからなくなる
  2. セキュリティリスク: サーバー内部の問題を示すため、悪いやつがその脆弱性を攻撃してくるかも
  • 400エラーが良い理由
  1. ユーザー体験の向上: 具体的にどこが悪いのか教えてくれる。どうすれば解決するのかがわかる状態
  2. セキュリティの向上: クライアントのリクエストが不正なので、サーバー側の問題が露呈しにくい

permit requireexpectを比較した時の話です

2.パタメータの型チェックをしてくれる

従来のparams.permitでは型のチェックをしてくれませんでした

仮にusers_paramsを下記に設定したとします。

  def users_params
    params.permit(user: [:name])
  end

意図としては、:nameは配列のみを許可したい感じです。

しかし、これだと

@user = User.new(user: { name: 'hoge' })

これでも通ってしまいます。

ではRails8のparams.expectでは

  def users_params
    params.expect(user: [[:name]])
  end

「二重配列」構文で明示的に配列のみを指定することで、配列だけを許可するという書き方ができます。

仮に

@user = User.new(user: { name: 'hoge' })

を渡してあげると"400 Bad Request"が出るようになります。

感想

  • 短いコードかつ、セキュリティが高くなる方が良いに決まっているので、こっち使おうと思った。
  • 意外と知らないことがたくさんあったのでボリュームあった

参考

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?