Using a paginate method to display the second group of 25 records on page 2

Hey all,

I’m trying to fully understand what this method in Ruby does. Basically
it passes a collection of records from the database (using the Rails
find method) into the argument list as a local variable called
resources. It assigns the local variable to an instance variable called
@all_resources. Then it checks the query string in the url to see if the
limit key has a value and if so grab it(e.g. ?limit=10), otherwise
default to 25. Then it checks the query string for a page key and if
none is there, it defaults to 1 and assigns it to instance variable
@page. Then we subtract 1 from @page, presumably because if we are on
page 1, then 1 -1 = 0, so 0 is assigned to @page_index. This means when
we multiply page_index by 25 (limit), we get 0, and so when we slice the
resources we slice the limit (25) by offset (0), and hence we return the
first 25 records, making sense since we want to display first 35 records
on page 1. However, if $page is equal to 2 and limit 25, then
page_index is equal to 1, and offset equal to 25. But I dont see how we
are getting the next 25 records on page 2.

I think what’s confusing me is this line of code:

((@all_resources.size - 1) / @limit).to_i + 1

What does the size method do and why add one at the end?

Here’s the method:

def paginate(resources)
@all_resources = resources
@limit = (params[:limit] && params[:limit].to_i) || 25
@page = (params[:page] && params[:page].to_i) || 1
@page_index = @page - 1
@offset = @page_index * @limit
@num_pages = if @limit == 0
1
elsif @all_resources.size == 0
1
else
((@all_resources.size - 1) / @limit).to_i + 1
end
@last_page = @num_pages
@limit == 0 ? @all_resources : @all_resources.slice(@offset, @limit)
end

Thanks for response

On 25 March 2011 20:33, John M. [email protected] wrote:

@page. Then we subtract 1 from @page, presumably because if we are on
page 1, then 1 -1 = 0, so 0 is assigned to @page_index. This means when
we multiply page_index by 25 (limit), we get 0, and so when we slice the
resources we slice the limit (25) by offset (0), and hence we return the
first 25 records, making sense since we want to display first 35 records
on page 1. However, if $page is equal to 2 and limit 25, then
page_index is equal to 1, and offset equal to 25. But I dont see how we
are getting the next 25 records on page 2.

Have a look at the Rails Guide on debugging and find out how to use
ruby-debug to break into the code and inspect data. Then break in at
the appropriate points and see what is happening. By a combination of
examining variables, entering expressions for evaluation to see what
the results are and stepping through the code you should see how (if)
it works.

I think what’s confusing me is this line of code:

((@all_resources.size - 1) / @limit).to_i + 1

What does the size method do and why add one at the end?

The size method is Array#size and returns the number of elements in
the array, ie the number of records in @all_resources in this case.

Colin

John M. wrote in post #989291:

((@all_resources.size - 1) / @limit).to_i + 1

What does the size method do and why add one at the end?

Suppose 100 records, with a page size of 30

num_pages = ((100-1)/30)
num_pages = 99/30
num_pages = 3.3
num_pages = 3 (to_i)
num_pages = 4

3 full pages of 30 records, and 1 page with 9 records

Suppose 90 records…
((90-1)/30).to_i + 1 = 3, 3 full pages

It’s just some math hijinks to make sure any partial page isn’t missed
in the page count.

The slice(offset,limit) is the elegant part. Start at the “offset”, and
return “limit” items.

On page 2, the offset is 1*25, skipping the records that would be
returned on page 1, and returns the next page’s records.

Suppose 90 records…
((90-1)/30).to_i + 1 = 3, 3 full pages

It’s just some math hijinks to make sure any partial page isn’t missed
in the page count.

Thanks that was very helpful.

On Mar 25, 4:33pm, John M. [email protected] wrote:

elsif @all_resources.size == 0
1
else
((@all_resources.size - 1) / @limit).to_i + 1
end
@last_page = @num_pages
@limit == 0 ? @all_resources : @all_resources.slice(@offset, @limit)
end

BTW, if you found this in production code, I’d highly recommend
KILLING IT WITH FIRE and using something like will_paginate if at all
possible - this is the quite-ancient original pagination code included
with Rails (stripped out to the classic_pagination plugin in 1.2.4!)
and is immensely inefficient. The Rails version of your code really
doesn’t matter; I just got will_paginate up and running on an old
1.2.3 app without any major issues.

–Matt J.