Как ограничить форматы ресурсов в файле маршрутов Rails
При маршрутизации ресурсов в Rails дополнительный атрибут формата автоматически добавляется к сгенерированным маршрутам. Это значит, что данный ресурс можно запросить как XML, HTML и т.д. Какие форматы, которые фактически разрешены, обычно описываются в контроллере с помощью respond_to
.
Но во многих случаях вы хотите только поддерживать HTML-код и чувствовать себя как накладные расходы, чтобы писать respond_to :html
в каждом действии в каждом контроллере. Поэтому было бы здорово, если бы там был способ ограничить допустимые типы контента уже при построении маршрутов в файле route.rb, например.
map.resources :users, :formats => :html
map.resources :users, :formats => [:html, :xml]
map.resources :users, :formats => {:index => :html, :show => [:html, :xml]}
Есть ли способ достичь этого либо нативного, либо через плагин?
P.S. Обычный способ обойти это - просто игнорировать проблему и не использовать respond_to
в действиях. Но это фактически не ограничивает допустимые типы контента. Вместо этого он просто ожидает, что шаблон существует в каталоге представлений для каждого возможного типа контента. Если по требованию не существует, система выдаст ошибку HTTP 500.
Ответы
Ответ 1
Вы должны обернуть эти маршруты в область видимости, если хотите ограничить их определенным форматом (например, html или json). К сожалению, ограничения в этом случае не работают должным образом.
Это пример такого блока...
scope :format => true, :constraints => { :format => 'json' } do
get '/bar' => "bar#index_with_json"
end
Дополнительную информацию можно найти здесь: https://github.com/rails/rails/issues/5548
Этот ответ копируется из моего предыдущего ответа здесь.
Rails Routes - ограничение доступных форматов для ресурса
Ответ 2
Так как Rails использует эквивалент подстановочного знака для обработки форматов ".: format" его немного сложнее предотвратить на стороне маршрута.
Вместо этого это довольно простой способ поймать любые не HTML-запросы в переднем фильтре. Вот один из способов, которым это может выглядеть:
class ApplicationController < ActionController::Base
before_filter :check_format
private
def check_format
if request.format != Mime::HTML
raise ActionController::RoutingError, "Format #{params[:format].inspect} not supported for #{request.path.inspect}"
end
end
end
ActionController:: RoutingErrors обрабатываются как 404 ошибок, которые разумны.
Если у вас есть действие, которое должно поддерживать что-то другое, кроме HTML, просто используйте:
skip_before_filter :check_format, :only => ACTION_NAME
Ответ 3
Я считаю, что вы можете сделать что-то вроде этого:
respond_to do |format|
format.html
format.json { render :json => @things }
format.any { render :text => "Invalid format", :status => 403 }
end
Если пользователь запрашивает html или json, он будет делать это как следует, но все остальное отобразит текст "Недопустимый формат".
Ответ 4
В любом случае вам не нужна ошибка HTTP 500? Как во второй строке вашего примера, если кто-то запросил JSON вместо HTML или XML, это не код ошибки, возвращающий соответствующий ответ?
Ответ 5
а не делать:
def some_action
...
respond_to do |format|
format.html
format.json { whatever }
format.any { whatever }
end
end
просто используйте:
def some_action
...
end
и Rails по умолчанию будет искать some_action.html.erb или любой другой формат. Если вы не определяете какие-либо представления, отличные от html, тогда все остальные форматы будут сбой при запросе.