Должно ли исключить несуществующий ресурс в 404 RESTful Rails?

В совершенно новом Rails-приложении с модифицированной моделью RESTful созданный код удаления выглядит следующим образом:

class BeersController < ApplicationController
  # DELETE /beers/1
  # DELETE /beers/1.xml
  def destroy
    @beer = Beer.find(params[:id])
    @beer.destroy

    respond_to do |format|
      format.html { redirect_to(beers_url) }
      format.xml  { head :ok }
    end
  end
end

Если пользователь пытается дважды удалить один и тот же пиво (возможно, быстрый двойной щелчок или действия в двух разных вкладках браузера), они получат ошибку RecordNotFound, приводящую к странице 404. Это довольно недружественный опыт; похоже, было бы лучше завершить перенаправление обратно на beers_url независимо, возможно, с ошибкой flash, так как на самом деле пользователь не может сделать что-то из-за неудачного второго удаления.

Альтернативный подход состоит в том, чтобы действовать так же, как удаление, в любом случае, с чем-то вроде этого:

def destroy
  @beer = Beer.find_by_id(params[:id])
  destroyed = @beer.try(:destroy)        

  respond_to do |format|
    format.html { redirect_to(beers_url) }
    format.xml  { destroyed ? head(:ok) : head(:not_found) }
  end
end

Я могу понять стремление к жесткой ошибке 404 в прецеденте API, но мне труднее оправдать это для веб-приложения. Может ли кто-нибудь дать вескую причину, почему мы должны бросать страшную ошибку у пользователя во имя RESTfulness?

(Этот вопрос не относится к Rails, но я не знаю, как другие фреймворки обрабатывают этот случай из коробки).

Ответ 1

HTTP DELETE является idempotent. Вызов его несколько раз подряд должен привести к тому же поведению, что и первый. Значение: вы не должны возвращать HTTP 404.

UPDATE. Оказывается, я ошибался: fooobar.com/questions/293303/...

Ответ 2

Я не думаю, что вы должны когда-либо бросать ошибку пользователю, чтобы поддерживать какой-то стандарт, особенно если это приложение, ориентированное на потребителя (в отличие от B2B). Но вы также не должны превращать свой api в свой код статуса только для этой ситуации. Ресурс больше не существует; поэтому 404 является правильным ответом.

Я думаю, что существует путь наименьшего (или лизингового - это даже слово???) сопротивления здесь. Я еще не изучил рубин, поэтому я не могу предоставить какую-либо полезную реализацию; но я несколько опытен с веб-приложениями, используя html/css/js.

Если есть некоторая законная проблема, когда пользователи дважды нажимают кнопку; почему бы не настроить кнопку так, чтобы она отключилась при отправке запроса и снова включила, когда условия были правильными (запрос вернулся)? Другими словами, избегайте логики if (эта очень конкретная ситуация), делая невозможным попадание в ситуацию, которую вы видите. Я предполагаю, что у ruby ​​есть что-то специально для обработки запросов и добавления обработчиков функций для разных кодов состояния; или по крайней мере не-200 кодов состояния.

Ответ 3

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

Ответ 4

Нет причин, по которым вы не можете вернуть красиво отформатированную страницу 404 с ответом. Код состояния может быть одним и тем же, только рендеринг более удобен для пользователя, чем ваша типичная страница 404. Вы даже можете вернуть "перенаправленную" страницу в тело ответа. Одной из возможных проблем является поддержка браузера. Прошло довольно много лет, но я, кажется, вспоминаю IE (6?), Полностью игнорируя содержание тела ответа при получении 404. Вам придется поэкспериментировать, чтобы увидеть, что лучше всего подходит вам.