class Shoulda::ActiveRecord::Matchers::ValidateUniquenessOfMatcher

:nodoc:

def case_insensitive

def case_insensitive
  @case_insensitive = true
  self
end

def class_name

def class_name
  @subject.class.name
end

def description

def description
  result = "require "
  result << "case sensitive " unless @case_insensitive
  result << "unique value for #{@attribute}"
  result << " scoped to #{@scopes.join(', ')}" unless @scopes.blank?
  result
end

def existing_value

def existing_value
  value = @existing.send(@attribute)
  value.swapcase! if @case_insensitive && value.respond_to?(:swapcase!)
  value
end

def find_existing

def find_existing
  if @existing = @subject.class.find(:first)
    true
  else
    @failure_message = "Can't find first #{class_name}"
    false
  end
end

def initialize(attribute)

def initialize(attribute)
  @attribute = attribute
end

def matches?(subject)

def matches?(subject)
  @subject = subject.class.new
  @expected_message ||= :taken
  find_existing && 
    set_scoped_attributes && 
    validate_attribute &&
    validate_after_scope_change
end

def scoped_to(*scopes)

def scoped_to(*scopes)
  @scopes = [*scopes].flatten
  self
end

def set_scoped_attributes

def set_scoped_attributes
  unless @scopes.blank?
    @scopes.each do |scope|
      setter = :"#{scope}="
      unless @subject.respond_to?(setter)
        @failure_message =
          "#{class_name} doesn't seem to have a #{scope} attribute."
        return false
      end
      @subject.send("#{scope}=", @existing.send(scope))
    end
  end
  true
end

def validate_after_scope_change

could actually find all values for scope and create a unique
to a value that's already taken. An alternative implementation
TODO: There is a chance that we could change the scoped field
def validate_after_scope_change
  if @scopes.blank?
    true
  else
    @scopes.all? do |scope|
      previous_value = @existing.send(scope)
      # Assume the scope is a foreign key if the field is nil
      previous_value ||= 0
      next_value = previous_value.next
      @subject.send("#{scope}=", next_value)
      if allows_value_of(existing_value, @expected_message)
        @negative_failure_message << 
          " (with different value of #{scope})"
        true
      else
        @failure_message << " (with different value of #{scope})"
        false
      end
    end
  end
end

def validate_attribute

def validate_attribute
  disallows_value_of(existing_value, @expected_message)
end

def with_message(message)

def with_message(message)
  @expected_message = message
  self
end