#ruby-on-rails #exception
#ruby-on-rails #исключение
Вопрос:
Я пытаюсь проверить, является ли формат, отправляемый через URL-адрес запроса, json или нет?
итак, в link_to я отправил формат следующим образом
<%= link_to "Embed", {:controller=>'api/oembed' ,:action => 'show',:url => catalog_url, format: 'xml'} %>
В соответствующем контроллере я перехватываю параметр и вызываю исключение следующим образом
format_request = params[:format]
if format_request != "json"
raise DRI::Exceptions::NotImplemented
end
но исключение не отображается, вместо этого сервер просто столкнулся с внутренней ошибкой, но если я изменил параметр внутри контроллера, тогда отобразится исключение, поэтому, если URL-адрес такой
<%= link_to «Embed», {:controller=>’api/oembed’,:action => ‘show’,:url => catalog_url, формат: ‘json’} %>
format_request = "xml"
if format_request != "json"
raise DRI::Exceptions::NotImplemented
end
почему исключение 501 не срабатывает, если я отправляю формат как xml в URL? Я делаю это с целью тестирования, чтобы в случае, если кто-то отправит запрос с неправильным форматом, отображалось ожидание 501
Комментарии:
1. Используйте request.format вместо params[:format], который присутствует только в том случае, если вы явно передаете этот параметр. Это также экземпляр запроса строки, поэтому вы можете сделать request.format.xml ? Что намного более рубиново, чем сравнение со строкой — и используйте, если вместо != .
2. Но вы действительно изобретаете колесо здесь, чтобы. Rails имеет MimeResponds, который уже реализует эту функциональность.
3. Я попробовал, но все то же самое, он не отображает исключение: (
4. поскольку у вас на самом деле нет воспроизводимого примера, я понятия не имею, что именно вы испортили. Я могу просто указать на очевидное, например, не изобретать велосипед. api.rubyonrails.org/classes/ActionController/MimeResponds.html и используйте rescue_from, если вы хотите обработать исключение.
5. Да. Если вы используете MimeResponds, это вызовет ошибку, если контроллер не обрабатывает формат запроса. Таким образом, изобретая велосипед.
Ответ №1:
Используйте ActionController::MimeResponds
вместо того, чтобы плохо изобретать колесо:
# or whatever your base controller class is
class ApplicationController < ActionController::API
# MimeResponds is not included in ActionController::API
include ActionController::MimeResponds
# Defining this in your parent class avoids repeating the same error handling code
rescue_from ActionController::UnknownFormat do
raise DRI::Exceptions::NotImplemented # do you really need to add another layer of complexity?
end
end
module Api
class OembedController < ApplicationController
def oembed
respond_to :json
end
end
end
Если вы не используете respond_to
Rails, неявно предполагается, что контроллер отвечает на все форматы ответов. Но если вы явно перечислите форматы, на которые вы отвечаете, с помощью списка символов (или более распространенного блочного синтаксиса), Rails вызовет ActionController::UnknownFormat
, если формат запроса отсутствует в списке. Вы можете сохранить исключения, с rescue_from
помощью которых вы можете использовать наследование вместо того, чтобы повторяться с той же обработкой ошибок.
Ответ №2:
Как упоминает @max, отправка format: 'xml'
не требуется, поскольку Rails уже знает формат запроса.
<%= link_to "Embed", {:controller=>'api/oembed' ,:action => 'show',:url => catalog_url } %>
В контроллере:
def oembed
respond_to do |format|
format.json { # do the thing you want }
format.any(:xml, :html) { # render your DRI::Exceptions::NotImplemented }
end
end
Или, если вы хотите больше контроля, вы можете перейти к пользовательскому действию:
def oembed
respond_to do |format|
format.json { # do the thing you want }
format.any(:xml, :html) { render not_implemented }
end
end
def not_implemented
# just suggestions here
flash[:notice] = 'No support for non-JSON requests at this time'
redirect_to return_path
# or if you really want to throw an error
raise DRI::Exceptions::NotImplemented
end
Если вы действительно хотите изобрести колесо (это ваше колесо, изобретайте, если хотите):
Я бы переименовал format
во что-то другое, оно, вероятно, зарезервировано и может вызвать у вас проблемы
<%= link_to "Embed", {:controller=>'api/oembed' ,:action => 'show',:url => catalog_url, custom_format: 'xml'} %>
Затем в вашем контроллере вам необходимо явно разрешить этот параметр:
def oembed
raise DRI::Exceptions::NotImplemented unless format_params[:custom_format] == 'json'
end
private
def format_params
params.permit(:custom_format)
end
Комментарии:
1. Вы на правильном пути, но лучшим решением здесь действительно является не отвечать на типы, которые вы не поддерживаете, и перехватывать
ActionController::UnknownFormat
исключение, поскольку оно является СУХИМ и будет досрочно прекращено, что предотвратит выполнение действия контроллера. Также да —format
параметр зарезервирован — для указания формата запроса. Он имеет приоритет над заголовками запроса.2. Я согласен с вами, @max, я бы просто сказал, что ваше решение на несколько уровней глубже (и правильнее), но может показаться слишком глубоким для OP, для меня это почти так, и у меня за плечами 5 лет Ruby.
3.Глубокий конец? Этот материал описан в руководствах и является довольно фундаментальным знанием rails. guides.rubyonrails.org/action_controller_overview.html#rescue guides.rubyonrails.org /…
4. Глубокий конец в смысле «MVC» -уровень против унаследованный уровень (Application, ApplicationRecord, ApplicationController)