Ruby-on-rails 过滤器在渲染之前但在控制器之后执行?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9281224/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Filter to execute before render but after controller?
提问by Chris
Suppose I have some logic in a base controller to pass information to the view to build something like a breadcrumb:
假设我在基本控制器中有一些逻辑来将信息传递给视图以构建类似面包屑的东西:
class ContextAwareController < ApplicationController
after_filter :build_breadcrumb
def build_breadcumb
#...
end
end
I want this build_breadcrumb method to run afterthe main controller logic, but beforethe view is rendered.
我希望这个 build_breadcrumb 方法在主控制器逻辑之后运行,但在呈现视图之前。
The above code runs too late, but a before_filter would be too early.
上面的代码运行得太晚了,但是 before_filter 太早了。
Can anybody suggest a way to accomplish this without explicitly calling build_breadcumb at the end of each of the actions in the child controllers?
任何人都可以建议一种方法来完成此操作,而无需在子控制器中的每个操作结束时显式调用 build_breadcumb 吗?
Thanks
谢谢
采纳答案by Peter Ehrlich
I believe rendering starts when render is called, and there's no default way to defer it. Here's one thing you could do:
我相信渲染在调用渲染时开始,并且没有默认的方法来推迟它。你可以做一件事:
filters are applied in the same order declared. So make a second after-filter that calls render with an array args stored in a class variable. Then anywhere you would normally call render, set the variable.
过滤器以声明的相同顺序应用。因此,使用存储在类变量中的数组 args 调用渲染的第二个后过滤器。然后在您通常调用渲染的任何地方设置变量。
回答by Joshua Muheim
I had the same problem and solved it like this:
我遇到了同样的问题并像这样解决了它:
class ApplicationController < ActionController::Base
def render *args
add_breadcrumbs
super
end
end
回答by knarewski
There are also some gems to achieve this. One of them is rails3_before_render. It works similarly to filters, for example:
也有一些宝石可以实现这一点。其中之一是rails3_before_render。它的工作原理类似于过滤器,例如:
class PostsController < ApplicationController
before_render :ping, :except => [:destroy]
def index; end
def new; end
def show; end
def destroy; end
private
def ping
Rails.logger.info "Ping-Pong actions"
end
end
(code snipped copied from gem documentation)
(从 gem 文档中截取的代码)
回答by Isaac Freeman
If we're overriding render, we're not really using the filter chain at all, so it might be simpler to determine which action we're in using the @_action_name.
如果我们覆盖render,我们根本就没有真正使用过滤器链,因此确定我们正在使用@_action_name.
StuffController < ApplicationController
def my_filter
# Do the stuff
end
def render(*args)
my_filter if @_action_name == "show"
super
end
end
回答by Lasse Skindstad Ebert
You can do like this to fake a before_render:
您可以这样做来伪造 before_render:
class StuffController < ApplicationController
before_filter :my_filter, only: [:index, :show]
def my_filter
@my_filter = true
end
def _my_filter
# Do the actual stuff here
end
def render(*args)
_my_filter if @my_filter
super
end
end
Thanks to @joshua-muheim for the tip about using render
感谢 @joshua-muheim 关于使用的提示 render

