元祖若手のプログラミング奮闘記

元祖若手の奮闘記。主にメモ

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

初歩的なミスですが 重大なバグになりそうなので書いておきました。