2012-03-06 7 views
7

W mojej aplikacji czasami utworzę użytkownika w locie, a adres e-mail użytkownika musi być prawidłowym formatem i być wyjątkowym.rails 3.1: w jaki sposób aplikacja może obsługiwać różne "powody" dla ActiveRecord :: RecordInvalid (na przykład duplikat vs błąd sprawdzania poprawności)

Chciałbym przekierować do różnych miejsc w zależności od tego, KTÓRYCH walidacja spowodowała błąd: nieprawidłowy format kontra duplikat.

W moim kodu mam

begin 
     user.save! 
     flash[:notice] = "Created new user #{email} with password #{password}" 

    rescue ActiveRecord::RecordInvalid => e 
     flash[:alert] = "Failed to create account because #{e.message}" 
     redirect_to SOMEPLACE 
    end 

Jeśli e-mail jest nieprawidłowy format (takich jak „użytkownik @ przykład”) e.message jest „Validation nie powiodło się: E-mail jest nieprawidłowy”

Jeśli e-mail już istnieje w tabeli, e.message to "Sprawdzanie poprawności nie powiodło się: wiadomość e-mail została już podjęta"

Nienawidzę idei analizowania tekstu e.message w celu ustalenia przyczyny ... czy istnieje lepszy sposób na obsługę ratunkową aby wykryć przyczynę powodującą wyjątek ActiveRecord :: RecordInvalid w jako wyrzucony?

P.S. Wiem, że w tym przykładzie mogę po prostu sprawdzić wcześniej e-mail już istniejący przed wykonaniem zapisu, ale staram się zrozumieć ogólne rozwiązanie do wykrywania i działania na różnych błędach walidacji rzucając ten sam wyjątek.

+1

W rzeczywistości nie można po prostu sprawdzić wcześniej e-mail już istnieje, walidacja ActiveRecord walidacji podlegają warunki wyścigu i zepsute przez projekt.Musisz mieć ograniczenie wyjątkowości w bazie danych i musisz być przygotowany poradzić sobie z wyjątkiem, że będzie się podnosił (z '.save' lub' .save! '). –

Odpowiedz

1

Standard Szyny sposób to zrobić, aby nie użyć operatora Wybuchu, który zgłasza wyjątek, ale w użyciu standardu Zapisz metody i sprawdzić, czy jest zwrócony prawda czy fałsz:

if @user.save 
    flash[:notice] = "User created." 
    redirect_to :action => :index 
else 
    flash[:alert] = "User could not be created." 
    render :action => :new 
end 

iw swoim widok stworzenie użytkownika:

<% if @user.errors.any? %> 
    <ul> 
    <% @user.errors.full_messages.each do |msg| %> 
     <li><%= msg %></li> 
    <% end %> 
    </ul> 
<% end %> 
+0

Ale to nie mówi, dlaczego zapis nie powiódł się. Jeśli masz unikalne ograniczenie w swojej bazie danych (które powinieneś, gdy walidacja AR jest uzależniona od warunków wyścigu), możesz mieć true, ale "x.save" i "x.save!" Mogą zgłosić wyjątek, ponieważ naruszono ograniczenie bazy danych. –

0

Jeśli mam zrozumienia tego, co staramy się robić prawidłowo, jednym ze sposobów, aby to zrobić byłoby tylko dochodzić przeciwko obecności błędu na poziomie pola. na przykład

if user.errors[:field_name].present? 
    redirect_to path_for_field_name_error 
end 

Alternatywnie, można zdefiniować pewne odwzorowanie jakie pola przekierować gdzie jako stały (np REDIRECT_PATHS w takim przypadku można skończyć z czymś takim:

redirect_to REDIRECT_PATHS[field_name] if user.errors[:field_name].present? 

gdzie można po prostu pętli nad field_name s

+0

W moim przykładzie może wystąpić wiele błędów dla tego samego adresu e-mail pola może być nieprawidłowy lub już używany, na przykład. – jpwynn

+0

K. Jeśli możesz w jakiś sposób użyć wbudowanych ActiveRecord do obsługi wszystkiego, co nie jest tym ograniczeniem unikalności opartym na DB (które jest zbyt krótkie, to nie zawsze działa zgodnie z oczekiwaniami), możesz po prostu sprawdzić przed '.valid?' i odkleić błędy w ten sposób, z wyjątkiem tego ograniczenia wyjątkowości. Oczywiście, jeśli masz wiele ograniczeń na innych polach, to nadal jest problem i wraca do parsowania ciągów. Powodzenia, mam nadzieję, że to jest pomocne? –

Powiązane problemy