今日はparams.requireの順番によってエラーが発生した件について書きたいと思います。
#エラーの解消後と解消前
(エラー解消前)posts_controller.rb
def post_params
#params.require(:post).permit(:name, :title, :content)
#pictureとtags_ids:[]の順番を入れ替えてみた
params.require(:post).permit(:title, :content, tag_ids:[], :picture)
end
(エラー解消後)posts_controller.rb
↓↓↓↓↓↓↓ あなたの記事の内容
───────
```rb
↑↑↑↑↑↑↑ 編集リクエストの内容
#paramsから欲しいデータのみ抽出
def post_params
#params.require(:post).permit(:name, :title, :content)
#picture → tags_ids:[] の順番
params.require(:post).permit(:title, :content, :picture, tag_ids:[])
end
画像でみるとこんな感じで間違ってるよ!の表示が2つあります。
#エラーの解決方法
回答についてはこちらRails5 Strong Parametersで複数の配列を許可するに書いてありました!
Strong Parametersで配列データを扱う時、該当の配列は一番最後に記述しなければいけないというルールがあるらしい(情報ソースはどこか忘れてしまいました)なので、以下のように書くと許可出来る。
def hoge_params
params.permit(:name, :pref, :text, hobbies: [])
end
とすると、配列データを許可することが出来ました。
ただ今回は、以下のストロングパラメータについて自分が理解していないので記事にまとめてみたいと思います!
params.require(:post).permit(:title, :content, :picture, tag_ids:[])
#strong parametersについて
私のアプリ内のusers_controller.rbには以下の記述があります。
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation)
end
また、post_sontroller.rbには最初に記述したものと同様、以下の記述があります。
def post_params
#params.require(:post).permit(:name, :title, :content)
params.require(:post).permit(:title, :content, :picture, tag_ids:[])
end
ついでにsomment_params.rbにも似たような記述がありました。
def comment_params
params.require(:comment).permit(:post_id, :name, :comment)
end
つまり、
def 〇〇_params
end
が何かの役割を持っているということでしょうか。
参考になるサイト:Railsを始めたばかりの人向け!Railsの仕組みを一から理解しながらブログを作成する
から引用します。
Railsではセキュアなアプリケーションの開発を促すためにいくつかのセキュリティ機構が存在します。そして、今そのセキュリティ機構によりエラーが発生しました。この機構は、Strong Parametersと呼ばれ、Railsは、私たちに「パラメーターのどの値を取得したいか」をコントローラー内に明示することを要求しています。今回の場合で言うと、パラメーター内のtitleとtextの値を取得したいので、次のように変更して下さい。
># POST /posts
def create
@post = Post.new(post_params)
@post.save
redirect_to @post
end
private
def post_params
params.require(:post).permit(:title, :text)
end
permitメソッドは、私たちがアクション内でtitleとtextを取得できるようにRailsに明示しています。
※def post_paramsがプライベートメソッドであることに注意して下さい。Strong Parametersは、攻撃者がパラメーターの値を操作し、モデル内の属性を開発者側の意図しない値に設定することを防ぐRails4から導入されたセキュリティ機構です。より詳細については、this blog post about Strong Parametersを参照ください。
Rails初学者がつまずきやすい「ストロングパラメータの仕組み」からも引用してみます。
サンプル:blog[title]:私たちのミッションは、
blog[content]:すべての人が、テクノロジーを武器にして活躍できる社会をつくることです。
が、Ruby on Rails内のコントローラ内部で使われる値(パラメータ)として使われます。
この Form Data の値。これをコントローラ内部で受け取る仕組みが、ストロングパラメータです。
ソースコードを見ると、
def create
@blog = Blog.new(blog_params)
にて、blog_paramsメソッドを実行した結果
def blog_params
params.require(:blog).permit(:title, :content)
end
を、new( ) メソッドの引数として使い、Blogモデルクラスのインスタンスを生成して、@blogに格納しています。この blog_params メソッドがストロングパラメータと呼ばれる仕組みを実現しているメソッドです。
httpリクエスト上の Form Data などの値を、Ruby on Rails では params メソッドでコントローラ内部に受け取ることができます。
params.require(:blog).permit(:title, :content)
は、「httpリクエスト上にあるパラメータのうち :blog というキーを持ち、 :title と :content というキーを持つハッシュ形式であること」を確かめます。確かめる目的は、Webブラウザ上で手作業などで意図的にパラメータを書き換えられた際に、エラーとして弾くことができるようにするためです。その後 @blog に格納された内容は、データベース内に保存されます。
if @blog.save
以上が、ストロングパラメータの仕組みです。
少し話がずれますが前半に出てきたいくつかの言葉について以下に引用してみました。
##プライベートメソッドとは?
Ruby の private メソッドとは - Secret Garden(Instrumental)
基本的には Ruby では自分以外からメソッドを呼び出す場合にレシーバが必要になる。
そのため、private メソッドにすることで『自分以外からメソッドを呼び出すことを制限する』事ができる。
##レシーバとは
あるオブジェクトに対して、メソッドを実行しようとした場合、そのメソッドの働きかけるオブジェクトのことをレシーバという。以下のコードの場合だと、配列部分がレシーバとなる。例えばこのような場合['1','2','3']の部分がレシーバである。
['1','2','3'].index(1)
#最後に
今回は一つのエラーがきっかけとなりストロングパラメータについて理解を深めることができました。
間違った記述をしている場合は教えてください。
今日のエラーは以上です。
(参考)一番上のサイトがわかりやすく説明していました。
・RailsのStrong Parametersを調べる
・Railsを始めたばかりの人向け!Railsの仕組みを一から理解しながらブログを作成する
・Rails5 Strong Parametersで複数の配列を許可する