如果我理解正确,你想要的是能够写:
link_to 'students', students_path
并根据当前用户自动设置部门选项。
这是一个与其他已提供的解决方案类似的解决方案:为需要部门的每条路线定义助手。但是,我们可以以编程方式执行此操作。
开始了:
app/helpers/url_helper.rb
module UrlHelper
Rails.application.routes.routes.named_routes.values.
select{ |route| route.parts.include?(:department) }.each do |route|
define_method :"department_#{route.name}_path" do |*args|
opts = args.extract_options!
if args.size > 0
keys = route.parts - [:department]
opts.merge!(Hash[*keys.zip(args).flatten])
end
opts.reverse_merge!(department: current_user.department.name.downcase)
Rails.application.routes.url_helpers.send(:"#{route.name}_path", opts)
end
end
end
您现在拥有辅助方法,例如department_students_path
每个具有路径:department
段的路线。这些将像students_path
- 您可以传入 opts,甚至可以:department
显式设置它,它将覆盖默认值。他们会及时了解您的更改,routes.rb
而无需您对其进行维护。
您甚至可以将它们命名为与原始助手相同的名称,即
define_method :"#{route.name}_path"
不必在它们前面加上department_
-- 我没有这样做,因为我宁愿避免这样的命名冲突。我不确定它是如何工作的(从视图模板调用它时哪个方法会赢得方法查找),但你可能会调查它。
您当然可以为_url
辅助方法重复此块,因此除了这些方法之外,您还可以使用这些_path
方法。
要使助手在控制器和视图上可用,只需include UrlHelper
在您的ApplicationController
.
所以我认为这符合您的标准:
:department
您可以为默认为' 部门的路径调用辅助方法current_user
,这样您就不必每次都明确指定。
- 帮助程序是通过基于实际定义的具有
:department
段的命名路由的元编程生成的,因此您不必维护它们。
- 就像内置的 rails url_helpers 一样,这些家伙可以将位置参数用于其他路径段,例如
department_student_path(@student)
. 但是,一个限制是,如果您想覆盖部门,您需要在最终的 opts 哈希 ( department_student_path(@student, department: 'math')
) 中这样做。再说一次,在那种情况下,你总是可以这样做student_path('math', @student)
,所以我认为这不是一个很大的限制。