Gdzie zdefiniować własne typy błędów w Ruby i / lub Rails?

Czy istnieje najlepsza praktyka definiowania niestandardowych typów błędów w bibliotece Ruby (gem) lub aplikacji Ruby on Rails? Konkretnie:

  1. Gdzie są one strukturalnie w projekcie? Oddzielny plik, z odpowiednim modułem / definicją klasy, gdzie indziej?
  2. czy są jakieś konwencje, które ustalają Kiedy doi kiedy nie do utworzyć nowy typ błędu?

Różne biblioteki mają różne sposoby robienia rzeczy i Nie zauważyłem żadnych prawdziwych wzorców. Niektóre biblioteki zawsze używają niestandardowych typów błędów, podczas gdy inne w ogóle ich nie używają; niektóre mają wszystkie błędy rozszerzające StandardError, podczas gdy inne mają zagnieżdżone hierarchie; niektóre są po prostu pustymi definicjami klas, inne mają różnego rodzaju sprytne sztuczki.

A to, że mam ochotę nazywać te "typy błędów" jest niejednoznaczne, mam na myśli to:
class AuthenticationError < StandardError; end
class InvalidUsername < AuthenticationError; end
Author: Erik B, 2011-03-05

5 answers

For Gems

Widziałem wiele razy, że definiujesz wyjątki w ten sposób:

Gem_dir / lib/gem_name / exceptions.rb

I zdefiniowane jako:

module GemName

  class AuthenticationError < StandardError; end
  class InvalidUsername < AuthenticationError; end

end

Przykładem może być coś takiego w httparty

Dla Ruby on Rails

Umieść je w folderze lib / w pliku o nazwie exceptions.rb, który wyglądałby mniej więcej tak:

module Exceptions
  class AuthenticationError < StandardError; end
  class InvalidUsername < AuthenticationError; end
end

I użyłbyś tego tak:

raise Exceptions::InvalidUsername
 223
Author: Mike Lewis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-12 09:37:13

Myślę, że aby mieć spójne pliki źródłowe w projekcie, należy zdefiniować błędy w klasie, w której mogą je wyrzucać i nigdzie indziej.

Niektóre heirarchia mogą być pomocne - przestrzenie nazw są dobre w utrzymywaniu zbędnych ciągów z nazw typów - ale to bardziej kwestia gustu - nie ma potrzeby przesadzać, pod warunkiem, że masz co najmniej jeden niestandardowy typ wyjątku w aplikacji, którego używasz do rozróżniania "celowego" i "przypadkowego" wyjątku sprawy.

 25
Author: Dean Radcliffe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-20 16:24:56

W rails możesz utworzyć app/errors katalog

# app/errors/foo_error.rb
class FooError < StandardError; end

Restart spring / server i powinien go odebrać

 24
Author: schpet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-11 20:09:13

To jest stare pytanie, ale chciałem podzielić się tym, jak sobie radzę z niestandardowymi błędami w Railach, w tym dołączaniem komunikatów o błędach, testowaniem i jak sobie z tym poradzić z modelami ActiveRecord.

Tworzenie Własnego Błędu

class MyClass
  # create a custome error
  class MissingRequirement < StandardError; end

  def my_instance_method
    raise MyClass::MissingRequirement, "My error msg" unless true   
  end
end

Testowanie (minitest)

test "should raise MissingRequirement if ____ is missing"
  # should raise an error
  error = assert_raises(MyClass::MissingRequirement) {
    MyClass.new.my_instance_method
  }

  assert error.message = "My error msg"
end

Z ActiveRecord

Myślę, że warto zauważyć, że jeśli pracujesz z modelem ActiveRecord, popularnym wzorcem jest dodanie błędu do modelu, jak opisano poniżej, aby Twoje walidacje nie powiodły się:

def MyModel < ActiveRecord::Base
  validate :code_does_not_contain_hyphens

  def code_does_not_contain_hyphens
    errors.add(:code, "cannot contain hyphens") if code.include?("-")
  end
end

Kiedy walidacje są uruchamiane, metoda ta zostanie przeniesiona do klasy błędów ActiveRecord::RecordInvalid ActiveRecord i spowoduje niepowodzenie walidacji.

Mam nadzieję, że to pomoże!
 14
Author: Matt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-04 20:37:23

Aby upewnić się, że autoloading działa zgodnie z oczekiwaniami w Rails 4.1.10 dla wielu niestandardowych klas błędów, musisz określić oddzielne pliki dla każdej z nich. Powinno to działać w rozwoju z jego dynamicznym przeładowywaniem.

Tak ustawiłem błędy w ostatnim projekcie:

W lib/app_name/error/base.rb

module AppName
    module Error
        class Base < StandardError; end
    end
end

I w kolejnych błędach niestandardowych, jak w lib/app_name/error/bad_stuff.rb

module AppName
    module Error
        class BadStuff < ::AppName::Error::Base; end
    end
end

Powinieneś być w stanie wywołać swoje błędy przez:

 raise AppName::Error::BadStuff.new("Bad stuff just happened")
 10
Author: spyle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-24 14:51:36