You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Rails的routes.rb中获取Current.user以简化路由约束?

Rails路由中使用Current.user的公认方案

由于Rails路由的执行早于控制器的before_action,如果你的Current.user是在ApplicationController中设置的,路由阶段自然无法访问到该值。要实现路由中直接判断用户权限,核心是让Current模块能在路由阶段从请求上下文(比如session)中加载用户,以下是几种公认的实现方式:

1. 改造Current模块,支持从Request加载用户

修改Current类,添加从request中直接读取session并加载用户的方法,这样就能在路由约束中调用该方法初始化用户:

# app/models/current.rb
class Current < ActiveSupport::CurrentAttributes
  attribute :user

  class << self
    # 从request中加载用户
    def load_from_request(request)
      return unless request.session[:user_id]
      self.user = User.find_by(id: request.session[:user_id])
    end
  end
end

然后在路由中使用lambda约束:

# config/routes.rb
mount Flipper::UI.app(Flipper) => '/admin/flipper', 
      as: "feature_flags", 
      constraints: ->(request) {
        Current.load_from_request(request)
        Current&.user&.superuser?
      }

2. 封装自定义路由约束类

如果多个引擎都需要相同的权限判断,封装一个可复用的约束类会更简洁,同时在类内部处理用户加载逻辑:

# app/constraints/superuser_constraint.rb
class SuperuserConstraint
  def matches?(request)
    Current.load_from_request(request)
    Current&.user&.superuser?
  end
end

路由中直接引用该类:

# config/routes.rb
mount Flipper::UI.app(Flipper) => '/admin/flipper', 
      as: "feature_flags", 
      constraints: SuperuserConstraint.new

关键注意事项

  • 避免在路由中执行复杂查询:路由阶段应尽量轻量,User.find_by比User.find更安全,避免因无效session ID抛出异常。
  • 保持Current的线程安全:ActiveSupport::CurrentAttributes本身就是线程安全的,无需额外处理多请求并发问题。

内容的提问来源于stack exchange,提问作者iconoclast

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 06:10:55