Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Consider expressions that cannot be type cast to be invalid #37

Merged
merged 1 commit into from

4 participants

@robworley

Useful for ActiveRecord models where string a value is assigned to using Model#attributes=. ActiveRecord will try to type cast the string to a date. When the type cast fails because the string cannot be parsed, it assigns nil to the attribute.

Prior to this change if you specified :allow_nil => true or :allow_blank => true it would incorrectly consider the attribute to be valid. I added some logic to check the value before type cast, taking care to preserve backwards compatibility.

It should resolve issue #25. Hope it helps.

@robworley

The travis build succeeded for the most part, but there's a problem with rbx-2.0. It looks like a travis-specific issue, rather than anything code-related. Maybe someone with rights could try a rebuild?

@amnesia7

@robworley, does this allow for virtual attributes as well as actual database-driven attributes?

I have a virtual date attribute in my form which I don't insert directly into a date field in my db. I'm not sure whether or not virtual attributes have _before_type_cast values or not but I don't think so.

Thanks

@robworley

@amnesia7 sorry for the delayed response.

It's true that virtual ActiveRecord attributes don't have _before_type_cast methods. This change only calls _before_type_cast methods for persistent attributes, so in that sense it's fully backwards compatible.

@korny

Works great for us, thank you!

@robworley

@oriolgual, @txus is this PR of interest to you? Anything I need to add or change?

@oriolgual
Owner

Sorry for the late response. Seems OK to me!

@oriolgual oriolgual merged commit 26a6462 into from
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
25 lib/active_model/validations/date_validator.rb
@@ -33,10 +33,33 @@ def check_validity!
end
end
+ # Overridden because standard allow_nil and allow_blank checks don't work with
+ # string expressions that cannot be type cast to dates. We have to validate
+ # the pre-type cast values.
+ def validate(record)
+ attributes.each do |attribute|
+ value = record.read_attribute_for_validation(attribute)
+ validate_each(record, attribute, value)
+ end
+ end
+
# The actual validator method. It is called when ActiveRecord iterates
# over all the validators.
def validate_each(record, attr_name, value)
- return if options[:allow_nil] && value.nil?
+ before_type_cast = :"#{attr_name}_before_type_cast"
+
+ value_before_type_cast = if record.respond_to?(before_type_cast)
+ record.send(before_type_cast)
+ else
+ nil
+ end
+
+ if value_before_type_cast.present? && value.nil?
+ record.errors.add(attr_name, :not_a_date, options)
+ return
+ end
+
+ return if (value.nil? && options[:allow_nil]) || (value.blank? && options[:allow_blank])
unless value
record.errors.add(attr_name, :not_a_date, options)
View
16 test/date_validator_test.rb
@@ -131,6 +131,22 @@ module Validations
TestRecord.new(Time.now).valid?.must_equal false
end
+
+ describe "with type cast attributes" do
+ before do
+ TestRecord.send(:define_method, :expiration_date_before_type_cast, lambda { 'last year' })
+ end
+
+ it "should detect invalid date expressions when nil is allowed" do
+ TestRecord.validates(:expiration_date, :date => true, :allow_nil => true)
+ TestRecord.new(nil).valid?.must_equal false
+ end
+
+ it "should detect invalid date expressions when blank is allowed" do
+ TestRecord.validates(:expiration_date, :date => true, :allow_blank => true)
+ TestRecord.new(nil).valid?.must_equal false
+ end
+ end
end
end
Something went wrong with that request. Please try again.