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
does_not_match?(given_record) click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 339
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
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] == true
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] == true
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

  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
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.map(&:to_sym)
  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 364
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 356
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 360
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 478
def actual_sets_of_scopes
  validations.map do |validation|
    Array.wrap(validation.options[:scope]).map(&:to_sym)
  end.reject(&:empty?)
end
all_scopes_are_booleans?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 831
def all_scopes_are_booleans?
  @options[:scopes].all? do |scope|
    @all_records.map(&scope).all? { |s| boolean_value?(s) }
  end
end
arbitrary_non_blank_value() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 558
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
attribute_changed_value_message() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 976
        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
attribute_names_under_test() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 894
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 607
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 1021
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 885
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 889
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 850
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 837
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 898
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 574
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 374
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 920
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 924
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 539
def create_existing_record
  @given_record.tap do |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 841
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 991
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 387
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 1017
def descriptions_for_attribute_setters_for_new_record
  attribute_setter_descriptions_for_new_record.to_sentence
end
does_not_match_allow_blank?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 505
def does_not_match_allow_blank?
  expects_to_allow_blank? && (
    update_existing_record!('') &&
    (@failure_reason = nil || disallows_value_of('', @expected_message))
  )
end
does_not_match_allow_nil?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 491
def does_not_match_allow_nil?
  expects_to_allow_nil? && (
    update_existing_record!(nil) &&
    (@failure_reason = nil || disallows_value_of(nil, @expected_message))
  )
end
does_not_match_presence_of_attribute?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 597
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
does_not_match_presence_of_scopes?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 636
def does_not_match_presence_of_scopes?
  if scopes_missing_on_model.any?
    true
  else
    inspected_scopes = scopes_present_on_model.map(&:inspect)

    reason = ''

    reason << inspected_scopes.to_sentence

    if inspected_scopes.many?
      reason << " seem to be attributes"
    else
      reason << " seems to be an attribute"
    end

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

    @failure_reason = reason

    false
  end
end
does_not_match_scopes_configuration?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 427
def does_not_match_scopes_configuration?
  if scopes_match?
    @failure_reason = 'Expected the validation '

    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

    false
  else
    true
  end
end
does_not_match_uniqueness_with_case_sensitivity_strategy?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 713
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
does_not_match_uniqueness_with_scopes?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 760
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
does_not_match_uniqueness_without_scopes?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 680
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
dummy_scalar_value_for(column) click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 798
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 788
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
existing_and_new_values_are_same?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 1034
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 512
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 908
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 912
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 474
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 932
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 529
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 520
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 570
def has_secure_password?
  Shoulda::Matchers::RailsShim.has_secure_password?(subject, @attribute)
end
inspected_actual_scopes() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 455
def inspected_actual_scopes
  inspected_actual_sets_of_scopes.to_sentence(
    words_connector: ' and ',
    last_word_connector: ', and'
  )
end
inspected_actual_sets_of_scopes() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 462
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 451
def inspected_expected_scopes
  expected_scopes.map(&:inspect).to_sentence
end
last_attribute_setter_used_on_new_record() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 1038
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 1042
def last_value_set_on_new_record
  last_submatcher_run.last_value_set
end
matches_allow_blank?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 498
def matches_allow_blank?
  !expects_to_allow_blank? || (
    update_existing_record!('') &&
    allows_value_of('', @expected_message)
  )
end
matches_allow_nil?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 484
def matches_allow_nil?
  !expects_to_allow_nil? || (
    update_existing_record!(nil) &&
    allows_value_of(nil, @expected_message)
  )
end
matches_presence_of_attribute?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 587
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
matches_presence_of_scopes?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 612
def matches_presence_of_scopes?
  if scopes_missing_on_model.none?
    true
  else
    inspected_scopes = scopes_missing_on_model.map(&:inspect)

    reason = ''

    reason << inspected_scopes.to_sentence

    if inspected_scopes.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
matches_scopes_configuration?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 404
def matches_scopes_configuration?
  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.any?
      @failure_reason << 'but it was scoped to '
      @failure_reason << "#{inspected_actual_scopes} instead."
    else
      @failure_reason << 'but it was not scoped to anything.'
    end

    false
  end
end
matches_uniqueness_with_case_sensitivity_strategy?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 690
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
matches_uniqueness_with_scopes?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 750
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
matches_uniqueness_without_scopes?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 672
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
model() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 928
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 744
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 378
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 810
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 802
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 846
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 446
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 666
def scopes_missing_on_model
  @_missing_scopes ||= expected_scopes.select do |scope|
    !model.method_defined?("#{scope}=")
  end
end
scopes_present_on_model() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 660
def scopes_present_on_model
  @_present_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 856
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 867
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 876
def set_attribute_on_new_record!(attribute_name, value)
  set_attribute_on!(
    :new_record,
    new_record,
    attribute_name,
    value
  )
end
setting_next_value_for(scope) { || ... } click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 771
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
should_test_case_sensitivity?() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 738
def should_test_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 547
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
validations() click to toggle source
# File lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb, line 398
def validations
  model._validators[@attribute].select do |validator|
    validator.is_a?(::ActiveRecord::Validations::UniquenessValidator)
  end
end