Как решить эту проблему - NoMethodError vs NoRecordFound - PullRequest
1 голос
/ 16 февраля 2011

просто задаюсь вопросом, как лучше справиться со следующим, поскольку в Интернете, похоже, есть противоречивая информация об этом.Мой код начал жизнь, как это ..

@merchant = Merchant.find_by_name(params[:merchant])
@products = @merchant.products.all.paginate(:page => params[:page])

Теперь это прекрасно работает, пока вы не нажмете на URL, где не будет торговца, т.е. /merchants/thisonedontexist/, и в этот момент я получаю следующую ошибку:

`undefined method `products' for nil:NilClass`

Я понимаю, почему я получаю эту ошибку.

Итак, после небольшого исследования, я решил изменить свой код на следующий с BANG (!), Что вызывает ошибку NoRecordFoundтак что он никогда не попадает в следующую строку, проблема в том, что теперь я получаю ужасную ошибку:

@merchant = Merchant.find_by_name!(params[:merchant])
@products = @merchant.products.all.paginate(:page => params[:page])

Ошибка: ActiveRecord::RecordNotFound

Так что после более подробного исследования я сделал следующееи перенаправил эти запросы на 404 ...

  def show
    @merchant = Merchant.find_by_name(params[:merchant])
    if !@merchant.nil?
      @products = @merchant.products.all.paginate(:page => params[:page])
    else
      redirect_to :status => 404
    end
  end

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

Я бы хотел за этопросто чтобы показать страницу с "Sorry no category exists".

ps. Я новичок в Rails, может быть, на этот вопрос есть действительно очевидный ответ n00b

Ответы [ 3 ]

2 голосов
/ 16 февраля 2011

Использование версии взрыва - лучший подход.Ошибка NoMethodError дает мне представление о том, что вы неправильно обрабатываете рабочий процесс приложения.

Кроме того, используя версию bang, вы можете упростить свой код.В производстве ActiveRecord::RecordNotFound восстанавливается как 404. Это означает, что при возникновении ошибки Rails спасет ошибку и отобразит страницу ошибки 404 с кодом состояния 404 для вас по умолчанию.

См. исходный код .

Вы можете упростить свой код

def show
  @merchant = Merchant.find_by_name!(params[:merchant])
  @products = @merchant.products.all.paginate(:page => params[:page])
end
0 голосов
/ 26 февраля 2011

Как говорит @simone, вы можете упростить свой код до

def show
  @merchant = Merchant.find_by_name!(params[:merchant])
  @products = @merchant.products.all.paginate(:page => params[:page])
end

Теперь, когда @merchant не найден, возникает исключение. И, к счастью, рельсы предлагают отличное решение для обработки исключений.

Внутри вашего контроллера (или вашего ApplicationController, если вы хотите сделать его универсальным) вы пишете

rescue_from ActiveRecord::RecordNotFound, :with => :handle_not_found

def handle_not_found
  # either 
  flash[:error] = ... some appropriate error message ...
  redirect_to :root # or some relevant path
end

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

0 голосов
/ 16 февраля 2011

контроллер

  def show
    @merchant = Merchant.find_by_name(params[:merchant])
    @products = @merchant.products.all.paginate(:page => params[:page]) if @merchant
  end

по вашему мнению /show.html.erb

if @merchant
  ...
  ...your code here
else
  <div>No such merchant</div>
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...