#ruby-on-rails #ruby #ruby-on-rails-4 #dry
#ruby-on-rails #ruby #ruby-on-rails-4 #сухой
Вопрос:
Может быть, это излишество, я но я пытаюсь использовать after_filter для вывода этого контроллера из строя. К моему ужасу, он взрывается, и я не могу понять, почему. Чтобы заставить его работать, мне пришлось добавить рендеринг в каждый метод.
Мысли?
Сообщение об ошибке
Рендеринг и / или перенаправление вызывались несколько раз в этом действии. Пожалуйста, обратите внимание, что вы можете вызывать render ИЛИ redirect только не чаще одного раза за действие. Также обратите внимание, что ни перенаправление, ни рендеринг не завершают выполнение действия, поэтому, если вы хотите завершить действие после перенаправления, вам нужно сделать что-то вроде «redirect_to(…) и return».
Контроллер
class ErrorController < ApplicationController
after_filter :render_me
def javascript_disabled
@title = 'Error! Javascript Disabled'
end
def system_requirements
@title = 'Error! System Requirements'
end
def browser_upgrade_required
@title = 'Error! Browser Upgrade Required'
end
private
def render_me
render 'error/system_requirements', layout: 'error'
end
end
Маршрут
scope 'error' do
get '/javascript-disabled', to: 'error#javascript_disabled'
get '/software-requirements', to: 'error#system_requirements'
get '/browser-upgrade-required', to: 'error#browser_upgrade_required'
end
Ответ №1:
Проблема в том, что рендеринг не останавливает выполнение в вашем методе. В вашем render_me
методе вы вызываете render, а затем выполнение продолжается в вызываемом методе action … в конце которого есть встроенный рендеринг.
Вы можете исправить это, самостоятельно вызывая свой метод after_filter в каждом действии и добавляя явный возврат для остановки выполнения, например:
class ErrorController < ApplicationController
def javascript_disabled
@title = 'Error! Javascript Disabled'
render_me
end
def system_requirements
@title = 'Error! System Requirements'
render_me
end
def browser_upgrade_required
@title = 'Error! Browser Upgrade Required'
render_me
end
private
def render_me
render 'error/system_requirements', layout: 'error'
end
end
Конечно, вы могли бы немного это исправить:
class ErrorController < ApplicationController
def javascript_disabled
render_with_error 'Error! Javascript Disabled'
end
def system_requirements
render_with_error 'Error! System Requirements'
end
def browser_upgrade_required
render_with_error 'Error! Browser Upgrade Required'
end
private
def render_with_error(msg)
@title = msg
render 'error/system_requirements', layout: 'error'
end
end
Я склонен считать, что если вам нужно повторно исправить кодовую базу rails, вы, вероятно, делаете что-то неправильно.
Комментарии:
1. Я только что попробовал это, и я все еще получаю ошибку: «Рендеринг и / или перенаправление были вызваны несколько раз в этом действии. Пожалуйста, обратите внимание, что вы можете вызывать render ИЛИ redirect только не чаще одного раза за действие. Также обратите внимание, что ни перенаправление, ни рендеринг не завершают выполнение действия, поэтому, если вы хотите завершить действие после перенаправления, вам нужно сделать что-то вроде «redirect_to(…) и return».
2. Моя ошибка — по какой-то причине у меня была полная заморозка мозга, и я ответил на это так, как если бы это было
before_filter
. Я обновил свой ответ для вас. Я думаю, что это лучше, чем обезьянье исправлениеrender
метода TBH.3. о, мне это очень нравится. Спасибо:)
4. Кстати,
and return
в конце метода бессмысленно.5. Да, верно — похмелье от моего первоначального плохо написанного ответа.
Ответ №2:
На случай, если другие найдут этот пост, вот другой подход, который вы можете предпринять, чтобы его исправить:
class ErrorController < ApplicationController
def javascript_disabled
@title = 'Error! Javascript Disabled'
render_it
end
def system_requirements
@title = 'Error! System Requirements'
render_it
end
def browser_upgrade_required
@title = 'Error! Browser Upgrade Required'
render_it
end
private
def render_it
render 'error/system_requirements', layout: 'error'
end
end
Ответ №3:
У вас уже есть неявный #render
вызов в действиях контроллера. Итак, после того, как filter вызывает #render
еще раз явно, и вы получаете DoubleRenderError.
Вы можете переопределить #render
подобный метод
def render(*args)
if args.blank? amp;amp; !block_given?
# default template
super('error/system_requirements', layout: 'error')
else
super
end
end
Я думаю, что это лучше, чем использовать обратные вызовы, иначе называемые фильтрами.
Комментарии:
1. это довольно сумасшедший подход. Интересно, будут ли другие разработчики злоупотреблять этим, но мне нравится это решение. хммм…
2. Как я уже сказал в своем ответе, если вы исправляете кодовую базу rails, я думаю, вы, вероятно, делаете что-то неправильно.
3. Это не патч для обезьяны. Это Ruby. Это наследование. Rails не предоставляет вам возможности установить вид по умолчанию для контроллера, но Ruby это делает.
4. @FlashGordon
Rails does not provide you ability to set default view for controller
это неправильно. AbstractController#append_view_path5. @Зелёный Ok. Не могли бы вы опубликовать суть с примером?