From f5f8e0aad36760ebf16fd0d200f0b2eafa523f1d Mon Sep 17 00:00:00 2001 From: Anthony Navarre Date: Mon, 20 Jan 2014 15:26:34 -0700 Subject: [PATCH] Validate unique + allow_nil + has_secure_password - Addresses #371 --- NEWS.md | 4 ++++ .../active_model/validate_uniqueness_of_matcher.rb | 8 ++++++++ .../validate_uniqueness_of_matcher_spec.rb | 12 ++++++++++++ 3 files changed, 24 insertions(+) diff --git a/NEWS.md b/NEWS.md index cf554860..bbf2f31e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -5,6 +5,10 @@ * Add ability to test `:autosave` option on associations. +* Fix `validate_uniqueness_of(...).allow_nil` so that it can be used against an + non-password attribute which is in a model that `has_secure_password`. Doing + so previously would result in a "Password digest missing on new record" error. + # v 2.5.0 * Fix Rails/Test::Unit integration to ensure that the test case classes we are diff --git a/lib/shoulda/matchers/active_model/validate_uniqueness_of_matcher.rb b/lib/shoulda/matchers/active_model/validate_uniqueness_of_matcher.rb index 50b4ed38..4f074ce3 100644 --- a/lib/shoulda/matchers/active_model/validate_uniqueness_of_matcher.rb +++ b/lib/shoulda/matchers/active_model/validate_uniqueness_of_matcher.rb @@ -115,10 +115,18 @@ module Shoulda # :nodoc: @subject.class.new.tap do |instance| instance.send("#{@attribute}=", value) + if has_secure_password? + instance.password = 'password' + instance.password_confirmation = 'password' + end instance.save(validate: false) end end + def has_secure_password? + @subject.class.ancestors.map(&:to_s).include?('ActiveModel::SecurePassword::InstanceMethodsOnActivation') + end + def set_scoped_attributes if @options[:scopes].present? @options[:scopes].all? do |scope| diff --git a/spec/shoulda/matchers/active_model/validate_uniqueness_of_matcher_spec.rb b/spec/shoulda/matchers/active_model/validate_uniqueness_of_matcher_spec.rb index 70689ef8..7c28f880 100644 --- a/spec/shoulda/matchers/active_model/validate_uniqueness_of_matcher_spec.rb +++ b/spec/shoulda/matchers/active_model/validate_uniqueness_of_matcher_spec.rb @@ -293,6 +293,18 @@ describe Shoulda::Matchers::ActiveModel::ValidateUniquenessOfMatcher do end end + if active_model_3_1? + context 'when the subject has a secure password' do + it 'allows nil on the attribute' do + model = define_model(:example, attr: :string, password_digest: :string) do |m| + validates_uniqueness_of :attr, allow_nil: true + has_secure_password + end.new + expect(model).to matcher.allow_nil + end + end + end + it "should create a nil and verify that it is allowed" do model = define_model_with_allow_nil expect(model).to matcher.allow_nil