рельсы 3.1: как приложение может обрабатывать различные «причины» для ActiveRecord :: RecordInvalid (например, дубликат или ошибка проверки) - PullRequest
7 голосов
/ 07 марта 2012

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

Я хочу перенаправить в разные места, в зависимости от того, ЧТО валидация вызвалавозникшая ошибка: неверный формат против дубликата.

В моем коде у меня есть

    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

Если сообщение электронной почты имеет недопустимый формат (например, "user @ example"), e.message is "Ошибка проверки: электронная почта недействительна "

Если электронная почта уже существует в таблице, e.message будет" Проверка не удалась: электронная почта уже получена "

Я ненавижу идею парсинга e.текст сообщения, чтобы определить причину ... есть ли лучший способ для обработчика спасения определить причину, по которой возникло исключение ActiveRecord :: RecordInvalid?

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

Ответы [ 2 ]

1 голос
/ 07 марта 2012

Стандартный способ Rails сделать это - не использовать оператор bang, который вызывает исключение, а использовать стандартный метод сохранения и проверить, вернул ли он значение true или false:

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

И в вашем представлении создания пользователя:

<% if @user.errors.any? %>
  <ul>
    <% @user.errors.full_messages.each do |msg| %>
      <li><%= msg %></li>
    <% end %>
  </ul>
<% end %>
0 голосов
/ 18 марта 2014

Если я понимаю, что вы пытаетесь сделать правильно, один из способов сделать это - просто заявить о наличии ошибки на уровне поля.например,

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

В качестве альтернативы вы определяете некоторое отображение того, какие поля перенаправляют куда в качестве константы (например, REDIRECT_PATHS, и в этом случае вы получите что-то вроде:

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

, где выможно просто зацикливаться на field_name с.

...