Rails 7升级至8后Doorkeeper混入模块无法识别问题咨询
问题
我有一个搭载Doorkeeper 5.8.1的Rails 7应用,通过extend ActiveSupport::Concern为Doorkeeper的Application、AccessToken和AccessGrant创建了混入模块。示例代码如下:
# app/models/concerns/my_mixin.rb module MyMixin extend ActiveSupport::Concern included do has_one :other_obj, foreign_key: :id, class_name: "OtherObj" validates :api_key, uniqueness: true, allow_nil: true validates_length_of :api_key, minimum: 32, allow_blank: true end def my_method(input) # do something with input. other_obj.process(input) end end Doorkeeper::Application.include MyMixin
升级至Rails 8后,调用Doorkeeper::Application.my_method(test_input)的单元测试失败,报错信息如下:
NoMethodError:
undefined method 'my_method' for an instance of Doorkeeper::Application
请问Rails 7到8之间是否存在我未注意到的变更?
解决方案
这个问题核心是Rails 8对ActiveSupport::Concern的加载时机和类重新加载机制做了调整,导致混入模块未正确挂载到Doorkeeper模型上。
原因分析
Rails 8默认启用Zeitwerk模式的严格类加载规则,Doorkeeper的模型类改为惰性加载(首次引用时才加载)。原代码在初始化阶段直接执行Doorkeeper::Application.include MyMixin,此时Doorkeeper模型可能还未加载,后续类加载时会覆盖之前的混入操作,导致实例方法丢失。修复步骤
- 调整混入时机:将混入操作移至
config/initializers/doorkeeper_mixin.rb,使用ActiveSupport.on_load钩子确保Doorkeeper模型加载完成后再执行混入:# config/initializers/doorkeeper_mixin.rb require_relative '../../app/models/concerns/my_mixin' ActiveSupport.on_load(:doorkeeper_application) do include MyMixin end # 如需给AccessToken和AccessGrant混入,同理添加: ActiveSupport.on_load(:doorkeeper_access_token) do include MyMixin end ActiveSupport.on_load(:doorkeeper_access_grant) do include MyMixin end - 清理原代码:删除
my_mixin.rb末尾的Doorkeeper::Application.include MyMixin语句,避免重复操作。 - 升级Doorkeeper版本:Doorkeeper 5.8.1发布于2021年,对Rails 8的类加载机制支持不足,建议升级至最新稳定版(至少兼容Rails 8的版本,如6.x系列),确保与Rails 8的类加载逻辑匹配。
- 调整混入时机:将混入操作移至
另外注意,测试代码中若出现DoorKeeper::Application的拼写错误(正确应为Doorkeeper),也可能引发异常,需确认调用时的类名拼写正确。
内容的提问来源于stack exchange,提问作者Jason Meckley
相关产品推荐
相关产品推荐

