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
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