Skip to content

Commit

Permalink
Uniqueness: Fix default behavior for case-insensitive models
Browse files Browse the repository at this point in the history
If you have a model that has a uniqueness validation using
`case_sensitive: false`, and you are testing against but do not qualify
the matcher with `case_insensitive`, then the matcher will pass
unexpectedly. Take this model for instance:

    class Product < ActiveRecord::Base
      validates_uniqueness_of :name, case_sensitive: false
    end

Currently, the following test passes. With this commit, it will now
(correctly) fail:

    describe Product do
      it { is_expected.to validate_uniqueness_of(:name) }
    end
  • Loading branch information
Anthony Navarre + Elliot Winkler authored and mcmire committed Feb 17, 2015
1 parent c3482d1 commit 57a1922
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ def matches?(subject)

set_scoped_attributes &&
validate_everything_except_duplicate_nils_or_blanks? &&
validate_case_sensitivity? &&
validate_after_scope_change? &&
allows_nil? &&
allows_blank?
Expand Down Expand Up @@ -353,6 +354,22 @@ def validate_everything_except_duplicate_nils_or_blanks?
disallows_value_of(existing_value, @expected_message)
end

def validate_case_sensitivity?
value = existing_value

if value.respond_to?(:swapcase)
swapcased_value = value.swapcase

if @options[:case_insensitive]
disallows_value_of(swapcased_value, @expected_message)
else
allows_value_of(swapcased_value, @expected_message)
end
else
true
end
end

def create_record_with_value
@existing_record = create_record_in_database
end
Expand Down Expand Up @@ -462,11 +479,7 @@ def available_enum_values_for(scope, previous_value)
end

def existing_value
value = existing_record.__send__(@attribute)
if @options[:case_insensitive] && value.respond_to?(:swapcase!)
value.swapcase!
end
value
existing_record.__send__(@attribute)
end

def class_name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@
end
end

context 'when the model has a case-sensitive validation on a string attribute' do
context 'when the model has a case-sensitive validation' do
context 'when case_insensitive is not specified' do
it 'accepts' do
record = build_record_validating_uniqueness(
Expand All @@ -416,6 +416,30 @@
end
end

context 'when the model has a case-insensitive validation' do
context 'when case_insensitive is not specified' do
it 'rejects' do
record = build_record_validating_uniqueness(
attribute_type: :string,
validation_options: { case_sensitive: false }
)

expect(record).not_to validate_uniqueness
end
end

context 'when case_insensitive is specified' do
it 'accepts' do
record = build_record_validating_uniqueness(
attribute_type: :string,
validation_options: { case_sensitive: false }
)

expect(record).to validate_uniqueness.case_insensitive
end
end
end

context 'when the validation is declared with allow_nil' do
context 'given a new record whose attribute is nil' do
it 'accepts' do
Expand Down

0 comments on commit 57a1922

Please sign in to comment.