ryanburnette / rcms

My learning rails project and long term Rails CMS. Not ready for primetime.
0 stars 0 forks source link

Previous/next record #23

Open ryanburnette opened 10 years ago

ryanburnette commented 10 years ago

I usually refer to prev/next links as "adjacent navigation" as you're linking to objects that are adjacent according to the current sort order.

I found this solution on StackOverflow which isn't great, but with a little tweaking it gave me a working solution when sorting by id or date. I want a more robust way to be able to take a model and scope and get what would come before or after in that context.

One solution that would work would involve retrieving many records to figure out which objects come before and after, but I wish there were a more elegant solution.

paulelliott commented 10 years ago

Kaminari should handle the adjacent navigation links for you. Is it not?

ryanburnette commented 10 years ago

I briefly looked into doing this with Kaminari but I'll try that again.

ryanburnette commented 10 years ago

I looked again and I don't see an immediate way that Kaminari will do this. It handles links for previous and next page in terms of pagination context, but if I'm on a single view for a page for example and want to determine what the previous and next records would be var a particular scope, I don't have an answer.

I've done this many times in PHP projects. I always ended up getting all the objects with a particular query then iterating them to find out which was was before and after in that context.

For now I used a really simple query to create scopes, but this doesn't work that well. There are dozens of Stack Overflow posts showing folks doing it this way, but it looks pretty fragile.

def previous_by_date
  Post.where("date <= ? AND id <> ?", self.date, self.id).by_date.first
end

def next_by_date
  Post.where("date >= ? AND id <> ?", self.date, self.id).by_date.last
end
ryanburnette commented 10 years ago

You can really see the flaw when you translate this method over to my popular scope. When it comes to dates you'll rarely have the same datetime on two posts, so these scopes work well enough. But with play counts a lot of them are 0. So you often fetch something you didn't expect in the popular scope.

def previous_by_popularity
  Post.where("plays_count <= ? AND id <> ?", self.plays_count, self.id).popular.first
end

def next_by_popularity
  Post.where("plays_count >= ? AND id <> ?", self.plays_count, self.id).popular.last
end