Wyjątki i custom validator

Mam pewien problem, kilka linijek kodu, ogólnie działa, ale w moim validatorze nie.

Mam model Entry z polem :url
Chcę sprawdzić czy to pole ma dobry format. Na stack-overflow znalazlem coś takiego(nie 100%, ale zasada ta sama):

require 'uri'

begin
  URI.parse("http://onet!!t.pl")
rescue URI::InvalidURIError
  puts "FALSE"
end

I to fajnie działa, pokazuje mi FALSE, jak jest zły adres.

Teraz w moim modelu daję validację:

      validates :url, uri_format: true

W katalogu apps/validators utworzyłem plik uri_format_validator.rb:

class UriFormatValidator < ActiveModel::EachValidator
  def validate_each(record,attribute,value)
    URI.parse(value)
  rescue URI::InvalidURIError
    record.errors[attribute] << "is not an URL format"
  end
end

Nawet jak już chamsko zamiast (value) wstawiam (“one!!t.pl”) to nie działa.

Będę wdzięczny za podpowiedź, co robię nie tak, bo siedzę nad tymi kilkoma linijkami już kilka godzin :confused:

Gdzie begin?

Zanim zaczniesz działać z całymi klasami walidatorów to po prostu sobie zwaliduj przez pojedynczą metodę

z tym, że URI.parse nie rzuca wyjątku dla “one!!t.pl” :smiley: spróbuj może tego - https://gist.github.com/2986523

Chyba wyrzica, bo dostaję taki błąd przy samym wywyołaniu:

initialize': the scheme http does not accept registry part: onet!!t.pl (or bad hostname?) (URI::InvalidURIError)

ps. dzieki zlw za linka, działa :slight_smile:
Będę wdzięczny za podpowiedź, dlaczego mój kod:

class UriFormatValidator < ActiveModel::EachValidator

  def validate_each(record, attribute, value)
    begin #tutaj próbowałem i z begin i bez
      URI.parse(value)
    rescue URI::InvalidURIError
      record.errors[attribute] << (options[:message] || "is an invalid URL")
    end
  end
end

Tłumaczyłem sobie to tak, że próbuję odpalić URI.parse(value) , co przetestowałem na prostym skrypciku i jak rzuca mi tym wyjątkiem to ustawiam record.error:

require 'uri'

begin
  URI.parse("http://onet!!t.pl")
  puts "TRUE"
rescue URI::InvalidURIError
  puts "FALSE"
end

MRI 1.9.3

1.9.3p286 :003 > URI.parse "one!!t.pl" => #<URI::Generic:0x007faee1111d80 URL:one!!t.pl>
JRuby

jruby-1.7.0 :011 > URI.parse "one!!t.pl" => #<URI::Generic:0x2cb549af URL:one!!t.pl>

To nie mam pojęcia czemu u ciebie jest tak, u mnie jeszcze raz w konsoli sprawdziłem:

1.9.3-p194 :002 > require 'uri' => true 1.9.3-p194 :003 > URI.parse("http://onet!!t.pl") URI::InvalidURIError: the scheme http does not accept registry part: onet!!t.pl (or bad hostname?)
Edit, a ok, już widzę to przez to, że ja wrzucam z http.

Zakończyło się tak, że jednak wykorzystałem jakiegoś zwykłego regexpa (http://www.railsmine.net/2010/09/ruby-way-to-do-url-validation.html), bo ten URI.parse puszcza jako ok praktycznie wszystko co ma dobrze ustawiony protokół “http://” czyli onet…pl czy -onet.pl (mozliwe ze jak nazwa wskazuje, to jest raczej do parsowania poprawnych url, a nie do ich validowania)

class UriFormatValidator < ActiveModel::EachValidator
  VALID_URL_REGEXP = /^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?\/.*)?$/ix

  def validate_each(record, attribute, value)
    url="http://"+value.sub(/^(http:\/\/|https:\/\/)/,"")
    record.errors[attribute] << (options[:message] || "is an invalid URL") unless url=~VALID_URL_REGEXP
  end

end

uri = URI.parse(str) [URI::HTTP, URI::HTTPS].include?(uri.class)
może to?