Общее спасение всего контроллера, когда id не найден - RoR - программирование
Подтвердить что ты не робот

Общее спасение всего контроллера, когда id не найден - RoR

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

Я знаю, что использование спасения с ситуацией довольно аккуратно, например:

def show
  @customer = Customer.find(params[:id])
  rescue ActiveRecord::RecordNotFound #customer with that id cannot be found
    redirect_to action: :index        #redirect to index page takes place instead of crashing
end

Если клиент не может быть найден, пользователь будет перенаправлен на индексную страницу. Это работает абсолютно нормально.

Теперь это все хорошо, но мне нужно выполнить те же попытки восстановления в таких действиях, как show, edit, destroy и т.д., т.е. каждый метод контроллера, которому нужен определенный идентификатор.

Сказав, что здесь мой вопрос: Разве нет способа вообще сообщить моему контроллеру, что если он не может найти идентификатор в любом из своих методов, он должен перенаправить на индексную страницу (или, как правило, выполнить определенную задачу)?

4b9b3361

Ответ 1

Для этой задачи вы должны использовать rescue_from. См. Пример в Обзор контроллера действий.

class ApplicationController < ActionController::Base
  rescue_from ActiveRecord::RecordNotFound, :with => :record_not_found

  private

  def record_not_found
    redirect_to action: :index
  end
end

Ответ 2

Rails имеет встроенный метод rescue_from:

class CustomersController < ApplicationController
  rescue_from ActiveRecord::RecordNotFound, with: :index
  ...
end

Ответ 3

Если вы говорите об этом в одном контроллере (в отличие от этого в глобальном масштабе в каждом контроллере), вот несколько вариантов:

Вы можете использовать файл before_filter для настройки вашего ресурса:

class CustomerController < ApplicationController
  before_filter :get_customer, :only => [ :show, :update, :delete ]

  def show
  end

  private

  def get_customer
    @customer = ActiveRecord.find(params[:id])
    rescue ActiveRecord::RecordNotFound
      redirect_to :action => :index
  end
end

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

class CustomerController < ApplicationController
  def show
    # Uses customer instead of @customer
  end

  private

  def customer
    @customer ||= Customer.find(params[:id])
    rescue ActiveRecord::RecordNotFound
      redirect_to :action => :index
  end
  helper_method :customer
end

Ответ 4

В некоторых случаях я рекомендую использовать Model.find_by_id(id), а не Model.find(id). Вместо того, чтобы бросать исключение, .find_by_id возвращает nil. если запись не найдена.

Просто убедитесь, что nils избегают NoMethodError!

P.S. Для того, что стоит, Model.find_by_id(id) функционально эквивалентен Model.where(id: id), что позволит вам построить дополнительные отношения, если вы хотите.