【发布时间】:2009-08-14 11:56:30
【问题描述】:
我希望在 Ruby on Rails 2.3.2 中以更动态的方式使用过滤器链。
目前,过滤器链是在加载类时构建的。我非常需要在加载类后的某个时间点重建过滤器链。
这与一个 Rails 项目(我猜是 Spree,Radiant 也可能受到影响)有关,该项目使用扩展,在为 MyController 构建过滤器链之后可以执行以下操作:
MyController.class_eval do
before_filter :my_filter_method
end
ApplicationController.class_eval do
before_filter :app_filter_method
end
这里的问题是app_filter_method 过滤器将不会添加到 MyController 过滤器链中。这是因为 MyController 的过滤器链是从 ApplicationController 的过滤器链的早期副本构建的。 ApplicationController 的过滤器链副本没有尚未应用app_filter_method 过滤器。
到目前为止,我能想到 2 个地方可以重建 FilterChain:
1) 每次在 MyController.filter_chain 上调用
2) 可按需重新加载。所以 MyController.reload_filter_chain 将重建过滤器链,使用来自链中 MyController 子类的过滤器。
也许指定一个 FilterChain 的子类,如 ReloadableFilterChain,它为每个请求构建过滤器链可能会这样做 - 想法?
这里是 GitHub 上用于 Ruby on Rails 2.3.2 的 filters.rb 源的链接:
The filter_chain method (line 573)
The FilterChain class (line 10)
我希望你们中的一些人可能对如何做到这一点有一些见解或建议。
非常感谢任何帮助。
艾略特
根据要求提供更多详细信息:
Spree 是一个使用扩展来修改行为的 Rails 应用。
有时会使用扩展来向控制器添加过滤器(例如问题中的示例代码)。一个示例使用是静态内容扩展。
静态内容扩展允许您显示存储在数据库中的 HTML 页面,以便针对您指定的任何请求路径显示。例如,您可以显示其中一个 HTML 页面,而不是 Spree 为 /products 请求路径显示的默认内容。
静态内容扩展过滤所有请求并检查路径。如果路径与 db 中的某个页面匹配,则过滤器会呈现该页面。
静态内容扩展声明其过滤器如下:
Spree::BaseController.class_eval do
before_filter :render_page_if_exists
def render_page_if_exists
...
end
end
【问题讨论】:
-
有关您尝试实现的目标的更多详细信息会很有用。
-
添加了一点更多细节。有什么具体的我可以添加帮助的吗?
-
我对原因更感兴趣。
-
当然,感谢您对这个问题感兴趣。我会把它添加到问题的末尾。
-
一种想法是修改Controller中的before_filter、after_filter等方法,使它们在子类上调用相同的方法。这实际上会发生: before_filter :render_page_if_exists subclasses.each do |subclass| subclass.class_eval do before_filter :render_page_if_exists end end subclasses method: class Class def subclasses result = [] ObjectSpace.each_object(Class) { |klass|结果
标签: ruby-on-rails filter spree radiant