LoginSignup
11
2

More than 5 years have passed since last update.

Rails5.1.3 + Devise4.3.0でのエラーについて(will_save_change_to_email?)

Posted at

先日開発中のアプリケーションをRails5.1.3にアップデートしたところ、Deviseの挙動が少しおかしくなったので、それを解消するまでの話です。

Undefined method will_save_change_to_email?

とりあえずアップデートをかけてテストしてみたら以下のようなエラー。

undefined method `will_save_change_to_email?' for #<User:0x007fedc1671310>
Did you mean?  will_save_change_to_name?
               will_save_change_to_id?
               will_save_change_to_uid?
               will_save_change_to_token?
               will_save_change_to_attribute?

とりあえずGithubの中身を確認

devise/lib/devise/models/validatable.rb
module Devise
  module Models
    # Validatable creates all needed validations for a user email and password.
    # It's optional, given you may want to create the validations by yourself.
    # Automatically validate if the email is present, unique and its format is
    # valid. Also tests presence of password, confirmation and length.
    #
    # == Options
    #
    # Validatable adds the following options to devise_for:
    #
    #   * +email_regexp+: the regular expression used to validate e-mails;
    #   * +password_length+: a range expressing password length. Defaults to 8..72.
    #
    module Validatable
      # All validations used by this module.
      VALIDATIONS = [:validates_presence_of, :validates_uniqueness_of, :validates_format_of,
                     :validates_confirmation_of, :validates_length_of].freeze

      def self.required_fields(klass)
        []
      end

      def self.included(base)
        base.extend ClassMethods
        assert_validations_api!(base)
        base.class_eval do
          validates_presence_of   :email, if: :email_required?
          if Devise.activerecord51?
            validates_uniqueness_of :email, allow_blank: true, if: :will_save_change_to_email?
            validates_format_of     :email, with: email_regexp, allow_blank: true, if: :will_save_change_to_email?
          else
            validates_uniqueness_of :email, allow_blank: true, if: :email_changed?
            validates_format_of     :email, with: email_regexp, allow_blank: true, if: :email_changed?
          end

          validates_presence_of     :password, if: :password_required?
          validates_confirmation_of :password, if: :password_required?
          validates_length_of       :password, within: password_length, allow_blank: true
        end
      end

      def self.assert_validations_api!(base) #:nodoc:
        unavailable_validations = VALIDATIONS.select { |v| !base.respond_to?(v) }

        unless unavailable_validations.empty?
          raise "Could not use :validatable module since #{base} does not respond " <<
                "to the following methods: #{unavailable_validations.to_sentence}."
        end
      end

    protected

      # Checks whether a password is needed or not. For validations only.
      # Passwords are always required if it's a new record, or if the password
      # or confirmation are being set somewhere.
      def password_required?
        !persisted? || !password.nil? || !password_confirmation.nil?
      end

      def email_required?
        true
      end

      module ClassMethods
        Devise::Models.config(self, :email_regexp, :password_length)
      end
    end
  end
end
if Devise.activerecord51?
            validates_uniqueness_of :email, allow_blank: true, if: :will_save_change_to_email?
            validates_format_of     :email, with: email_regexp, allow_blank: true, if: :will_save_change_to_email?

ここでActiveRecord5.1だった時の処理が追加されていますね。
ここの条件として利用されているのがwill_save_change_to_email?という関数になります。ですが、どうやらdeviseのレポジトリの中のどこにもその関数が定義されていないようです。

バグっぽい?(2017/08/08時点)

Issuesでも指摘されているように、どうやらバグっぽいのですね。自分でこのdeviseを適用しているモデルにこの関数を定義してあげる必要があります。

app/models/user.rb
def will_save_change_to_email?
  false
end

今回私のアプリケーションではEmailを使っていなかったので、falseに設定しています。Emailを使っているならtrueにするといいでしょう。

11
2
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
11
2