Ruby on rails Rails:在运行时为每个请求动态包含帮助程序
我的应用程序是有固定用户和管理员的。它有几个显示小部件的渲染帮助程序:Ruby on rails Rails:在运行时为每个请求动态包含帮助程序,ruby-on-rails,ruby-on-rails-4,actioncontroller,Ruby On Rails,Ruby On Rails 4,Actioncontroller,我的应用程序是有固定用户和管理员的。它有几个显示小部件的渲染帮助程序: module ApplicationHelper def widget "widget" end end 对于管理员,有以下小部件的扩展版本: module AdminHelper def widget "admin-widget" end end 默认情况下,通过config.action\u controller.include\u all\u helpers=false将应用程序配置
module ApplicationHelper
def widget
"widget"
end
end
对于管理员,有以下小部件的扩展版本:
module AdminHelper
def widget
"admin-widget"
end
end
默认情况下,通过config.action\u controller.include\u all\u helpers=false将应用程序配置为不包括所有帮助程序
当管理员查看一个页面(同一个控制器、同一个视图模板)时,我希望通过使用其AdminHelper版本重载帮助程序来呈现该页面的扩展版本。如果当前登录的用户是管理员,如何在每个请求的基础上使用AdminHelper重载ApplicationHelper
我试过了
class ApplicationController < ActionController::Base
before_action :include_backend_helpers
protected
def include_backend_helpers
self.class.helper "pica/backend" if admin_signed_in?
end
end
class ApplicationController
但是,除非在请求之间重新加载ApplicationController,否则这不起作用。尝试动态加载代码以覆盖小部件是错误的做法。相反,小部件
方法应该根据请求决定显示哪个版本。在我们研究一些方法之前,让我们解释一下为什么模块重写不起作用
ApplicationController
在Rails应用程序启动时加载。这将自动包括ApplicationHelper
模块,该模块定义了小部件
方法。由于config.action\u controller.include\u all\u helpers
设置,未加载AdminHelper
,Rails将其设置为false
仅加载与控制器同名的帮助器
当普通用户调用widget
方法时,返回字符串“widget”
。但是一旦管理员访问该站点,include\u backend\u helpers
回调将加载您的AdminHelper
模块,覆盖小部件
方法。管理员得到返回的字符串“admin widget”
,但将来每个访问该站点的访问者都会得到返回!小部件
方法没有根据用户类型进行区分
您可以通过在每次请求后重新加载ApplicationController
来解决此问题,但这需要时间,而且会导致性能下降。但这似乎是一个充满困难的方法。您还可以尝试在每次请求时重新加载帮助程序:
def include_backend_helpers
if admin_signed_in?
self.class.helper "admin/backend"
else
self.class.helper "user/backend"
end
end
但我不确定这是否有效,我也不推荐这样做
取而代之的是,小部件的工作似乎是决定什么是适合显示的。例如,如果这是一个导航组件,它应该足够智能,只显示管理员链接。您仍然可以将其分解为不同的方法:
module ApplicationHelper
def widget
if admin_signed_in?
user_widget
else
admin_widget
end
end
private
def user_widget
"widget"
end
def admin_widget
"admin-widget"
end
end
您可以对Rails部分使用类似的方法-您可以有一个\u navigation.html.erb
部分,其中包括\u user\u navigation.html.erb
或\u admin\u navigation.html.erb
基于admin\u登录?
。您的视图包含“”,不需要担心内部细节
如果您有足够多的代码,上面的内容开始变得笨拙,那么您应该看看。这是一个使构建封装显示组件(控制器逻辑和视图代码的组合)更容易的宝石。感谢您提供详细的答案!我不希望检查每个小部件中的用户角色-这是相当多余的对于我的视图和部分,我只要在管理员登录时预先设置视图路径?
——这样我就可以在必要时逐个覆盖它们;我所缺少的只是一种处理助手的类似优雅方法。如果你有几十个组件,我会尝试找到一些我可以定义的东西然后,在基类中,我将执行类似于m=“admin#{method}”的操作,返回self.call(m)(如果admin#u登录?&&self.respond(m)
在它里面。这似乎是你可以很好地处理的事情。我会尝试一下这个想法,谢谢。对于这个项目,我已经看过了Cells,出于概念上的原因,放弃了它,但我会再试一次。