1
0
Fork 0
mirror of https://github.com/thoughtbot/shoulda-matchers.git synced 2022-11-09 12:01:38 -05:00

Uniqueness: Support UUID columns that end in "f"

This commit fixes the uniqueness matcher so that when qualified with
`scoped_to` and one of the scopes is a UUID column that happens to end
in an "f", the matcher is able to generate a proper next value during
testing and doesn't error.
This commit is contained in:
Elliot Winkler 2015-02-09 16:40:52 -07:00
parent 74fa081ef5
commit 81034eaf3d
3 changed files with 45 additions and 13 deletions

10
NEWS.md
View file

@ -21,6 +21,16 @@
* `set_session['key'].to(nil)` will no longer pass when the key in question * `set_session['key'].to(nil)` will no longer pass when the key in question
has not been set yet. has not been set yet.
### Bug fixes
* So far the tests for the gem have been running against only SQLite. Now they
run against PostgreSQL, too. As a result we were able to fix some
Postgres-related bugs:
* Fix `validate_uniqueness_of` + `scoped_to` so that when one of the scope
attributes is a UUID column that ends in an "f", the matcher is able to
generate a proper "next" value without erroring.
# 2.8.0 # 2.8.0
### Deprecations ### Deprecations

View file

@ -393,11 +393,14 @@ module Shoulda
end end
def correct_type_for_column(column) def correct_type_for_column(column)
if column.type == :string column = column_for(scope)
case column.type
when :string
'0' '0'
elsif column.type == :datetime when :datetime
DateTime.now DateTime.now
elsif column.type == :uuid when :uuid
SecureRandom.uuid SecureRandom.uuid
else else
0 0
@ -405,10 +408,14 @@ module Shoulda
end end
def next_value_for(scope, previous_value) def next_value_for(scope, previous_value)
if @subject.class.respond_to?(:defined_enums) && @subject.defined_enums[scope.to_s] 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 = available_enum_values_for(scope, previous_value)
available_values.keys.last available_values.keys.last
elsif scope.to_s =~ /_type$/ && model_class?(previous_value) elsif polymorphic_type_attribute?(scope, previous_value)
Uniqueness::TestModels.create(previous_value).to_s Uniqueness::TestModels.create(previous_value).to_s
elsif previous_value.respond_to?(:next) elsif previous_value.respond_to?(:next)
previous_value.next previous_value.next
@ -419,16 +426,21 @@ module Shoulda
end end
end end
def defined_as_enum?(scope)
@subject.class.respond_to?(:defined_enums) &&
@subject.defined_enums[scope.to_s]
end
def polymorphic_type_attribute?(scope, previous_value)
scope.to_s =~ /_type$/ && model_class?(previous_value)
end
def available_enum_values_for(scope, previous_value) def available_enum_values_for(scope, previous_value)
@subject.defined_enums[scope.to_s].reject do |key, _| @subject.defined_enums[scope.to_s].reject do |key, _|
key == previous_value key == previous_value
end end
end end
def class_name
@subject.class.name
end
def existing_value def existing_value
value = existing_record.__send__(@attribute) value = existing_record.__send__(@attribute)
if @options[:case_insensitive] && value.respond_to?(:swapcase!) if @options[:case_insensitive] && value.respond_to?(:swapcase!)
@ -436,6 +448,14 @@ module Shoulda
end end
value value
end end
def class_name
@subject.class.name
end
def column_for(scope)
@subject.class.columns_hash[scope.to_s]
end
end end
end end
end end

View file

@ -35,8 +35,8 @@ describe Shoulda::Matchers::ActiveRecord::ValidateUniquenessOfMatcher, type: :mo
context "when more than one record exists that has the next version of the attribute's value" do context "when more than one record exists that has the next version of the attribute's value" do
it 'accepts' do it 'accepts' do
value1 = dummy_value_for(value_type) value1 = dummy_value_for(value_type)
value2 = next_version_of(value1) value2 = next_version_of(value1, value_type)
value3 = next_version_of(value2) value3 = next_version_of(value2, value_type)
model = define_model_validating_uniqueness( model = define_model_validating_uniqueness(
scopes: [ build_attribute(name: :scope) ], scopes: [ build_attribute(name: :scope) ],
) )
@ -633,8 +633,10 @@ describe Shoulda::Matchers::ActiveRecord::ValidateUniquenessOfMatcher, type: :mo
end end
end end
def next_version_of(value) def next_version_of(value, value_type)
if value.is_a?(Time) if value_type == :uuid
SecureRandom.uuid
elsif value_type == :time
value + 1 value + 1
elsif value.respond_to?(:next) elsif value.respond_to?(:next)
value.next value.next