如何重构Ruby模块,获取包含Gem的API命名空间下所有控制器?
解决方案
原代码依赖Rails路由集合获取控制器,Gem中的控制器若未在主应用路由显式挂载,就不会出现在anchored_routes中。要覆盖Gem里的API控制器,需换思路直接从已加载的控制器类中筛选:
重构后的代码
# frozen_string_literal: true module ApiControllers mattr_accessor :list def list return @list if @list @list = ActionController::Base.descendants.select do |controller_class| controller_class.respond_to?(:controller_path) && controller_class.controller_path.start_with?('api/') end.map(&:to_s).uniq end module_function :list end
代码说明
ActionController::Base.descendants:获取所有已加载的、继承自ActionController::Base的控制器类,包含Gem中定义的控制器controller_path.start_with?('api/'):通过控制器的controller_path判断是否属于API命名空间,这和路由配置中的controller参数完全对应,比单纯匹配类名更可靠uniq:避免因类被多次加载导致的重复条目- 返回格式和原代码一致,均为控制器类名字符串数组
注意事项
- 开发环境默认不会预加载所有类,若要获取完整的API控制器列表,可在调用
list前执行Rails.application.eager_load!(生产环境默认已开启预加载) - 若Gem中的控制器是延迟加载的,需确保在调用该方法前已触发其加载逻辑
内容的提问来源于stack exchange,提问作者Anton-Ivanov
相关产品推荐
相关产品推荐

