如何在Ruby中用sort_by块排序且不转为数组(适配ActiveRecord分页)
解决方案:在数据库层面按姓氏排序(保留ActiveRecord Relation)
sort_by是Ruby端的排序逻辑,会把查询结果转成数组,自然没法用分页方法。要继续用.page,必须让排序逻辑在数据库里执行——用order配合数据库的字符串处理函数就能实现按姓氏排序,而且返回的还是ActiveRecord Relation。
分数据库环境处理:
PostgreSQL:用
split_part函数直接取最后一段schedule_projects.order("split_part(sold_to_name, ' ', -1) ASC")split_part(sold_to_name, ' ', -1)按空格拆分全名,取最后一部分(也就是姓氏),加ASC或DESC控制排序方向,之后直接调用.page即可。MySQL/MariaDB:用
SUBSTRING_INDEX函数取最后分隔后的内容schedule_projects.order("SUBSTRING_INDEX(sold_to_name, ' ', -1) ASC")这个函数会返回空格分隔的最后一段字符串,同样支持后续的分页操作。
SQLite:没有直接的函数,只能用嵌套逻辑处理(适合只有名+姓的情况)
schedule_projects.order("REPLACE(sold_to_name, ' ' || SUBSTR(sold_to_name, 1, INSTR(sold_to_name, ' ')), '') ASC")要是全名里有中间名(多个空格),这个方法会失效,建议换数据库或者提前处理数据。
长期最优方案:拆分字段存储
如果经常要按姓氏排序,最省心的是新增first_name和last_name两个字段,在数据入库时(比如同步API后)拆分全名存进去:
# 模型里加回调,保存时自动拆分 before_save :split_full_name def split_full_name name_parts = sold_to_name.split(' ') self.first_name = name_parts[0...-1].join(' ') # 把中间名也算进名字里 self.last_name = name_parts.last end
之后排序就简单了:
schedule_projects.order(last_name: :asc).page(params[:page])
内容的提问来源于stack exchange,提问作者Jeff Zivkovic
相关产品推荐
相关产品推荐

