升级Redmine时旧插件Redmine_out_of_band_auth出现Routes常量未定义错误的求助
兄弟我太懂你这种非Ruby/Rails开发者跟旧插件死磕的憋屈了!花了超多时间还摸不着头脑的感觉真的糟透了,先给你捋捋问题出在哪:
首先,你猜的没错,这个报错确实是因为Zeitwerk(Rails 6+开始用的自动加载器)的原因。Zeitwerk有个规则:它会根据文件名去匹配对应的Ruby常量,你的插件里这个plugins/redmine_out_of_band_auth/app/config/routes.rb文件,Zeitwerk会期望它定义一个Routes常量,但你的文件里只有路由绘制的代码,没有这个常量,所以就报了那个错。
另外,你贴的路由代码本身也有语法问题,这也是旧插件适配新Rails版本的坑:
原来的错误代码:
Rails.application.routes.draw do resources :out_of_band_auth do resources :out_of_band_auths_controller do get :login post :login end end end
这里的resources :out_of_band_auths_controller完全不对,resources是用来定义资源路由的,参数应该是资源名称,不是控制器名称。正确的做法是在resources里用collection或者member来挂载额外的动作,或者直接明确指定路由到控制器的动作。
给你两个可行的修改方案,选一个就行:
方案一:简化的直接路由定义
把routes.rb改成下面这样,直接定义login的GET和POST路由,指向插件的控制器:
# 先加上Zeitwerk需要的Routes常量 module Routes; end Rails.application.routes.draw do # 定义GET请求的login路由,用于显示验证码输入页面 get 'out_of_band_auth/login', to: 'out_of_band_auth#login', as: :out_of_band_auth_login # 定义POST请求的login路由,用于提交验证码验证 post 'out_of_band_auth/login', to: 'out_of_band_auth#login' end
方案二:用resources的collection方式定义
如果你想保留resources的写法,可以改成这样,通过collection来挂载login动作:
# 先加上Zeitwerk需要的Routes常量 module Routes; end Rails.application.routes.draw do # 只定义out_of_band_auth资源,不生成默认的CRUD路由 resources :out_of_band_auth, only: [] do # 在collection下定义login动作,对应GET和POST collection do get :login post :login end end end
改完之后重启Redmine,应该就能解决那个Routes常量未定义的报错,同时路由也能正常工作了。
另外再提个小细节:如果你的插件原来的路由文件是放在app/config下面的,其实更标准的Redmine插件路由位置是插件根目录的config文件夹下,你也可以试试把routes.rb移到redmine_out_of_band_auth/config/下面,这样可能更符合Redmine的插件规范,也能避免Zeitwerk的扫描问题。
备注:内容来源于stack exchange,提问作者user27552065

