我希望我仍然不知道如何实现元编程。
对于从我的Admin :: Base控制器呈现的视图,我想覆盖位于ActionView :: Helpers :: AssetTagHelper下的Rails compute_public_path
,以便我所有管理员的布局文件都在public / admin下。
可能有更好的方法,但此时我想学习如何这样做。
我把它放在Admin :: Base控制器中:
module ActionView::Helpers::AssetTagHelper
def compute_public_path(source, dir, ext = nil, include_host = true)
super(source, "admin/#{dir}", ext = nil, include_host = true)
end
end
但它给了我:
super: no superclass method `compute_public_path' for #<ActionView::Base:0x1032240a8>
这并不让我感到惊讶。
如果我在我的管理员助手中尝试此操作:
def compute_public_path_with_admin(source, dir, ext = nil, include_host = true)
compute_public_path_without_admin(source, "admin/#{dir}", ext, include_host)
end
alias_method_chain :compute_public_path, :admin
我得到模块“AdminHelper”的“未定义方法'compute_public_path'”,我猜这是因为compute_public_path
是私有方法。
我发现这有效:
ActionView::Helpers::AssetTagHelper.class_eval do
def compute_public_path_with_admin(source, dir, ext = nil, include_host = true)
compute_public_path_without_admin(source, "admin/#{dir}", ext, include_host)
end
alias_method_chain :compute_public_path, :admin
end
只要我将config.cache_classes
设置为false
,否则会出现堆栈级错误。
感谢Squeegy让我指向了正确的方向。
如何通过禁用类缓存来实现此功能?
答案 0 :(得分:1)
def compute_public_path_with_admin(source, dir, ext = nil, include_host = true)
compute_public_path_without_admin(source, "admin/#{dir}", ext, include_host)
end
alias_method_chain :compute_public_path, :admin
compute_public_path
现在将调用您的实现,然后调用原始实现。
答案 1 :(得分:0)
请不要这样做。
接受的答案将得到您想要的,但您想要的可能会产生危险的安全隐患。
为什么您希望管理员布局位于public
下? Rails默认情况下将其置于app/views/layouts
之下的原因是:没有人能够在那里阅读其来源。
如果你把它们放在public
中,它们基本上对任何访问者都是可读的。
如果您将它们放在所属的位置,则不会公开您的布局代码。最重要的是,您可以按照任何方式构建app/views/layouts
,而无需任何元编程,即无需破解框架内部。