使用Pagy gem时触发undefined method `model_name' for #Array报错如何解决
Rails Pagy分页报错undefined method `model_name' for Array 排查
报错根因
- 你的查询语句末尾调用了Ruby原生方法
sort_by(&:id),该方法会将ActiveRecord::Relation查询对象直接转换为普通数组,丢失了ActiveRecord模型的元数据方法(比如model_name) - 自定义的
pagy_get_vars方法调用了collection.model_name获取模型i18n键,普通数组不具备该方法,直接触发报错 - 额外隐患:数组的
count方法不支持传参,你写的collection.count(:all)后续也会触发新的报错
解决方案
方案1:改为数据库层排序(推荐)
将sort_by(&:id)替换为ActiveRecord提供的order方法,全程保持Relation对象状态,无需转换数组,性能更高也符合Pagy的设计预期:
# data_controller.rb index方法修改后代码 def index @pagy, @datas = pagy(Data.active_only.where(data_location: @location).order(:id)) end
修改后无需调整其他代码即可解决问题。
方案2:适配Ruby层排序场景(仅用于SQL无法实现的复杂排序逻辑)
如果必须在Ruby层完成排序,可以通过以下两种方式适配:
方式A:修改pagy_get_vars方法兼容数组场景
# application_controller.rb修改后代码 def pagy_get_vars(collection, vars) # 兼容Relation和数组两种入参类型 count = collection.is_a?(ActiveRecord::Relation) ? collection.count(:all) : collection.count item_path = if collection.is_a?(ActiveRecord::Relation) "activerecord.models.#{collection.model_name.i18n_key}" else # 数组场景指定对应模型的i18n键即可 "activerecord.models.data" end { count: count, page: params[vars[:page_param]||Pagy::VARS[:page_param]], item_path: item_path }.merge!(vars) end
方式B:分页时手动传入缺失参数
# data_controller.rb index方法修改后代码 def index relation = Data.active_only.where(data_location: @location) sorted_datas = relation.sort_by(&:id) # 手动传入count和item_path,覆盖pagy_get_vars的自动读取逻辑 @pagy, @datas = pagy(sorted_datas, count: relation.count, item_path: "activerecord.models.data") end
注意:Ruby层排序会将全量数据加载到内存再分页,数据量大时性能损耗极高,非必要不建议使用。
内容的提问来源于stack exchange,提问作者And24
相关产品推荐
相关产品推荐

