I have a Post model and a View model (which logs the view of each post by a user) as follows:
class View < ActiveRecord::Base
belongs_to :user, :class_name => 'User'
belongs_to :post, :class_name => 'Post'
validates_uniqueness_of :user_id, :scope =>:post_id
end
Each post has a boolean field named “special”.
I want to fetch all posts with following sort conditions:
- If a post is ‘special’ AND NOT VIEWED by the current user (say user_id=2), then that should appear on top in the result, internally sorted by id in descending order).
- Sort all other posts (not special and viewed-special) on the basis of id field for the posts.
Cant figure out if and how I can do that.
To start with, I tried the following query:
posts = Post.order("(case when special = true then 'special desc, id desc' else 'id desc' end)")
But it behaves in a funny manner: returns all special posts in top followed by regular posts but with ids sorted in ascending order.
What am i missing here? Also, how can I use join (for views table) with such a complex order by clause? I tried to write a SQL for this but struggling there also! Show me some light 🙂
P.S I’m new to Rails and still learning.
The code you posted is, for each row computing one of 2 string literals and ordering based on that which is why you don’t get the examples you want.
I’d do something like
Since rails stores boolean fields as 0/1 in MySQL this will sort special posts ahead of non special posts.
Adding views to this doesn’t change a whole lot: you need to left join the views table and do something like
The
is nulldetects whether a view was found which is then and-ed with the post’s specialness.