Rails表单中能否对已构建的关联记录集合进行排序?
如何按关联集合的属性排序CakeDetails
嘿,我明白你现在的困境——每次尝试排序关联属性集合都会踩不同的坑,我来帮你捋清楚可行的方案!
首先看你的代码:你先确保每个Size都对应一个CakeDetail(不存在就build新的),然后想对@cake.cake_details排序。这里的核心问题是:ActiveRecord的order方法只对数据库中已保存的记录生效,而你build的新CakeDetail还在内存里,不会被order语句处理,所以直接用@cake.cake_details.order(:size_id)会导致新对象排序混乱。
下面给你两种针对性的解决方案:
方案1:按size_id排序(包含未保存的新记录)
把关联集合转成数组,用Ruby的sort_by方法对所有记录(已保存+未保存)统一排序:
def edit Size.all.each do |size| unless @cake.sizes.exists?(size.id) @cake.cake_details.build(size_id: size.id, price: nil) end end # 转数组后按size_id排序,覆盖所有记录 @cake_details_collection = @cake.cake_details.to_a.sort_by { |detail| detail.size_id } end
这个方法简单直接,不管记录是否保存,都能按size_id的数值顺序排列。
方案2:按Size模型的其他属性排序(比如名称、自定义排序位)
如果你不想只按size_id,而是想按Size本身的属性(比如name或者position字段)排序,只需要调整sort_by的依据:
# 按Size的名称排序(处理可能的nil情况) @cake_details_collection = @cake.cake_details.to_a.sort_by { |detail| detail.size&.name } # 按Size的自定义排序位(比如数据库里的position字段) @cake_details_collection = @cake.cake_details.to_a.sort_by { |detail| detail.size&.position }
这里用&.是为了避免万一Size不存在时出现报错,让代码更健壮。
补充:只对已保存记录排序(数据库层面)
如果你的场景不需要包含未保存的新记录,也可以直接在数据库层面通过关联查询排序,性能会更好:
# 按Size的名称排序已保存的CakeDetail @cake_details_collection = @cake.cake_details.joins(:size).order('sizes.name ASC')
但这个方法只适用于已经存在数据库里的记录,新build的对象不会被包含进来。
内容的提问来源于stack exchange,提问作者jimgug
相关产品推荐
相关产品推荐

