このエラーはしばらく見ていなかった上に、そんなに詰まるようなところでもないのですが、今回はハマってしまった、、、
結論を伝えると、
scopeの問題でした。
controllerのnewアクションとcreateアクションを書いた後に、
以下のように記述して、submitを押すと、今回のエラーが出てきました。
このエラーの時は大体、以下の場合なので、「はいはい、また出たね」という感じでした。
- パラメータを送れていない
- タイポしている
= form_with url: user_path, method: :post, local:true do |f|
= f.check_box :hoge_id
= f.hidden_field :user_id, value: current_user.id
= f.submit "Submit", disable_with: 'Submiting...'
しかし、
パラメータを確認してみると、以下のようになっていて、渡ってきている、、、
{"utf8"=>"✓", "authenticity_token"=>"省略", user_id"=>"1", "hoge_id"=>"1", 省略}
以下はストロングパラメータだが、タイポかなと思って確認するが、それも違う、、、
private
def user_params
params.require(:user).permit(:user_id, :hoge_id)
end
じゃあ、何が違うのか、、、と色々と試行錯誤してみましたがエラーが解消されず。
そして、あることに気がつきました。
「scopeが違う、、、」と。
どういうことかというと、先ほどのストロングパラメータではざっくりいうと
「userモデルにuser_idとhoge_idを保存することを許可するよ」ということです。
private
def interview_sheet_params
params.require(:user).permit(:user_id, :hoge_id)
end
しかし、先ほどのパラメータだとおかしくて、正しくは、以下のようにならなければいけません。
{"utf8"=>"✓", "authenticity_token"=>"省略", "user"=>{"user_id"=>"1", "hoge_id"=>"1"}, 省略}
重要な部分だけ取り出すと、以下の部分です。
上が間違いで下が正しい書き方です。
要は、userモデルの中にuser_idとhoge_idが入っているよというのが下です。
上だと、どのモデルに送るのかが明示されていないので、データが存在しない振る舞いになるわけですね。
user_id"=>"1", "hoge_id"=>"1"
"user"=>{"user_id"=>"1", "hoge_id"=>"1"}
じゃあ、どうしたら良いかというと、scopeを使いましょう。
以下のようにscopeでモデル名を指定すれば、paramsが上から下のようになります。
= form_with url: user_path, method: :post, scope: :user, local:true do |f|
railsは色々と勝手にやってくれる反面、時々思った挙動にならないこともあるので、注意が必要ですね。