class Shoulda::Matchers::ActiveRecord::ValidateUniquenessOfMatcher
@private
Public Class Methods
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 299 def initialize(attribute) super(attribute) @expected_message = :taken @options = { case_sensitivity_strategy: :sensitive, } @existing_record_created = false @failure_reason = nil @failure_reason_when_negated = nil @attribute_setters = { existing_record: AttributeSetters.new, new_record: AttributeSetters.new, } end
Calls superclass method
Shoulda::Matchers::ActiveModel::ValidationMatcher::new
Public Instance Methods
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 352 def allow_blank @options[:allow_blank] = true self end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 343 def allow_nil @options[:allow_nil] = true self end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 328 def alternatives(values) @options[:alternatives] = values self end
@param values [String, Array<String>]
Alternative value(s) to use for testing uniqueness instead of using the `succ` operator on the existing value.
@return [ValidateUniquenessOfMatcher]
@example
it { should validate_uniqueness_of(:title).alternatives('Alternative Title') } it { should validate_uniqueness_of(:title).alternatives(['Title 1', 'Title 2']) }
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 333 def case_insensitive @options[:case_sensitivity_strategy] = :insensitive self end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 389 def does_not_match?(given_record) @given_record = given_record @all_records = model.all does_not_match_presence_of_scopes? || does_not_match_scopes_configuration? || does_not_match_uniqueness_without_scopes? || does_not_match_uniqueness_with_case_sensitivity_strategy? || does_not_match_uniqueness_with_scopes? || does_not_match_allow_nil? || does_not_match_allow_blank? ensure Uniqueness::TestModels.remove_all end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 357 def expects_to_allow_blank? @options[:allow_blank] == true end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 348 def expects_to_allow_nil? @options[:allow_nil] == true end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 338 def ignoring_case_sensitivity @options[:case_sensitivity_strategy] = :ignore self end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 373 def matches?(given_record) @given_record = given_record @all_records = model.all matches_presence_of_attribute? && matches_presence_of_scopes? && matches_scopes_configuration? && matches_uniqueness_without_scopes? && matches_uniqueness_with_case_sensitivity_strategy? && matches_uniqueness_with_scopes? && matches_allow_nil? && matches_allow_blank? ensure Uniqueness::TestModels.remove_all end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 314 def scoped_to(*scopes) @options[:scopes] = [*scopes].flatten.map(&:to_sym) self end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 361 def simple_description description = "validate that :#{@attribute} is" description << description_for_case_sensitive_qualifier description << ' unique' if @options[:scopes].present? description << " within the scope of #{inspected_expected_scopes}" end description end
Protected Instance Methods
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 414 def build_allow_or_disallow_value_matcher(args) super.tap do |matcher| matcher.failure_message_preface = method(:failure_message_preface) matcher.attribute_changed_value_message = method(:attribute_changed_value_message) end end
Calls superclass method
Shoulda::Matchers::ActiveModel::ValidationMatcher#build_allow_or_disallow_value_matcher
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 406 def failure_reason @failure_reason || super end
Calls superclass method
Shoulda::Matchers::ActiveModel::ValidationMatcher#failure_reason
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 410 def failure_reason_when_negated @failure_reason_when_negated || super end
Calls superclass method
Shoulda::Matchers::ActiveModel::ValidationMatcher#failure_reason_when_negated
Private Instance Methods
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 547 def actual_sets_of_scopes validations.map do |validation| Array.wrap(validation.options[:scope]).map(&:to_sym) end.reject(&:empty?) end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 897 def all_scopes_are_booleans? @options[:scopes].all? do |scope| @all_records.map(&scope).all? { |s| boolean_value?(s) } end end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 623 def arbitrary_non_blank_value non_blank_value = dummy_value_for(@attribute) limit = column_limit_for(@attribute) is_string_value = non_blank_value.is_a?(String) if is_string_value && limit && limit < non_blank_value.length 'x' * limit else non_blank_value end end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 1039 def attribute_changed_value_message <<-MESSAGE.strip As indicated in the message above, :#{last_attribute_setter_used_on_new_record.attribute_name} seems to be changing certain values as they are set, and this could have something to do with why this test is failing. If you or something else has overridden the writer method for this attribute to normalize values by changing their case in any way (for instance, ensuring that the attribute is always downcased), then try adding `ignoring_case_sensitivity` onto the end of the uniqueness matcher. Otherwise, you may need to write the test yourself, or do something different altogether. MESSAGE end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 960 def attribute_names_under_test [@attribute] + expected_scopes end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 672 def attribute_present_on_model? model.method_defined?("#{attribute}=") || model.columns_hash.key?(attribute.to_s) end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 1087 def attribute_setter_descriptions_for_new_record attribute_setters_for_new_record.map do |attribute_setter| same_as_existing = ( attribute_setter.value_written == existing_value_written ) description_for_attribute_setter( attribute_setter, same_as_existing: same_as_existing, ) end end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 951 def attribute_setter_for_existing_record @attribute_setters[:existing_record].last end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 955 def attribute_setters_for_new_record @attribute_setters[:new_record] + [last_attribute_setter_used_on_new_record] end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 916 def available_enum_values_for(scope, previous_value) new_record.defined_enums[scope.to_s].reject do |key, _| key == previous_value end end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 903 def boolean_value?(value) [true, false].include?(value) end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 964 def build_attribute_setter(record, attribute_name, value) Shoulda::Matchers::ActiveModel::AllowValueMatcher::AttributeSetter. new( matcher_name: :validate_uniqueness_of, object: record, attribute_name: attribute_name, value: value, ignore_interference_by_writer: ignore_interference_by_writer, ) end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 478 def build_failure_reason String.new('Expected the validation ').tap do |failure_reason_string| failure_reason_string << if expected_scopes.empty? 'not to be scoped to anything, ' else "to be scoped to #{inspected_expected_scopes}, " end if actual_sets_of_scopes.any? failure_reason_string << 'but it was scoped to ' failure_reason_string << "#{inspected_actual_scopes} instead." else failure_reason_string << 'but it was not scoped to anything.' end end end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 639 def build_new_record @new_record = existing_record.dup attribute_names_under_test.each do |attribute_name| set_attribute_on_new_record!( attribute_name, existing_record.public_send(attribute_name), ) end @new_record end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 424 def case_sensitivity_strategy @options[:case_sensitivity_strategy] end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 987 def column_for(scope) model.columns_hash[scope.to_s] end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 991 def column_limit_for(attribute) column_for(attribute).try(:limit) end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 604 def create_existing_record @given_record.tap do |existing_record| existing_record.save(validate: false) end rescue ::ActiveRecord::StatementInvalid => e raise ExistingRecordInvalid.create(underlying_exception: e) end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 907 def defined_as_enum?(scope) model.respond_to?(:defined_enums) && new_record.defined_enums[scope.to_s] end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 1054 def description_for_attribute_setter( attribute_setter, same_as_existing: nil ) description = "its :#{attribute_setter.attribute_name} to " if same_as_existing == false description << 'a different value, ' end description << Shoulda::Matchers::Util.inspect_value( attribute_setter.value_written, ) if attribute_setter.attribute_changed_value? description << ' (read back as ' description << Shoulda::Matchers::Util.inspect_value( attribute_setter.value_read, ) description << ')' end if same_as_existing == true description << ' as well' end description end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 437 def description_for_case_sensitive_qualifier case case_sensitivity_strategy when :sensitive ' case-sensitively' when :insensitive ' case-insensitively' else '' end end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 1083 def descriptions_for_attribute_setters_for_new_record attribute_setter_descriptions_for_new_record.to_sentence end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 576 def does_not_match_allow_blank? expects_to_allow_blank? && ( update_existing_record!('') && (@failure_reason = nil || disallows_value_of('', @expected_message)) ) end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 560 def does_not_match_allow_nil? expects_to_allow_nil? && ( update_existing_record!(nil) && (@failure_reason = nil || disallows_value_of(nil, @expected_message) ) ) end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 662 def does_not_match_presence_of_attribute? if attribute_present_on_model? @failure_reason = ":#{attribute} seems to be an attribute on #{model.name}." false else true end end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 700 def does_not_match_presence_of_scopes? if scopes_missing_on_model.any? true else inspected_scopes = scopes_present_on_model.map(&:inspect) @failure_reason = String.new.tap do |reason| reason << inspected_scopes.to_sentence reason << if inspected_scopes.many? ' seem to be attributes' else ' seems to be an attribute' end reason << " on #{model.name}." end false end end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 496 def does_not_match_scopes_configuration? if scopes_match? @failure_reason = String.new('Expected the validation ').tap do |failure_reason| if expected_scopes.empty? failure_reason << 'to be scoped to nothing, ' failure_reason << 'but it was scoped to ' failure_reason << "#{inspected_actual_scopes} instead." else failure_reason << 'not to be scoped to ' failure_reason << inspected_expected_scopes end end false else true end end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 776 def does_not_match_uniqueness_with_case_sensitivity_strategy? if should_test_case_sensitivity? @failure_reason = nil value = existing_value_read swapcased_value = value.swapcase if case_sensitivity_strategy == :sensitive disallows_value_of(swapcased_value, @expected_message) else if value == swapcased_value raise NonCaseSwappableValueError.create( model: model, attribute: @attribute, value: value, ) end allows_value_of(swapcased_value, @expected_message) end else true end end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 823 def does_not_match_uniqueness_with_scopes? expected_scopes.any? && !all_scopes_are_booleans? && expected_scopes.any? do |scope| setting_next_value_for(scope) do @failure_reason = nil disallows_value_of(existing_value_read, @expected_message) end end end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 743 def does_not_match_uniqueness_without_scopes? @failure_reason = nil if existing_value_read.blank? update_existing_record!(arbitrary_non_blank_value) end allows_value_of(existing_value_read, @expected_message) end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 861 def dummy_scalar_value_for(column) Shoulda::Matchers::Util.dummy_value_for(column.type) end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 851 def dummy_value_for(scope) column = column_for(scope) if column.respond_to?(:array) && column.array [dummy_scalar_value_for(column)] else dummy_scalar_value_for(column) end end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 1100 def existing_and_new_values_are_same? last_value_set_on_new_record == existing_value_written end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 583 def existing_record unless defined?(@existing_record) find_or_create_existing_record end @existing_record end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 975 def existing_value_read existing_record.public_send(@attribute) end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 979 def existing_value_written if attribute_setter_for_existing_record attribute_setter_for_existing_record.value_written else existing_value_read end end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 543 def expected_scopes Array.wrap(@options[:scopes]) end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 999 def failure_message_preface # rubocop:disable Metrics/MethodLength String.new.tap do |prefix| if @existing_record_created prefix << "After taking the given #{model.name}" if attribute_setter_for_existing_record prefix << ', setting ' prefix << description_for_attribute_setter( attribute_setter_for_existing_record, ) else prefix << ", whose :#{attribute} is " prefix << "‹#{existing_value_read.inspect}›" end prefix << ', and saving it as the existing record, then' elsif attribute_setter_for_existing_record prefix << "Given an existing #{model.name}," prefix << ' after setting ' prefix << description_for_attribute_setter( attribute_setter_for_existing_record, ) prefix << ', then' else prefix << "Given an existing #{model.name} whose :#{attribute}" prefix << ' is ' prefix << Shoulda::Matchers::Util.inspect_value( existing_value_read, ) prefix << ', after' end prefix << " making a new #{model.name} and setting " prefix << descriptions_for_attribute_setters_for_new_record prefix << ", the matcher expected the new #{model.name} to be" end end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 600 def find_existing_record model.first.presence end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 591 def find_or_create_existing_record @existing_record = find_existing_record unless @existing_record @existing_record = create_existing_record @existing_record_created = true end end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 635 def has_secure_password? Shoulda::Matchers::RailsShim.has_secure_password?(subject, @attribute) end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 524 def inspected_actual_scopes inspected_actual_sets_of_scopes.to_sentence( words_connector: ' and ', last_word_connector: ', and', ) end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 531 def inspected_actual_sets_of_scopes inspected_sets_of_scopes = actual_sets_of_scopes.map do |scopes| scopes.map(&:inspect) end if inspected_sets_of_scopes.many? inspected_sets_of_scopes.map { |x| "(#{x.to_sentence})" } else inspected_sets_of_scopes.map(&:to_sentence) end end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 520 def inspected_expected_scopes expected_scopes.map(&:inspect).to_sentence end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 1104 def last_attribute_setter_used_on_new_record last_submatcher_run.last_attribute_setter_used end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 1108 def last_value_set_on_new_record last_submatcher_run.last_value_set end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 569 def matches_allow_blank? !expects_to_allow_blank? || ( update_existing_record!('') && allows_value_of('', @expected_message) ) end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 553 def matches_allow_nil? !expects_to_allow_nil? || ( update_existing_record!(nil) && allows_value_of(nil, @expected_message) ) end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 652 def matches_presence_of_attribute? if attribute_present_on_model? true else @failure_reason = ":#{attribute} does not seem to be an attribute on #{model.name}." false end end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 677 def matches_presence_of_scopes? if scopes_missing_on_model.none? true else inspected_scopes = scopes_missing_on_model.map(&:inspect) @failure_reason = String.new.tap do |reason| reason << inspected_scopes.to_sentence reason << if inspected_scopes.many? ' do not seem to be attributes' else ' does not seem to be an attribute' end reason << " on #{model.name}." end false end end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 454 def matches_scopes_configuration? if scopes_match? true else @failure_reason = String.new('Expected the validation ').tap do |failure_reason_string| failure_reason_string << if expected_scopes.empty? 'not to be scoped to anything, ' else "to be scoped to #{inspected_expected_scopes}, " end if actual_sets_of_scopes.any? failure_reason_string << 'but it was scoped to ' failure_reason_string << "#{inspected_actual_scopes} instead." else failure_reason_string << 'but it was not scoped to anything.' end end false end end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 753 def matches_uniqueness_with_case_sensitivity_strategy? if should_test_case_sensitivity? value = existing_value_read swapcased_value = value.swapcase if case_sensitivity_strategy == :sensitive if value == swapcased_value raise NonCaseSwappableValueError.create( model: model, attribute: @attribute, value: value, ) end allows_value_of(swapcased_value, @expected_message) else disallows_value_of(swapcased_value, @expected_message) end else true end end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 813 def matches_uniqueness_with_scopes? expected_scopes.none? || all_scopes_are_booleans? || expected_scopes.all? do |scope| setting_next_value_for(scope) do allows_value_of(existing_value_read, @expected_message) end end end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 735 def matches_uniqueness_without_scopes? if existing_value_read.blank? update_existing_record!(arbitrary_non_blank_value) end disallows_value_of(existing_value_read, @expected_message) end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 995 def model @given_record.class end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 807 def model_class?(model_name) model_name.constantize.ancestors.include?(::ActiveRecord::Base) rescue NameError false end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 428 def new_record unless defined?(@new_record) build_new_record end @new_record end
Also aliased as: subject
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 873 def next_scalar_value_for(scope, previous_value) column = column_for(scope) if column.type == :uuid SecureRandom.uuid elsif defined_as_enum?(scope) available_values = available_enum_values_for(scope, previous_value) available_values.keys.last elsif polymorphic_type_attribute?(scope, previous_value) Uniqueness::TestModels.create(previous_value).to_s elsif @options[:alternatives] && scope == @attribute alternatives = Array.wrap(@options[:alternatives]) alternatives.first elsif previous_value.respond_to?(:next) previous_value.next elsif previous_value.respond_to?(:to_datetime) previous_value.to_datetime.in(60).next elsif boolean_value?(previous_value) !previous_value else previous_value.to_s.next end end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 865 def next_value_for(scope, previous_value) if previous_value.is_a?(Array) [next_scalar_value_for(scope, previous_value[0])] else next_scalar_value_for(scope, previous_value) end end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 912 def polymorphic_type_attribute?(scope, previous_value) scope.to_s =~ /_type$/ && model_class?(previous_value) end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 515 def scopes_match? actual_sets_of_scopes.empty? && expected_scopes.empty? || actual_sets_of_scopes.any? { |scopes| scopes == expected_scopes } end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 729 def scopes_missing_on_model @_scopes_missing_on_model ||= expected_scopes.reject do |scope| model.method_defined?("#{scope}=") end end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 723 def scopes_present_on_model @_scopes_present_on_model ||= expected_scopes.select do |scope| model.method_defined?("#{scope}=") end end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 922 def set_attribute_on!(record_type, record, attribute_name, value) attribute_setter = build_attribute_setter( record, attribute_name, value, ) attribute_setter.set! @attribute_setters[record_type] << attribute_setter end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 933 def set_attribute_on_existing_record!(attribute_name, value) set_attribute_on!( :existing_record, existing_record, attribute_name, value, ) end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 942 def set_attribute_on_new_record!(attribute_name, value) set_attribute_on!( :new_record, new_record, attribute_name, value, ) end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 834 def setting_next_value_for(scope) previous_value = @all_records.map(&scope).compact.max next_value = if previous_value.blank? dummy_value_for(scope) else next_value_for(scope, previous_value) end set_attribute_on_new_record!(scope, next_value) yield ensure set_attribute_on_new_record!(scope, previous_value) end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 801 def should_test_case_sensitivity? case_sensitivity_strategy != :ignore && existing_value_read.respond_to?(:swapcase) && !existing_value_read.empty? end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 612 def update_existing_record!(value) if existing_value_read != value set_attribute_on_existing_record!(@attribute, value) # It would be nice if we could ensure that the record was valid, # but that would break users' existing tests existing_record.save(validate: false) end true end
Source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 448 def validations model.validators_on(@attribute).select do |validator| validator.is_a?(::ActiveRecord::Validations::UniquenessValidator) end end