Rails Newbie: рекомендации по обработке ошибок в контроллере - PullRequest
5 голосов
/ 27 октября 2010

Извините, если вопрос очевиден, я только начинаю работать с Rails.
У меня есть следующий код в нескольких методах контроллера сейчас:

respond_to do |format|
    if @project.save
        format.html { redirect_to(edit_project_url(@project), :notice => '#{user.name} added to #{role}.') }
        format.js
    else
        format.html { render :action => "edit" }
        format.js #...
    end
end

Итак, вопрос в том, как лучше всего сделать одно и то же для ошибок во всех методах?
Рекомендуется ли использовать save! и обрабатывать его в rescue_action?

Или я должен сделать свой собственный respond метод и передать save в блоке?

Ответы [ 2 ]

16 голосов
/ 27 октября 2010

Часто более удобно использовать вариант сохранения и спасения, вызывающий исключения, который позже в блоке, чем ветвление подобным образом.Преимущество исключений заключается в том, что они прерывают транзакции.

def create
  @project.save!

  respond_to do |format|
    format.html { redirect_to(edit_project_url(@project), :notice => '#{user.name} added to #{role}.') }
    format.js
  end

rescue ActiveRecord::RecordInvalid
  respond_to do |format|
    format.html { render :action => "edit" }
    format.js #...
  end
end

Вы обнаружите, что действительно сложно вырваться из груды вложенных операторов if при попытке сохранить большечем один объект за раз, но простой rescue для исключений будет обрабатывать его аккуратно.

def create
  Project.transaction do
    @project.save!
    @something_else.save!
    @other_stuff.save!
  end

  # ...
rescue ActiveRecord::RecordInvalid
  # ...
end

Если взорвется любой из этих сохранений, вы получите исключение.Чтобы убедиться, что все они отображают ошибки проверки, вам, возможно, придется вызывать .valid? для каждой из них, чтобы восполнить их, или они будут у вас после того, как ошибка не будет проверена.

3 голосов
/ 27 октября 2010

Неплохо использовать шаблон if @object.save.Однако, если вы делаете то же самое для всех ваших действий на контроллере, вы можете определить действие rescue_from.

Что-то вроде

class MyController < ActionController::Base
  rescue_from ActiveRecord::RecordInvalid do
    render :action => edit
  end
end
...