validates_format_of

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.

Ja rowniez mialem bardzo podobny problem. Postaram sie jutro odszukac jak go rozwiazalem.
Co dzine jesli tego regexpa dasz w Rubym tak:

[code=ruby]
reg=/^\d{4,5}$/

irb(main):017:0> reg =~ “1234”
=> 0

irb(main):018:0> reg =~ “12345”
=> 0

irb(main):019:0> reg =~ “123456”
=> nil

irb(main):020:0> reg =~ “1234a”
=> nil

irb(main):021:0> reg =~ “1234asf”
=> nil[/code]
to jak widac wszystko dziala poprawnie.
Wyglada jakby ^ i $ byly ignorowane.

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.