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:
parent
74fa081ef5
commit
81034eaf3d
3 changed files with 45 additions and 13 deletions
10
NEWS.md
10
NEWS.md
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Reference in a new issue