Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Change `validate_uniqueness_of_matcher` to give non-null columns defa…

…ult 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.
  • Loading branch information...
commit 561ac3e2f0c9b717114f7452597062cf32584316 1 parent 5b44edf
petedmarsh petedmarsh authored mcmire committed
3  NEWS.md
View
@@ -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
13 lib/shoulda/matchers/active_model/validate_uniqueness_of_matcher.rb
View
@@ -115,6 +115,11 @@ def create_record_in_database(options = {})
@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 @@ def validate_after_scope_change?
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 @@ def existing_value
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
36 spec/shoulda/matchers/active_model/validate_uniqueness_of_matcher_spec.rb
View
@@ -341,6 +341,42 @@ def define_model_without_allow_nil
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
Please sign in to comment.
Something went wrong with that request. Please try again.