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

More than 1 year has passed since last update.

【Rails】ストロングパラメータについて勉強しました【form_with】

Last updated at Posted at 2022-08-31

目的

Railsチュートリアル 第7章にてストロングパラメータという概念が紹介されていたので、その必要性と実装方法をまとめます。

今回開発するもの

Userモデル ユーザー
has_many: posts
idカラム: userインスタンスが作成されると自動付与される値

Postモデル ユーザーが行う投稿
belongs_to: user
contentカラム: 投稿内容
user_idカラム: 投稿とユーザーを紐づける値

表示画面
contentにテキストを入力し、送信すると新規postにcontentuser_idが入力される。
という機能を実装します。

これを実装するためのcreateアクションをストロングパラメータを使わずに(Progate的に)書くと下記の様になります。

posts_controller
def create
  @post = Post.new(
    content: params[:content],
    user_id: @current_user.id
  )
end

このとき@current_userは、現在ログイン中のユーザーを意味し、application_controllerで定義されています。

ビューファイルではform_withを使って、下記のように表現します。

posts/new.html.erb
<%= form_with model: @post, url: "/posts/create", method: :post, local: true do |f| %>
  <%= f.label :content %>
  <%= f.text_area :content %>
  <%= f.submit "送信" %>
<% end %>

このとき、ユーザーはcontent情報のみを記入し、user_idは記入していないことがポイントです。

ストロングパラメータの必要性

テキストエリアに入力された値はparamsによって取得されます。
このとき、paramsに不正な値が含まれる可能性があります。
例えばparamsadmin = 1のような値を入れ込まれると、Webサイトの管理者権限を奪われてしまい、セキュリティ的に問題が発生します。

ここでストロングパラメータを使うと指定した属性以外がparamsに入れられるのを防ぐことができます。

ストロングパラメータを使った記載方法

ストロングパラメータを使ったcreateアクションの記載方法は以下です。

posts_controller
def create
  @post = Post.new(post_params)
end

private
  
  def post_params
    params.require(:post).permit(:content).merge(user_id: @current_user.id)
  end

createアクションでは@postを定義しています。
@postはPostモデルのインスタンスを新たに作成し、そのキーと値はpost_paramsを使用します。

post_paramsはコントローラ内で定義されます。
このとき、privateで保護することで、このコントローラ外でpost_paramsが使用されるのを防ぎます。

さて、post_paramsparamsに対してどのようなメソッドが使われているのかを順番に見ていきましょう。
(やっと本題)

requireはデータをまとめるハッシュ

requireメソッドはPost.newを送るデータをまとめるハッシュの要素を示します。
RailsではPost.newで送られるデータはparams[:post]というハッシュにまとめて送っており、このハッシュの要素がrequireメソッドで指定されます。

permitは入力フォームで記入する値

ユーザーが実際に入力する項目をpermit内で指定します。
今回の例だとcontent属性の値を記入するので、permit(:content)としています。

mergeは裏で渡す値

インスタンスの属性には含めるけどユーザーが記入しない項目はmerge内で指定します。
今回の例でいうと、ユーザーは投稿時に自分のユーザーidを記入しませんが、@postにはuser_idが値として付与されます。
このように裏で渡す値を扱う場合はmergeを使用します。

複数の属性を渡すときは,で区切る

例えば今、投稿時にユーザーがcontent以外にgenreという属性も記入するとします。
このときのpost_params

posts_controller
def post_params
  params.require(:post).permit(:content, :genre).merge(user_id: @current_user.id)
end

と、,で区切ります。

まとめ

ProgateでRailsを一通り勉強した後、自分で簡単な投稿サイトを作成しました。
その後Railsチュートリアルで勉強し直したところ、より現場に近い設計思想をもとに話が進んでいると感じました。
自分で作った投稿サイトをProgateレベルからRailsチュートリアルレベルにリファクタリングする上で、知識が定着する感覚を得られました。

参考文献

Railsチュートリアル 第7章

【rails】form_forとform_tagの違い

【Rails】form_withの使い方とストロングパラメーターによるレコード登録

【Ruby on Rails】ストロングパラメータって何なの?

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