Wyjątki - ActiveRecord::RecordNotFound

Witam, dopiero zaczynam z Railsami, mógłby mi ktoś wyjaśnić jedną rzecz?

begin @article = Article.find(params[:id]) rescue ActiveRecord::RecordNotFound flash[:error] = "Couldn't find category with given ID" redirect_to articles_path end if params[:review] ... else @review = @article.reviews.new end
Nie rozumiem dlaczego wyjątek jest wyłapywany a mimo tego kod wykonuje się dalej i otrzymuję dla wywołania @article.reviews.new:

You have a nil object when you didn't expect it! The error occurred while evaluating nil.reviews
Analogiczny kod mam w innych kontrolerach i wszystko działa jak należy :confused: Z góry dzięki za odp.

Po pierwsze primo: wyjątki nie są instrukcjami sterującymi. Po drugie primo, jak zastąpisz przechwycenie wyjątku instrukcją sterującą “if”, to zobaczysz co masz źle. Po wykonaniu klauzuli rescue wykonuje Ci się dalsza część kodu kontrolera, w tym jest problem, wyjątki zarezerwuj dla sytuacji wyjątkowych!

A ten redirect_to w rescue ?? Skoro robię przekierowanie to czemu kod się dalej wykonuje?

Article.find(123) => ActiveRecord::RecordNotFound: Couldn't find Article with ID=123
Sam rzuca, to go łapię.

Po przekierowaniu metoda dalej się wykonuje. Dodaj jawne “return”.

Lub dodaj else:

begin @article = Article.find(params[:id]) rescue ActiveRecord::RecordNotFound flash[:error] = "Couldn't find category with given ID" redirect_to articles_path else if params[:review] ... else @review = @article.reviews.new end end
Wtedy twój dalszy kod wykona się tylko jeśli wyjątek nie wystąpi.

Jeśli to jest kod całej akcji możesz też go zapisać bez begin:

def akcja @article = Article.find(params[:id]) rescue ActiveRecord::RecordNotFound flash[:error] = "Couldn't find category with given ID" redirect_to articles_path else if params[:review] ... else @review = @article.reviews.new end end

Nie chcesz łapać takich błędów i przekierowywać na inną stronę. Lepszą reakcją (jeśli ktoś zmieni id w URL) jest grzeczne wywalenie się i zwrócenie kodu 404 a nie przekierowanie.

Wyszukiwarki oczekują takiego zachowania od Twojej aplikacji. Jeśli użyjesz przekierowania to zaczynają głupieć.

Pomyśl raczej o zmianie domyślnie wyświetlanej strony dla błędu 404: http://www.evolt.org/article/mblog/4090/4299/