Fixes uniqueness matcher for enum columns
In Rails 4.1, if the scope from a validates_uniqueness_of matcher is an enum, next_value won't get the correct value, then tests will fail even that validation works. This adds a way to check if the scoped attribute is an enum, and correctly get the next value.
This commit is contained in:
parent
ee2eca4098
commit
d4b1fc2fa1
2
NEWS.md
2
NEWS.md
|
@ -32,6 +32,8 @@
|
|||
* Fix `delegate_method` so that it does not stub the target method forever,
|
||||
returning it to its original implementation after the match ends.
|
||||
|
||||
* Fix `validate_uniqueness_of` to work with Rails 4.1 enum columns.
|
||||
|
||||
# 2.6.0
|
||||
|
||||
* The boolean argument to `have_db_index`'s `unique` option is now optional, for
|
||||
|
|
|
@ -173,7 +173,12 @@ module Shoulda # :nodoc:
|
|||
previous_value ||= correct_type_for_column(@subject.class.columns_hash[scope.to_s])
|
||||
|
||||
next_value =
|
||||
if previous_value.respond_to?(:next)
|
||||
if @subject.class.respond_to?(:defined_enums) && @subject.defined_enums[scope.to_s]
|
||||
available_values = @subject.defined_enums[scope.to_s].reject do |key, _|
|
||||
key == previous_value
|
||||
end
|
||||
available_values.keys.last
|
||||
elsif previous_value.respond_to?(:next)
|
||||
previous_value.next
|
||||
elsif previous_value.respond_to?(:to_datetime)
|
||||
previous_value.to_datetime.next
|
||||
|
|
|
@ -122,6 +122,40 @@ describe Shoulda::Matchers::ActiveModel::ValidateUniquenessOfMatcher do
|
|||
not_to matcher.scoped_to(:fake)
|
||||
end
|
||||
|
||||
if rails_gte_4_1?
|
||||
context 'when the scoped attribute is an enum' do
|
||||
it 'accepts' do
|
||||
expect(validating_scoped_uniqueness_with_enum([:scope1], scope1: 0)).
|
||||
to matcher.scoped_to(:scope1)
|
||||
end
|
||||
|
||||
context 'with a nil value' do
|
||||
it 'accepts' do
|
||||
expect(validating_scoped_uniqueness_with_enum([:scope1], scope1: nil)).
|
||||
to matcher.scoped_to(:scope1)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when too narrow of a scope is specified' do
|
||||
it 'rejects' do
|
||||
expect(validating_scoped_uniqueness_with_enum_with_two_scopes).
|
||||
not_to matcher.scoped_to(:scope1, :scope2, :other)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when too broad of a scope is specified' do
|
||||
it 'rejects' do
|
||||
expect(validating_scoped_uniqueness_with_enum_with_two_scopes).
|
||||
not_to matcher.scoped_to(:scope1)
|
||||
end
|
||||
end
|
||||
|
||||
def validating_scoped_uniqueness_with_enum_with_two_scopes
|
||||
validating_scoped_uniqueness_with_enum([:scope1, :scope2], scope1: 0, scope2: 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the scoped attribute is a date' do
|
||||
it "accepts" do
|
||||
expect(validating_scoped_uniqueness([:scope1], :date, scope1: Date.today)).
|
||||
|
@ -250,6 +284,14 @@ describe Shoulda::Matchers::ActiveModel::ValidateUniquenessOfMatcher do
|
|||
model
|
||||
end
|
||||
|
||||
def validating_scoped_uniqueness_with_enum(*args)
|
||||
attributes = args.extract_options!
|
||||
model = define_scoped_model(*args)
|
||||
model.enum scope1: [:foo, :bar]
|
||||
create_existing_record(attributes)
|
||||
model.new
|
||||
end
|
||||
|
||||
def validating_scoped_uniqueness_with_conflicting_next(*args)
|
||||
attributes = args.extract_options!
|
||||
model = define_scoped_model(*args).new
|
||||
|
|
Loading…
Reference in New Issue