Rails: How to sort many-to-many relation

前端 未结 3 638
攒了一身酷
攒了一身酷 2021-01-29 04:10

I have a many-to-many relationship between a model User and Picture. These are linked by a join table called Picturization.

If I obtain a list of users of a single pict

相关标签:
3条回答
  • 2021-01-29 05:02

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

    picture.users.order("picturizations.created_at DESC")
    
    0 讨论(0)
  • 2021-01-29 05:04

    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'
    
    0 讨论(0)
  • 2021-01-29 05:16

    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
    
    0 讨论(0)
提交回复
热议问题