如何修改Rails ActiveRecord限制返回记录所用的limit关键字为rows
解决方案
方案1:全局修改Arel SQL生成规则(推荐)
你遇到的是数据库方言语法不兼容问题,最规范的处理方式是重写Arel访问者类中生成Limit语句的逻辑,全局将LIMIT关键字替换为ROWS,一次修改全量生效。
- 在Rails项目的
config/initializers目录下新建初始化文件custom_sql_dialect.rb - 写入以下代码,需将代码中的
PostgreSQL替换为你当前使用的数据库对应的适配器类名(如MySQL对应MySQL,SQL Server对应SQLServer):
module Arel module Visitors class PostgreSQL < Arel::Visitors::ToSql # 重写Limit节点的SQL生成逻辑 def visit_Arel_Nodes_Limit(node, collector) collector << " ROWS " visit node.expr, collector end end end end
修改后重启Rails服务,所有ActiveRecord查询生成的LIMIT语句都会自动替换为ROWS,你可以正常使用SomeModel.find(20)、SomeModel.limit(10)、SomeModel.first等原生方法,不会再出现语法报错。
方案2:针对单个模型自定义查询方法
如果你不想修改全局规则,只想针对访问该旧数据库的模型做兼容,可以直接重写模型的默认查询方法:
class SomeModel < ApplicationRecord # 重写find方法,规避默认LIMIT逻辑 def self.find(id) where(id: id).to_a.first end # 重写first方法,适配非标准分页语法 def self.first(limit_count = nil) result = all.to_a limit_count ? result.take(limit_count) : result[0] end end
修改后你可以正常调用该模型的find、first方法,无需手动写[0]取数据。
方案说明
你当前使用的SomeModel.where(id: 20)[0]方案本质是将所有符合条件的记录全部拉取到Ruby层再取第一条,数据量较大时会有明显性能损耗。上述两种方案均支持在数据库层面完成行数限制,性能更优。
内容的提问来源于stack exchange,提问作者John Small
相关产品推荐
相关产品推荐

