16

In the case where I have the id of a paginated item, how can I find its page number?

I'm using rails 3 and kaminari.

Unfortunately passing the page number as a parameter is not an option. The paginated items are images of an image gallery maintained by user generated content evolving over time. This means an image may appear on page one on week one but page 2 a subsequent week.

Another option would have been maintaining a numeric order of images (acts_as_list), again this is not possible in my case as photos may appear in multiple galleries of varying scopes.

edit:

Have added a bounty to this as I see this same question asked years ago in various places with no solution. I'm happy to accept an sql query if no active record solution comes up.

fl00r
  • 82,987
  • 33
  • 217
  • 237
mark
  • 10,316
  • 6
  • 37
  • 58
  • This could be very inefficient but I *guess* it works https://gist.github.com/885484 (haven't tested it yet), it would be nice to get the result using a query but it seems to be a hard problem, I'd love to see another approach without that loop. – jpemberthy Mar 24 '11 at 17:35
  • Hi and thanks for the answer. That would work but I was hoping more for a query as this would be slow on large collections. – mark Mar 24 '11 at 17:53

3 Answers3

21
# Your "per_page" count
per_page = 30
# Your Image instance:
@image = Image.find_your_image
# SQL. If you're ordering by id, how many lower IDs are there?
position = Image.where("id <= ?", @image.id").count
# Your page
page = (position.to_f/per_page).ceil

Now you can wrap it as a class method

class Image < ActiveRecord::Base
  def page(order = :id, per_page = 30)
    position = Image.where("#{order} <= ?", self.send(order)).count
    (position.to_f/per_page).ceil
  end
end

Usage

@image.page
@image.page(:created_at)
@image.page(:title, 10)
Mauricio Pasquier Juan
  • 2,265
  • 3
  • 27
  • 39
fl00r
  • 82,987
  • 33
  • 217
  • 237
  • Thanks for the reply. I'm sure this will be fine but haven't had a chance to test it out yet as busy on other stuff. – mark Mar 29 '11 at 13:24
  • 1
    Hi again and sorry for delay getting round to this. Your answer works with one correction; to get the position it's necessary to have a <= condition. Thanks for your help. – mark Apr 02 '11 at 19:15
  • One refinement. if you sort by non uniq column results can be wrong . what is working for me - is https://gist.github.com/pironim/5975256 – Volodymyr Jul 11 '13 at 13:03
  • for similar solution check http://stackoverflow.com/questions/13365089/find-page-for-given-record-using-kaminari as well – equivalent8 Dec 10 '13 at 17:13
0

I had the same issue but with but with multiple orders. I only could get it working with a little bad trick.

@model = Model.find(params[:id])
page = 1
  if params[:page]
  page = params[:page]
else
  page = (Model.some_scope.order(some_attribute: :desc, updated_at: :desc).pluck(:id).index(@model.id).to_f / per_page).ceil
end

It only works good if you don't have to many records in the result of the pluck, otherwise it will get slow.

Fabian
  • 275
  • 4
  • 8
0

If you find the page id means it will need the some sql queries. instead of that you can pass the page value as a param. This will increase your performance too.

Ramanavel
  • 408
  • 8
  • 19
  • Thanks Ramanavel. My problem with this is the paginated instance may not always appear on the same page of its associated records. I'll add clarification with regard to this to the question. – mark Mar 25 '11 at 10:40