Rails 5.1.7升级后如何修复`uninitialised constant 'ActiveRecord_Relation'`错误?
解决Rails 5.1升级后
BusinessType::ActiveRecord_Relation未定义的问题 这个问题是Rails 5.1对ActiveRecord关联对象的类结构做了核心改动导致的——在Rails 5.0中,每个模型的Relation对象会动态生成一个嵌套的Model::ActiveRecord_Relation类,但Rails 5.1移除了这个机制,所有Relation对象统一使用顶层的ActiveRecord::Relation类,仅通过内部属性关联对应的模型。
解决方案:修改测试中的类型匹配逻辑
你需要把测试里的kind_of(BusinessType::ActiveRecord_Relation)替换为对ActiveRecord::Relation的检查,同时验证其关联的模型是BusinessType。有几种简洁的写法可以实现:
方法1:用satisfy匹配器验证模型类
修改测试代码如下:
describe 'GET #index' do it 'initialises the view model with the correct arguments' do expect(BusinessTypes::Index).to receive(:new) .with( an_instance_of(ActiveRecord::Relation).and(satisfy { |rel| rel.model == BusinessType }), user, address_confirmed: true ) get :index end context 'user has not confirmed his address' do let(:user) { create(:user, address_confirmed_at: nil) } it 'initialises the view model with the correct arguments' do expect(BusinessTypes::Index).to receive(:new) .with( an_instance_of(ActiveRecord::Relation).and(satisfy { |rel| rel.model == BusinessType }), user, address_confirmed: false ) get :index end end end
方法2:用have_attributes匹配器简化写法
如果你更喜欢更紧凑的表达,可以直接检查Relation内部的klass属性(和model方法等价,用于存储关联的模型类):
.with( kind_of(ActiveRecord::Relation).and(have_attributes(klass: BusinessType)), user, address_confirmed: true )
验证改动的合理性
你可以在Rails 5.1的控制台里快速验证这个变化:
# 查看Relation对象的实际类 BusinessType.all.class # => ActiveRecord::Relation # 查看关联的模型类 BusinessType.all.model # => BusinessType BusinessType.all.klass # => BusinessType
而在Rails 5.0中,BusinessType.all.class会返回BusinessType::ActiveRecord_Relation,这就是旧测试在升级后失效的核心原因。
额外优化:封装自定义匹配器
如果项目中有多处类似的测试,可以封装一个自定义RSpec匹配器,让代码更整洁:
RSpec::Matchers.define :be_a_relation_of do |expected_model| match do |actual| actual.is_a?(ActiveRecord::Relation) && actual.model == expected_model end end
之后就能在测试里直接用be_a_relation_of(BusinessType),替代冗长的匹配逻辑。
内容的提问来源于stack exchange,提问作者edmunteanu
相关产品推荐
相关产品推荐

