2

デバイスとパスワードの確認に問題があります。次のようなモデル テストを rails4 で作成しました。

test "user requires a password_confirmation" do
  user = FactoryGirl.build(:user)
  assert user.valid?, "FactoryGirl should return a valid user"

  user.password_confirmation = nil

  # These are just some outputs to verify what's going on.
  # This is the condition in devises's password_required? method
  puts !user.persisted? || !user.password.nil? || !user.password_confirmation.nil? #=> true
  puts user.valid? #=> true

  assert user.invalid?, "Password confirmation should be required" # Fails here
  assert_equal 1, user.errors.size, "Only one error should have occured. #{user.errors.full_messages}"
end

このテストは 2 回目のアサートで失敗します ( "Password confirmation should be required")。

ここに私の完全なユーザーモデルがあります:

class User < ActiveRecord::Base
  has_one :user_entity

  has_one :manager,through: :user_entity, source: :entity, source_type: 'Manager'
  has_one :client, through: :user_entity, source: :entity, source_type: 'Client'

  # Adds default behavior. See: https://github.com/stanislaw/simple_roles#many-strategy
  simple_roles

  validates :username,
    presence: true,
    length: { minimum: 4, allow_blank: true, if: :username_changed? },
    uniqueness: { allow_blank: true, if: :username_changed? },
    format: { with: /\A[A-z_0-9]+\z/, allow_blank: true, if: :username_changed? }

  # Include default devise modules. Others available are:
  # :token_authenticatable, :timeoutable, :omniauthable, :registerable
  devise  :database_authenticatable, :recoverable, :rememberable,
          :trackable, :validatable, :confirmable, :lockable

  # Virtual attribute for authenticating by either username or email
  # This is in addition to a real persisted field like 'username'
  attr_accessor :login

  def self.find_first_by_auth_conditions(warden_conditions)
    conditions = warden_conditions.dup

    # User need to be active
    conditions[:active] = true

    if login = conditions.delete(:login)
      where(conditions).where(["lower(username) = :value OR lower(email) = :value", { :value => login.downcase }]).first
    else
      where(conditions).first
    end
  end

  def entity
    self.user_entity.try(:entity)
  end

  def entity=(newEntity)
    self.build_user_entity(entity: newEntity)
  end

end

ユーザーモデルに追加してみました:

validates :password,    confirmation: true

その後、テストはパスしますが、次のテストでエラーが発生します:

  1) Failure:
UserTest#test_user_requires_a_password [/my/project/test/models/user_test.rb:52]:
Two errors should have occured. ["Password confirmation doesn't match confirmation", "Password confirmation doesn't match confirmation", "Password can't be blank"].
Expected: 2
  Actual: 3

ご覧のとおり、確認の検証が 2 回発生し、両方とも失敗したようです。

Rails4 (エッジ) と、デバイス用の rails4 ブランチを使用しています。

編集:設定してみました

user.password_confirmation = "#{user.password}_diff"

そして、テストはパスします。では、が設定されているときに確認が無視されるのはなぜnilですか? オブジェクトはまだ永続化されていないため、パスワードの確認を提供する必要があると想定します。

4

1 に答える 1

6

これは古い質問であることは知っていますが、同じ問題を抱えていました。

最初に、これをモデルから削除して、検証チェックが重複しないようにします。

validates :password, confirmation: true

次に、以下を追加します。作成時にのみ機能するように変更しました:

validates :password_confirmation, presence: true, on: :create

この apidock ページのvalidates_confirmation_ofセクションを参照してください。

注: このチェックは、password_confirmation が nil でない場合にのみ実行されます。確認を要求するには、確認属性の存在チェックを必ず追加してください。

validates_presence_of :password_confirmation, if: :password_changed?

于 2016-12-11T20:54:22.050 に答える