5

我有一条类似的路线:

scope ":department", department: /admin|english|math/, defaults: { department: 'admin' }

是否可以使此路线的默认部门基于current_user.department.name

如果这是不可能的,那么解决我的问题的另一种方法是什么。问题是我希望所有链接都默认为当前范围,除非另有说明。我目前在很多地方做以下事情:

# links to /math/students
link_to 'students', students_path(department: current_user.department.name.downcase)
4

5 回答 5

6

如果我理解正确,你想要的是能够写:

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.

所以我认为这符合您的标准:

  1. :department您可以为默认为' 部门的路径调用辅助方法current_user,这样您就不必每次都明确指定。
  2. 帮助程序是通过基于实际定义的具有:department段的命名路由的元编程生成的,因此您不必维护它们。
  3. 就像内置的 rails url_helpers 一样,这些家伙可以将位置参数用于其他路径段,例如department_student_path(@student). 但是,一个限制是,如果您想覆盖部门,您需要在最终的 opts 哈希 ( department_student_path(@student, department: 'math')) 中这样做。再说一次,在那种情况下,你总是可以这样做student_path('math', @student),所以我认为这不是一个很大的限制。
于 2013-06-14T15:44:57.023 回答
1

路由约束可以接受一个过程,所以你可以用下面的“hack”来解决这个问题:

concern :student_routes do
  # all your routes where you want this functionality
end

# repeat this for all departments
scope ":department", constraints: lambda{|req| req.session[:user_id] && User.find(req.session[:user_id]).department.name.downcase == "english"}, defaults: { department: 'english' } do
  concerns :student_routes
end

路由问题是 rails 4 的一个特性。如果你不使用 rails 4,你可以通过这个 gem 获得这个特性:https ://github.com/rails/routing_concerns 。

您也可以将学生的所有路线复制到所有范围。

于 2013-06-19T14:19:15.230 回答
0

使用嵌套路由怎么样?您可以通过以下方式实现:

resources :departments do
  resources :students
end

如果您想使用友好的 url(例如“math”而不是 id),您可以将以下内容添加到部门模型中:

  # in models/department.rb
  def to_param
    name.downcase
  end

请记住,每个部门的名称必须是唯一的。瑞安 B 对此进行了一次轨道广播。您也可以使用像友好 id这样的宝石。

您现在可以将以下内容添加到您的视图中:

# links to /math/students
link_to 'students', department_students_path(current_user.department)

如果您经常使用它,请创建一个助手:

# helpers/student_helpers.rb
def students_path_for_current_user
  department_students_path(current_user.department)
end

# in view
link_to 'students', students_path_for_current_user
于 2013-06-18T19:05:25.523 回答
0

你可以使用

link_to 'students', polymorphic_path([current_user.department.name.downcase, :students])

这将调用

math_students_path

所以为了工作,我想你应该添加你的路线

scope ':department', as: 'department' do
  ...

askey 生成以下形式的助手:department_something_path

由于该行太长,您可以将其提取给助手

# students path taking into account department
def students_path!(other_params = {}, user = current_user)
  polymorphic_path([user.department.name.downcase, :students], other_params)

然后您将在您的视图中使用

link_to 'students', students_path!
于 2013-06-14T15:39:54.640 回答
0

我最终在ApplicationControllerwith 中指定了它:

def default_url_options(options={})
    {department: current_user.department.name}
end

路径助手将:department自动填充参数,然后......

于 2016-03-27T12:21:24.540 回答