Rails: How to sort many-to-many relation

折月煮酒 提交于 2019-12-02 11:34:28
Firoz Ansari

Have an additional column something like sequence in picturization table and define sort order as default scope in your Picturization

default_scope :order => 'sequence ASC'

If you want default sort order based on modified_at then use following default scope

default_scope :order => 'modified_at DESC'

You can specify the table name in the order method/clause:

picture.users.order("picturizations.created_at DESC")

Well, in my case, I need to sort many-to-many relation by a column named weight in the middle-table. After hours of trying, I figured out two solutions to sort many-to-many relation.

Solution1: In Rails Way

picture.users.where(:order => "created_at")

cannot return a ActiveRecord::Relation sorted by Picturization's created_at column.

I have tried to rewrite a default_scope method in Picturization, but it does not work:

def self.default_scope
  return Picturization.all.order(weight: :desc)
end  

Instead, first, you need to get the ids of sorted Picturization:

ids = Picturization.where(user_id:user.id).order(created_at: :desc).ids

Then, you can get the sorted objects by using MySQL field functin

picture.users.order("field(picturizations.id, #{ids.join(",")})")

which generates SQL looks like this:

SELECT `users`.* 
FROM `pictures` INNER JOIN `picturizations` 
ON `pictures`.`id` = `picturizations`.`picture_id` 
WHERE `picturizations`.`user_id = 1#for instance 
ORDER BY field(picturizations.id, 9,18,6,8,7)#for instance

Solution2: In raw SQL Way

you can get the answer directly by using an order by function:

SELECT `users`.* 
FROM `pictures` INNER JOIN `picturizations` 
ON `pictures`.`id` = `picturizations`.`picture_id` 
WHERE `picturizations`.`user_id = 1

order by picturizations.created_at desc
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!