Rails 更新時にParams Permitを間違えてまるっと子モデルのデータが消えた話
困った問題
なぜか子モデルが消して入れ直す形になってしまったので 忘れないようにメモ
class UsersController < ApplicationController before_action :set_user, only: %i[edit update] def edit; end def update if @user.update(user_params) redirect_to home_path else render :edit end end private def user_params params.require(:user).permit( :email, :password, user_profile_attributes: %i[address nick_name] ) end def set_user @user = User.find(session[:user_id]) end end # 親モデル class User < ApplicationRecord has_one :user_profile, dependent: :destroy accepts_nested_attributes_for :user_profile end # 子モデル class UserProfile < ApplicationRecord belongs_to :user end
そして今回ハマったのがここなんですが user_params
これとは違うControllerで UserProfileを更新することがあるのですが
そうするとUsersController で更新した際に 見事に一回消して入れて行なってしまうため 前の項目がまるっと消されてる! という状況が生まれてしまうのでした。。
Unpermitted parameter: :id (1.6ms) BEGIN UserProfile Load (2.4ms) SELECT `user_profiles`.* FROM `user_profiles` WHERE `user_profiles`.`user_id` = 1 LIMIT 1 SQL (2.2ms) DELETE FROM `user_profiles` WHERE `user_profiles`.`id` = 101 SQL (2.9ms) INSERT INTO `user_profiles` (`user_id`, `address`, `nick_name`, `created_at`, `updated_at`) VALUES (1, 'tokyo', 'hoge', 2020-02-20 13:51:02', '2020-02-20 13:51:02') SQL (2.5ms) UPDATE `users` SET `updated_at` = '2020-02-20 13:51:02' WHERE `users`.`id` = 1 (10.1ms) COMMIT
ですが実はもう答えは書いてあるのです!
そこ! Unpermitted parameter: :id
解決策
子モデルの permit parameter に :id を追加してあげれば ちゃんと更新されるのでした。
def user_params params.require(:user).permit( :email, :password, user_profile_attributes: %i[id address nick_name] ) end
(1.9ms) BEGIN UserProfile Load (2.6ms) SELECT `user_profiles`.* FROM `user_profiles` WHERE `user_profiles`.`user_id` = 1 LIMIT 1 SQL (2.5ms) UPDATE `user_profiles` SET `nick_name` = 'hogehoge', `updated_at` = '2020-02-20 14:01:29' WHERE `user_profiles`.`id` = 102 SQL (2.3ms) UPDATE `users` SET `updated_at` = '2020-02-20 14:01:29' WHERE `users`.`id` = 1 (3.6ms) COMMIT
初歩的なミスですが 重大なバグになりそうなので書いておきました。