Witam,
mam problem z validates_format_of, a mianowicie:
mam jeden model, najprostszy z możliwych:
class Costam << ActiveRecord::Base
validates_format_of :code, :with => /^\d{4,5}$/
end
czyli atrybut code musi składać się z cyfr, minimalnie czterech, a maksymalnie pięciu (na tyle na ile znam regexpy).
Natomiast jak to dziala?
[code]>> test = Costam.new
test.code = “1234”
=> “1234”
test.valid?
=> true
test.code = “12345”
=> “12345”
test.valid?
=> true
test.code = “123456”
=> “123456”
test.valid?
=> false
test.code = “12345y”
=> “12345y”
test.valid?
=> true
test.code = “1234yui”
=> “1234yui”
test.valid?
=> true[/code]
Ktoś umie mi to wyjaśnić? Bo wg mnie dwa ostatnie przypadki powinny zwrócić false.
validates_format_of również posługuje się operatorem ~=. Fragment ze źródeł:
# File vendor/rails/activerecord/lib/active_record/validations.rb
record.errors.add(attr_name, configuration[:message]) unless value.to_s =~ configuration[:with]
Problem wynika z tego, że prawdopodobnie w bazie pole “code” jest typu int, wtedy najpierw metoda code= posłuży się to_i, a jak mówi dokumentacja:
str.to_i(base=10) => integer
Returns the result of interpreting leading characters in str as an integer base base (2, 8, 10, or 16). Extraneous characters past the end of a valid number are ignored. If there is not a valid number at the start of str, 0 is returned. This method never raises an exception.
i przykład:
"12345".to_i #=> 12345
"99 red balloons".to_i #=> 99
"0a".to_i #=> 0
"0a".to_i(16) #=> 10
"hello".to_i #=> 0
Podobnie, jeśli pole jest typu int, nie będzie można zweryfikować takim regexpem wartości w stylu 0001, 01234, gdyż 0 zostaną najpierw obcięte, a dopiero później będzie sprawdzanie regexpem.
Rozwiązaniem jest posłużenie się polem typu string (varchar, char czy inne), co w sumie wydaje się logiczne.