[Rails]deviseで思わぬバリデーションエラー


はじめに

ユーザー管理でお世話になっているdeviseで思わぬエラーにハマり、かなりの時間を溶かしたので備忘録として残しておきます。

環境/Gem(ver)

  • Ruby (2.5.1)
  • Rails (5.2.4.3)

結論

自分でUserモデルにvalidatesをかける時は気をつけよう。

ちゃんと下調べをして今後実装するようにします。。

前提

devise を bundle install 後、以下のように Userモデルにバリデーションをかけていました。
passwordには7文字以上の制限をかけたいと考えていました。

これで、新規ユーザーの登録は問題なくできていました。

※UserとShopは多対多の関係で中間テーブルにStylistテーブルがあるイメージで実装しています。

(models/user.rb)
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable

  has_many   :stylists
  has_many   :shops, through: :stylists

  (省略)

  validates :password, presence: true, length: { minimum: 7 }, format: { with: /(?=.*\d+.*)(?=.*[a-zA-Z]+.*)./ }
end 

現象

ユーザー(Userモデル)登録後に新規でショップ(Shopモデル)を作成と同時に中間テーブル(Stylistモデル)を作成しようとすると、、エラー。

パラメーターにはちゃんと値が入っているし、何が「不正な値」なのか、その原因が突き止められず。
また、「新規登録(new/create)はできないが編集(edit/update)はできる」という状況で、謎が深まり、多くの時間を溶かしました。。

仮説

外部キーのnilを許可すれば解決するのでは?

(models/stylist.rb)
class Stylist < ApplicationRecord
#修正前
  belongs_to :shop
  belongs_to :user
#修正後
  belongs_to :shop, optional: true
  belongs_to :user, optional: true
end

・・・ダメでした。

解決策

バリデーションに原因があるのは間違いないので、Userモデルに記述しているvalidatesを一つ一つ解除しながら、挙動を確かめていくと、、

(models/user.rb)
class User < ApplicationRecord

  (省略)

  validates :password, presence: true, length: { minimum: 7 }, format: { with: /(?=.*\d+.*)(?=.*[a-zA-Z]+.*)./ }
end 

↑ validates :password を消したら万事解決でした!!

そして、以下の場所にカスタマイズ内容を書き換えました。

(config/initializers/devise.rb)
class User < ApplicationRecord

  (省略)

#修正前
  config.password_length = 6..128
#修正後
  config.password_length = 7..128

そもそもなぜ中間テーブルを保存する際にエラーを吐き出すのか?謎のままですが、deviseにはデフォルトのバリデーションがあり、自作したバリデーションと良からぬ反応をしたのかなと思います。。(勉強します)

また、以下の記事を参考にさせていただき、カスタマイズをしたところ問題なく動作しております!

参考記事

https://qiita.com/hirokihello/items/862284c60429be5e01cd
https://github.com/heartcombo/devise/wiki/Customize-minimum-password-length