ActiveAdmin+Ransack报错:undefined method `table_name' for Arel::Table的排查修复
错误场景
在ActiveAdmin中为Card模型的question文本字段配置包含筛选时:
filter :question, filters: [:cont]
触发如下错误:
undefined method `table_name' for #<Arel::Table:0x00007efe88977f38 @name="cards", @klass=Card(id: integer, deck_id: integer, question: text, created_at: datetime, updated_at: datetime), @type_caster=#<ActiveRecord::TypeCaster::Map:0x00007efe88977df8 @klass=Card(id: integer, deck_id: integer, question: text, created_at: datetime, updated_at: datetime)>, @table_alias=nil>
使用版本:
- ransack: 4.0.0
- activeadmin: 3-0-stable
错误成因
这是ransack 4.0.0与activeadmin 3-0-stable的兼容性问题:
- Ransack 4.x版本对内部查询构建的API做了调整,将部分模型类的调用替换为Arel::Table对象
- ActiveAdmin 3.0稳定版的筛选组件仍沿用旧逻辑,错误地将Arel::Table对象当作ActiveRecord模型类处理,调用了不存在的
table_name方法,导致报错
修复方案
方案一:降级Ransack到兼容版本
修改Gemfile,指定与ActiveAdmin 3.0兼容的Ransack版本:
gem 'ransack', '~> 3.2.0'
执行bundle install更新依赖后,重启服务即可恢复筛选功能。
方案二:自定义筛选器绕过兼容性问题
在ActiveAdmin的Card资源配置中,手动实现包含筛选逻辑,不依赖Ransack的:cont筛选器:
filter :question_cont, label: '问题包含' do |scope, value| scope.where('cards.question LIKE ?', "%#{value}%") if value.present? end
该方式直接使用SQL LIKE语句实现包含查询,避免触发API不兼容的问题。
方案三:升级ActiveAdmin到适配版本
若ActiveAdmin已发布适配Ransack 4.x的新版本(如3.1及以上),可升级ActiveAdmin:
- 修改Gemfile中的activeadmin版本为最新兼容版
- 执行
bundle update activeadmin - 重启服务后测试筛选功能
内容的提问来源于stack exchange,提问作者Nikita Fedyashev

