LoginSignup
4
4

More than 3 years have passed since last update.

DeviseのUserテーブルにUpdateアクションでカラムを更新しようとするとうまくいかない現象について

Posted at

事の発端

Deviseで作ったUserモデルのテーブルにカラムを更新しようとするとできなかったことが始まりです。

意外なところで詰まったなぁと思ったので健忘録としてまとめます。

user_controller.rb

  def update
    @user = User.find(params[:id])
    if @user.update(user_params)
      redirect_to user_path(@user.id)
    else  
      render :show
    end
  end

僕は月の走行距離をマイページにて追加したかった為詳細ページにform_withを構えています。

show.html.erb
  <%= form_with(model: @user, local: true, class: "goal-form")  do |f| %>
    <%= f.text_field :distance, placeholder: "目標を記入する", class: "form__text" %>
    <%= f.submit "設定する", class: "btn btn-primary" %>
  <% end %>

送られてくる値も間違ってなかったのでなんでやねんと思っていたとこでした。
そこで以下のエラーを見つけました。
EFE24E99-97AA-473B-8332-1DEF840AD209_4_5005_c.jpeg

そもそもUserテーブルの編集にはPasswordの入力が必要だということ。

知りませんでした。
これまでユーザーの編集を行うことがなかったんです。

そこでPasswordを入力せずにユーザーの編集を行う方法を見つけました。
カラムを更新するには新たなコントローラの作成やメソッドが必要なようです。

まずは、users/registrations_controller.rbを作成します。

registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
  before_action :configure_account_update_params, only: [:update]

  protected

  def configure_account_update_params
    devise_parameter_sanitizer.permit(:account_update, keys: [:name])
  end
end

次にルーティングを設定します。

route.rb
  devise_for :users, controllers: {
    registrations: 'users/registrations'
  }

Userモデルを編集。メソッドを追加します。

user.rb

  メソッドを追加
  def update_without_current_password(params, *options)
    params.delete(:current_password)

    if params[:password].blank? && params[:password_confirmation].blank?
      params.delete(:password)
      params.delete(:password_confirmation)
    end

    result = update_attributes(params, *options)
    clean_up_passwords
    result
  end
end

Userモデルで定義したメソッドを呼び出します。

registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
  before_action :configure_account_update_params, only: [:update]

  protected
追加
  def update_resource(resource, params)
    resource.update_without_password(params)
  end

  def configure_account_update_params
    devise_parameter_sanitizer.permit(:account_update, keys: [:distance])
  end

また、モデルにpasswordのバリデーションがかかっているとまだエラーになると思うので外しておきましょう。

user.rb
  with_options presence: true do
    validates :nickname
    validates :email
    validates :password    ←消す
  end  

できました。ほぼコピペです…

ここで初見だった方々が多かったのでまとめてみました。

・:account_update・・・Updateをするときに指定する引数。
・blank?・・・中身が空もしくは存在しないときにtrueを返す。
・update_attributes・・・一つのカラムのみを変更できる。しかし、バリデーションがスルーされる為、エラーの判定位が出ない。(これに苦しめられた)

キリがないのでここまで。

完成

これから、jsで今日走った距離が引かれて減っていくような機能を導入したいなと思います。
お疲れ様でした。

参考文献

4
4
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
4
4