Change `validate_uniqueness_of_matcher` to give non-null columns default values
Previously, if a model had an attribute that mapped to a non-nullable database column that was not under test the matcher would fail with an SQL error like: examples.column may not be NULL #... With this change the matcher attempts to provide a default value for all non-nullable, non-primary attributes. This should avoid the above error in simple cases.
This commit is contained in:
parent
5b44edf8b3
commit
561ac3e2f0
3
NEWS.md
3
NEWS.md
|
@ -22,6 +22,9 @@
|
|||
* You cannot test that your attribute allows nil (`.in_array([nil])`) if
|
||||
the column does not allow null values.
|
||||
|
||||
* Change `validate_uniqueness_of(...)` so that it provides default values for
|
||||
non-nullable attributes.
|
||||
|
||||
# v 2.5.0
|
||||
|
||||
* Fix Rails/Test::Unit integration to ensure that the test case classes we are
|
||||
|
|
|
@ -115,6 +115,11 @@ module Shoulda # :nodoc:
|
|||
|
||||
@subject.class.new.tap do |instance|
|
||||
instance.__send__("#{@attribute}=", value)
|
||||
|
||||
other_non_nullable_columns.each do |non_nullable_column|
|
||||
instance.__send__("#{non_nullable_column.name}=", correct_type_for_column(non_nullable_column))
|
||||
end
|
||||
|
||||
if has_secure_password?
|
||||
instance.password = 'password'
|
||||
instance.password_confirmation = 'password'
|
||||
|
@ -193,7 +198,7 @@ module Shoulda # :nodoc:
|
|||
end
|
||||
|
||||
def correct_type_for_column(column)
|
||||
if column.type == :string
|
||||
if column.type == :string || column.type == :binary
|
||||
'0'
|
||||
elsif column.type == :datetime
|
||||
DateTime.now
|
||||
|
@ -215,6 +220,12 @@ module Shoulda # :nodoc:
|
|||
end
|
||||
value
|
||||
end
|
||||
|
||||
def other_non_nullable_columns
|
||||
@subject.class.columns.select do |column|
|
||||
column.name != @attribute && !column.null && !column.primary
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -341,6 +341,42 @@ describe Shoulda::Matchers::ActiveModel::ValidateUniquenessOfMatcher do
|
|||
end
|
||||
end
|
||||
|
||||
context "a model with non-nullable attribute" do
|
||||
context "of type" do
|
||||
[:string, :text, :integer, :float, :decimal, :datetime, :timestamp, :time, :date, :binary, :boolean].each do |type|
|
||||
context type do
|
||||
it "does not raise an error" do
|
||||
model = define_model_with_non_nullable(type)
|
||||
expect { expect(model).to matcher }.not_to raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "that is a primary key" do
|
||||
it "does not cause duplicate entry errors by re-using default values for primary keys" do
|
||||
create_table :examples, id: false do |t|
|
||||
t.string :attr
|
||||
t.integer :non_nullable, primary: true
|
||||
end
|
||||
model_class = define_model(:example, attr: :string) do
|
||||
validates_uniqueness_of :attr
|
||||
end
|
||||
model_1 = model_class.new
|
||||
model_2 = model_class.new
|
||||
expect(model_1).to matcher
|
||||
expect { expect(model_2).to matcher }.not_to raise_error
|
||||
end
|
||||
end
|
||||
|
||||
def define_model_with_non_nullable(type)
|
||||
define_model(:example, attr: :string, non_nullable: { type: type, options: { null: false } }) do
|
||||
attr_accessible :attr, :non_nullable
|
||||
validates_uniqueness_of :attr
|
||||
end.new
|
||||
end
|
||||
end
|
||||
|
||||
def case_sensitive_validation_with_existing_value(attr_type)
|
||||
model = define_model(:example, attr: attr_type) do
|
||||
attr_accessible :attr
|
||||
|
|
Loading…
Reference in New Issue