# Complex pagination issue

**URL:** <https://www.ruby-forum.com/t/complex-pagination-issue/137975>\
**Category:** Rails\
**Created:** [May 19, 2008, 6:37am UTC](https://www.ruby-forum.com/t/complex-pagination-issue/137975 "2008-05-19T06:37:59Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Danimal](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/bb73d2/32.png) [@Danimal](https://www.ruby-forum.com/u/Danimal)\
**Post date:** [May 19, 2008, 6:37am UTC](https://www.ruby-forum.com/t/complex-pagination-issue/137975/1 "2008-05-19T06:37:59Z")

</div>

I wonder if anyone can give me some direction.

I’m trying to figure out how to handle pagination when I have a very  
complex way of building up a collection of objects. I’ve used the old  
classic pagination before, and I’ve used will\_paginate, but I don’t  
think either will work in my case.

Briefly, I have a Location model that defines a physical location. I  
then build up a list of @locations by a variety of “filters”… for  
example, a text-based search query plus a geolocation radial search,  
plus one or more category selections. Underneath the hood, these are  
each separate queries that build a list of location objects. I then  
merge the results into a single instance variable: @locations, which  
is the array of matched Location objects.

Now, I wanna paginate that.

I suppose one option might be for me to try and build the thing into a  
single, monster SQL query that I can then add some LIMIT fields to…  
but for now, let’s assume that’s not an option. (I shiver at the  
complexity of it. oy!)

So… is there anything I can do with an existing set? Can  
will\_paginate support that? (I’m thinking no, but I figured I’d ask).  
I think the classic\_pagination plugin can, but I’m not really sure  
how.

Help?

-Danimal

---

<div class="post-metadata">

**Author:** ![Danimal](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/bb73d2/32.png) [@Danimal](https://www.ruby-forum.com/u/Danimal)\
**Post date:** [May 19, 2008, 7:06am UTC](https://www.ruby-forum.com/t/complex-pagination-issue/137975/2 "2008-05-19T07:06:40Z")

</div>

Never mind.

I was gonna just delete this post as I figured it out, but I’ll leave  
it and post my solution in case it helps anyone else.

Turns out will\_paginate can handle this. You just wrap your Array with  
a WillPaginate::Collection and split it manually into the “windows”  
needed/desired for pagination.

Here’s my code snippit. I start with @locations being the full array  
of matched locations. Then…

```auto
  page = (params[:page] ||= 1).to_i
  PAGE_SIZE = 10 # could be defined somewhere global
  offset = (page - 1) * PAGE_SIZE
  @locations = WillPaginate::Collection.new(page, PAGE_SIZE,
"#{@locations.length}").concat(@locations[offset..(offset + PAGE_SIZE
- 1)])
```

Then, I just use the normal: \<%= will\_paginate @locations %\> code in  
my view and voila! Instant pagination! Whee!

“Dang, that was easy.” \<-- me, about so many things of the Rails  
persuasion.

-Danimal

---

<div class="post-metadata">

**Author:** ![Danimal](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/bb73d2/32.png) [@Danimal](https://www.ruby-forum.com/u/Danimal)\
**Post date:** [May 19, 2008, 7:13am UTC](https://www.ruby-forum.com/t/complex-pagination-issue/137975/3 "2008-05-19T07:13:42Z")

</div>

Getting the final @locations variable looks complicated to me, is this  
something you had to code for the solution to work, or is this how  
you’ve  
been using will\_paginate from the beginning?

---

<div class="post-metadata">

**Author:** ![Danimal](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/bb73d2/32.png) [@Danimal](https://www.ruby-forum.com/u/Danimal)\
**Post date:** [May 19, 2008, 1:40pm UTC](https://www.ruby-forum.com/t/complex-pagination-issue/137975/4 "2008-05-19T13:40:29Z")

</div>

If the @locations collection is that complicated to assemble you might  
also want to introduce some caching on the results. Unless I  
misunderstand what you’re doing it appears that you are going to have  
to calculate that collection on every page request and then select the  
appropriate results to return.

On May 19, 1:12 am, “Ryan B. (Radar)” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

---

<div class="post-metadata">

**Author:** ![Danimal](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/bb73d2/32.png) [@Danimal](https://www.ruby-forum.com/u/Danimal)\
**Post date:** [May 22, 2008, 7:35pm UTC](https://www.ruby-forum.com/t/complex-pagination-issue/137975/5 "2008-05-22T19:35:30Z")

</div>

Quoting D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> Here’s my code snippit. I start with @locations being the full array
> 
> Then, I just use the normal: \<%= will\_paginate @locations %\> code in  
> my view and voila! Instant pagination! Whee!

Here is an even simpler way:

```auto
    @locations = WillPaginate::Collection.create(page, PAGE_SIZE,
         locations.size) do |pager|
      pager.replace(locations[pager.offset,
            [pager.per_page, locations.size].min])
    end
```

locations is the full array of locations, @locations is the WillPaginate  
object.

HTH,  
Jeffrey

P.S. not tested or guaranteed to work. I copy and pasted it from  
working code  
with editing of variables to match your code.

---

<div class="post-metadata">

**Author:** ![Danimal](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/bb73d2/32.png) [@Danimal](https://www.ruby-forum.com/u/Danimal)\
**Post date:** [May 23, 2008, 1:55am UTC](https://www.ruby-forum.com/t/complex-pagination-issue/137975/6 "2008-05-23T01:55:08Z")

</div>

Jeffrey,

Thanks for the refactor! I like the block style! I’ll have to  
incorporate that. Nice & clean.

-Danimal

On May 22, 11:34 am, “Jeffrey L. Taylor” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

---

<div class="post-metadata">

**Author:** ![Danimal](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/bb73d2/32.png) [@Danimal](https://www.ruby-forum.com/u/Danimal)\
**Post date:** [May 19, 2008, 4:49pm UTC](https://www.ruby-forum.com/t/complex-pagination-issue/137975/7 "2008-05-19T16:49:40Z")

</div>

It was coded that way because of the application needs. Ultimately,  
it’s that I have a potentially large set of Location objects and the  
end-user can choose one or more methods of “whittling” that set down  
(search, geolocation, categories, etc). So I have mulitple, complex  
finds that AND or OR merge together for a final results set. And that  
final set is what I need to paginate.

It may be worth a refactor attempt, but I think I might just have to  
live with it as-is and just do as much performance enhancements as I  
can… i.e. like caching as Andy suggested.

-Danimal

On May 18, 11:12 pm, “Ryan B. (Radar)” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)
