简体   繁体   中英

Ruby on Rails - Order records by created_at and sort_by by boolean

I'm trying to loop over my posts and order('created_at DESC') and sort by pinned (which is a boolean ) .

How is it possible to order records by created_at and sort with pinned so pinned posts come on top.

I've tried with the following, but the sorting gets massed up and is no longer ordered by created_at or if I try to add the sort_by at the end, the pagination would stop work.

posts = Post.active.order('created_at DESC').page(params[:page]).per(25)
@posts = posts.sort_by { |post| [post.pinned ? 0 : 1, post] }

I have also tried the following with no luck:

@posts = Post.active.order('created_at DESC').page(params[:page]).per(25)
// In my view
- @posts.sort_by { |post| [post.pinned ? 0 : 1, post] }.each do |post|

This will produce an error for the pagination

posts = Post.active.order('created_at DESC').sort_by { |post| [post.pinned ? 0 : 1, post] }.page(params[:page]).per(25)

Any tips are appreciated!

Max 的回答是要走的路,他的评论中唯一缺少的是将它包装在 Arel.sql 中

posts = Post.active.order(Arel.sql("CASE WHEN pinned THEN 0 ELSE 1 END"), "created_at DESC"))

As an alternative you can construct the query with Arel::Nodes::Case instead of a string:

class Post < ApplicationRecord
  def self.pinned_on_top
    kase = Arel::Nodes::Case.new(arel_table[:pinned])
    order(
      kase.when(1).then(0).else(1)
    )
  end
end
# Given the following
Post.create(pinned: true)   # id: 1
Post.create(pinned: false)  # id: 2
Post.create(pinned: true)   # id: 3

Post.pinned_on_top.order(created_at: :desc).ids # 3, 1, 2

The key advantage is portability.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM