class Shoulda::Matchers::ActiveRecord::ValidateUniquenessOfMatcher

@private

Public Class Methods

new(attribute) click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 263
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

Public Instance Methods

allow_blank() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 302
def allow_blank
  @options[:allow_blank] = true
  self
end
allow_nil() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 293
def allow_nil
  @options[:allow_nil] = true
  self
end
case_insensitive() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 283
def case_insensitive
  @options[:case_sensitivity_strategy] = :insensitive
  self
end
expects_to_allow_blank?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 307
def expects_to_allow_blank?
  @options[:allow_blank]
end
expects_to_allow_nil?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 298
def expects_to_allow_nil?
  @options[:allow_nil]
end
ignoring_case_sensitivity() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 288
def ignoring_case_sensitivity
  @options[:case_sensitivity_strategy] = :ignore
  self
end
matches?(given_record) click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 323
def matches?(given_record)
  @given_record = given_record
  @all_records = model.all

  validate_attribute_present_on_model? &&
    validate_scopes_present_on_model? &&
    validate_scopes_match? &&
    validate_two_records_with_same_non_blank_value_cannot_coexist? &&
    validate_case_sensitivity? &&
    validate_after_scope_change? &&
    allows_nil? &&
    allows_blank?
ensure
  Uniqueness::TestModels.remove_all
end
scoped_to(*scopes) click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 278
def scoped_to(*scopes)
  @options[:scopes] = [*scopes].flatten
  self
end
simple_description() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 311
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

build_allow_or_disallow_value_matcher(args) click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 349
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
failure_reason() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 341
def failure_reason
  @failure_reason || super
end
failure_reason_when_negated() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 345
def failure_reason_when_negated
  @failure_reason_when_negated || super
end

Private Instance Methods

actual_sets_of_scopes() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 444
def actual_sets_of_scopes
  validations.map do |validation|
    Array.wrap(validation.options[:scope])
  end.reject(&:empty?)
end
all_scopes_are_booleans?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 713
def all_scopes_are_booleans?
  @options[:scopes].all? do |scope|
    @all_records.map(&scope).all? { |s| boolean_value?(s) }
  end
end
all_scopes_present_on_model?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 587
def all_scopes_present_on_model?
  scopes_missing_on_model.none?
end
allows_blank?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 459
def allows_blank?
  if expects_to_allow_blank?
    update_existing_record!('')
    allows_value_of('', @expected_message)
  else
    true
  end
end
allows_nil?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 450
def allows_nil?
  if expects_to_allow_nil?
    update_existing_record!(nil)
    allows_value_of(nil, @expected_message)
  else
    true
  end
end
arbitrary_non_blank_value() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 520
def arbitrary_non_blank_value
  limit = column_limit_for(@attribute)
  non_blank_value = 'an arbitrary value'

  if limit && limit < non_blank_value.length
    'x' * limit
  else
    non_blank_value
  end
end
attribute_changed_value_message() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 858
        def attribute_changed_value_message
          "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.
".strip
        end
attribute_names_under_test() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 776
def attribute_names_under_test
  [@attribute] + expected_scopes
end
attribute_present_on_model?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 560
def attribute_present_on_model?
  model.method_defined?("#{attribute}=") ||
    model.columns_hash.key?(attribute.to_s)
end
attribute_setter_descriptions_for_new_record() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 903
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
attribute_setter_for_existing_record() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 767
def attribute_setter_for_existing_record
  @attribute_setters[:existing_record].last
end
attribute_setters_for_new_record() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 771
def attribute_setters_for_new_record
  @attribute_setters[:new_record] +
    [last_attribute_setter_used_on_new_record]
end
available_enum_values_for(scope, previous_value) click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 732
def available_enum_values_for(scope, previous_value)
  new_record.defined_enums[scope.to_s].reject do |key, _|
    key == previous_value
  end
end
boolean_value?(value) click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 719
def boolean_value?(value)
  [true, false].include?(value)
end
build_attribute_setter(record, attribute_name, value) click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 780
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
build_new_record() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 537
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
case_sensitivity_strategy() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 359
def case_sensitivity_strategy
  @options[:case_sensitivity_strategy]
end
column_for(scope) click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 802
def column_for(scope)
  model.columns_hash[scope.to_s]
end
column_limit_for(attribute) click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 806
def column_limit_for(attribute)
  column_for(attribute).try(:limit)
end
create_existing_record() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 495
def create_existing_record
  @given_record.tap do |existing_record|
    ensure_secure_password_set(existing_record)
    existing_record.save(validate: false)
  end
rescue ::ActiveRecord::StatementInvalid => error
  raise ExistingRecordInvalid.create(underlying_exception: error)
end
defined_as_enum?(scope) click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 723
def defined_as_enum?(scope)
  model.respond_to?(:defined_enums) &&
    new_record.defined_enums[scope.to_s]
end
description_for_attribute_setter(attribute_setter, same_as_existing: nil) click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 873
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
description_for_case_sensitive_qualifier() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 372
def description_for_case_sensitive_qualifier
  case case_sensitivity_strategy
  when :sensitive
    ' case-sensitively'
  when :insensitive
    ' case-insensitively'
  else
    ''
  end
end
descriptions_for_attribute_setters_for_new_record() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 899
def descriptions_for_attribute_setters_for_new_record
  attribute_setter_descriptions_for_new_record.to_sentence
end
dummy_scalar_value_for(column) click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 680
def dummy_scalar_value_for(column)
  Shoulda::Matchers::Util.dummy_value_for(column.type)
end
dummy_value_for(scope) click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 670
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
ensure_secure_password_set(instance) click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 504
def ensure_secure_password_set(instance)
  if has_secure_password?
    instance.password = "password"
    instance.password_confirmation = "password"
  end
end
existing_and_new_values_are_same?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 916
def existing_and_new_values_are_same?
  last_value_set_on_new_record == existing_value_written
end
existing_record() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 468
def existing_record
  unless defined?(@existing_record)
    find_or_create_existing_record
  end

  @existing_record
end
existing_value_read() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 790
def existing_value_read
  existing_record.public_send(@attribute)
end
existing_value_written() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 794
def existing_value_written
  if attribute_setter_for_existing_record
    attribute_setter_for_existing_record.value_written
  else
    existing_value_read
  end
end
expected_scopes() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 440
def expected_scopes
  Array.wrap(@options[:scopes])
end
failure_message_preface() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 814
def failure_message_preface
  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"
  else
    if 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
  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"

  prefix
end
find_existing_record() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 485
def find_existing_record
  record = model.first

  if record.present?
    record
  else
    nil
  end
end
find_or_create_existing_record() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 476
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
has_secure_password?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 531
def has_secure_password?
  model.ancestors.map(&:to_s).include?(
    'ActiveModel::SecurePassword::InstanceMethodsOnActivation'
  )
end
inspected_actual_scopes() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 421
def inspected_actual_scopes
  inspected_actual_sets_of_scopes.to_sentence(
    words_connector: " or ",
    last_word_connector: ", or"
  )
end
inspected_actual_sets_of_scopes() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 428
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
inspected_expected_scopes() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 417
def inspected_expected_scopes
  expected_scopes.map(&:inspect).to_sentence
end
inspected_scopes_missing_on_model() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 597
def inspected_scopes_missing_on_model
  scopes_missing_on_model.map(&:inspect)
end
last_attribute_setter_used_on_new_record() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 920
def last_attribute_setter_used_on_new_record
  last_submatcher_run.last_attribute_setter_used
end
last_value_set_on_new_record() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 924
def last_value_set_on_new_record
  last_submatcher_run.last_value_set
end
model() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 810
def model
  @given_record.class
end
model_class?(model_name) click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 638
def model_class?(model_name)
  model_name.constantize.ancestors.include?(::ActiveRecord::Base)
rescue NameError
  false
end
new_record() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 363
def new_record
  unless defined?(@new_record)
    build_new_record
  end

  @new_record
end
Also aliased as: subject
next_scalar_value_for(scope, previous_value) click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 692
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 previous_value.respond_to?(:next)
    previous_value.next
  elsif previous_value.respond_to?(:to_datetime)
    previous_value.to_datetime.next
  elsif boolean_value?(previous_value)
    !previous_value
  else
    previous_value.to_s.next
  end
end
next_value_for(scope, previous_value) click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 684
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
polymorphic_type_attribute?(scope, previous_value) click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 728
def polymorphic_type_attribute?(scope, previous_value)
  scope.to_s =~ /_type$/ && model_class?(previous_value)
end
scopes_match?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 412
def scopes_match?
  actual_sets_of_scopes.empty? && expected_scopes.empty? ||
    actual_sets_of_scopes.any? { |scopes| scopes == expected_scopes }
end
scopes_missing_on_model() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 591
def scopes_missing_on_model
  @_missing_scopes ||= expected_scopes.select do |scope|
    !model.method_defined?("#{scope}=")
  end
end
set_attribute_on!(record_type, record, attribute_name, value) click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 738
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
set_attribute_on_existing_record!(attribute_name, value) click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 749
def set_attribute_on_existing_record!(attribute_name, value)
  set_attribute_on!(
    :existing_record,
    existing_record,
    attribute_name,
    value
  )
end
set_attribute_on_new_record!(attribute_name, value) click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 758
def set_attribute_on_new_record!(attribute_name, value)
  set_attribute_on!(
    :new_record,
    new_record,
    attribute_name,
    value
  )
end
should_validate_case_sensitivity?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 632
def should_validate_case_sensitivity?
  case_sensitivity_strategy != :ignore &&
    existing_value_read.respond_to?(:swapcase) &&
    !existing_value_read.empty?
end
subject()
Alias for: new_record
update_existing_record!(value) click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 511
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
end
validate_after_scope_change?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 644
def validate_after_scope_change?
  if expected_scopes.empty? || all_scopes_are_booleans?
    true
  else
    expected_scopes.all? do |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)

      if allows_value_of(existing_value_read, @expected_message)
        set_attribute_on_new_record!(scope, previous_value)
        true
      else
        false
      end
    end
  end
end
validate_attribute_present_on_model?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 550
def validate_attribute_present_on_model?
  if attribute_present_on_model?
    true
  else
    @failure_reason =
      ":#{attribute} does not seem to be an attribute on #{model.name}."
    false
  end
end
validate_case_sensitivity?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 609
def validate_case_sensitivity?
  if should_validate_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
validate_scopes_match?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 389
def validate_scopes_match?
  if scopes_match?
    true
  else
    @failure_reason = 'Expected the validation'

    if expected_scopes.empty?
      @failure_reason << ' not to be scoped to anything'
    else
      @failure_reason << " to be scoped to #{inspected_expected_scopes}"
    end

    if actual_sets_of_scopes.empty?
      @failure_reason << ', but it was not scoped to anything.'
    else
      @failure_reason << ', but it was scoped to '
      @failure_reason << "#{inspected_actual_scopes} instead."
    end

    false
  end
end
validate_scopes_present_on_model?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 565
def validate_scopes_present_on_model?
  if all_scopes_present_on_model?
    true
  else
    reason = ''

    reason << inspected_scopes_missing_on_model.to_sentence

    if inspected_scopes_missing_on_model.many?
      reason << " do not seem to be attributes"
    else
      reason << " does not seem to be an attribute"
    end

    reason << " on #{model.name}."

    @failure_reason = reason

    false
  end
end
validate_two_records_with_same_non_blank_value_cannot_coexist?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 601
def validate_two_records_with_same_non_blank_value_cannot_coexist?
  if existing_value_read.blank?
    update_existing_record!(arbitrary_non_blank_value)
  end

  disallows_value_of(existing_value_read, @expected_message)
end
validations() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 383
def validations
  model._validators[@attribute].select do |validator|
    validator.is_a?(::ActiveRecord::Validations::UniquenessValidator)
  end
end