Můj malý svět

Obrať obličej k slunci
a stíny budou padat za tebe

shoulda nerada duplicitní chybové zprávy validací

Standardní validační hlášky v Ruby on Rails netřeba představovat. Je to super, člověk nemusí nic dělat, má je zadarmo. Na druhou stranu jsou také patřičně strojové a na skutečném webu zní velice zvláštně. Občas ani nemusí vystihovat, co je vlastně špatně.

Je proto běžné, že se pro jednotlivé validace v jednotlivých modelech píší chybové hlášky na míru. Ti pečlivější se je snaží co nejlépe sladit s kontextem, aby perfektně zapadly. Pro jeden atribut se pak třeba nevypisuje více než 1 chyba současně, vše je lokalizované a ideální.

Dá se však i narazit. Když pro různé validace jednoho atributu v témže modelu budete mít stejné chybové zprávy (protože to tak dává v daném kontextu smysl – např. lze sloučit informaci o nutnosti zadat údaj a že musí být číselný, tzn. „je třeba zadat číselný údaj“). Na první pohled není důvod k potížím, ale pokud poctivě testujete, může se to stát.

Přítomnost a konfiguraci validací testuji pomocí gemu shoulda, což je ohromně jednoduché a pohodlné (na jeden řádek vše, co potřebuji). Nicméně shoulda kontroluje seznam chybových zpráv a hledá tam tu, která odpovídá dané testované validaci. Pokud mají dvě validace stejnou chybovou hlášku, splnění jedné z těchto validací shoulda nepozná, protože její chybová zpráva v seznamu stále bude.

Tento problém se dá vyřešit drobným hackem – jednoduše všechny validační hlášky převést na unikátní, např. připojením jedinečného suffixu.

A přesně to provádí následující kód, který patří do test/test_helper.rb:

class ActiveSupport::TestCase
  def make_validation_messages_unique(model, locale = I18n.locale)
    i = 0
    I18n.get_backend.translations[locale][:activemodel][:errors][:models][model][:attributes].each do |attr, messages|
      messages.each do |error, msg|
        messages[error] = msg + '//' + i.to_s
        i += 1
      end
    end
  end
end

module I18n
  module Base
    def get_backend
      backend = config.backend
      backend.available_locales   # to force load of translations
      backend
    end
  end

  class Backend::Simple
    public :translations
  end
end

Přičemž :activemodel zde můžete chtít nahradit za :activerecord – podle toho, kde přesně validujete.

V testu modelu pak stačí tento kód vždy ad-hoc zavolat:

setup do
  make_validation_messages_unique :jmeno_modelu
end

Zaškatulkováno v kategorii: Ruby on Rails | 19. listopadu 2017

Komentáře

Jak přidat komentář? E-mailem! :c) Na komentare -zavináč- mujmalysvet -tečka- cz – do předmětu „Komentář:“ + název zápisku (tj. „Komentář: shoulda nerada duplicitní chybové zprávy validací“), případně připojte i svou přezdívku a domovskou stránku.