如何在Rails关联查询中实现关联记录按指定固定顺序排序?
实现方案
方案1:关联默认按自定义规则排序(调用article.tags直接返回正确顺序)
先在Tag模型定义固定排序常量,再修改Article的关联规则,加上排序逻辑:
class Tag < ActiveRecord::Base # 固定标签排序规则,调整顺序直接修改该数组即可 SORT_ORDER = %w[Foo Bar Baz Hello World].freeze end class Article < ActiveRecord::Base has_many :tag_associations, dependent: :destroy has_many :tags, -> { order_sql = Arel.sql( "CASE tags.name " + Tag::SORT_ORDER.each_with_index.map { |name, idx| "WHEN '#{name}' THEN #{idx}" }.join(" ") + " END ASC" ) order(order_sql) }, through: :tag_associations end
说明:用
Arel.sql包裹原生SQL片段是Rails 5+的规范写法,可以避免SQL注入安全警告。如果后续新增了不在SORT_ORDER里的标签,会默认排在现有标签后面。
方案2:独立Scope灵活调用(不需要默认排序时可选)
如果不需要每次查关联标签都走自定义排序,可以把排序逻辑封装成Tag的独立Scope,按需调用:
class Tag < ActiveRecord::Base SORT_ORDER = %w[Foo Bar Baz Hello World].freeze scope :sorted_by_custom_rule, -> { order_sql = Arel.sql( "CASE name " + SORT_ORDER.each_with_index.map { |name, idx| "WHEN '#{name}' THEN #{idx}" }.join(" ") + " END ASC" ) order(order_sql) } end # 调用方式 article.tags.sorted_by_custom_rule
方案3:Ruby内存层面排序(仅适用于已加载的标签数组)
如果已经把标签查询出来拿到了数组对象,可以直接用Ruby方法排序:
# 示例:对已经加载的tags数组排序 sorted_tags = article.tags.sort_by { |tag| Tag::SORT_ORDER.index(tag.name) || Float::INFINITY }
内容的提问来源于stack exchange,提问作者Alien
相关产品推荐
相关产品推荐

