3

In Rails console, I do:

Video.count 

Returns 4

Video.limit(2)

Returns 2

v   = Video.limit(2)
vv = v.page(1).per(20).count

Returns 4

Why is Kaminari displaying 4 / all records when there is a limit being applied? Shouldn't it return 2 instead?

Christian Fazzini
  • 19,613
  • 21
  • 110
  • 215

3 Answers3

2

If you check the source code for per method you'll see

  # Specify the <tt>per_page</tt> value for the preceding <tt>page</tt> scope
  #   Model.page(3).per(10)
  def per(num)
    if (n = num.to_i) <= 0
      self
    else
      limit(n).offset(offset_value / limit_value * n)
    end
  end

so your code is something like

Video.limit(2).limit(20).count

which gives

irb(main):002:0* Video.count
=> 4
irb(main):003:0> Video.limit(2).count
=> 2
irb(main):004:0> Video.limit(2).limit(4).count
=> 4
irb(main):005:0> Video.limit(4).limit(10).to_sql 
=> "SELECT TOP (10) [Video].* FROM [Video]"

SQL output may be different for different DBMS but count should give same values

Bohdan
  • 8,298
  • 6
  • 41
  • 51
  • Good findings! So lets say I have 100 records in the db. How do I tell Kaminari to paginate, but only for the first 50 records? – Christian Fazzini Oct 13 '11 at 13:46
  • I don't see a way to do it Kaminari uses `limit` so any your custom value will be overridden on pagination. You might use some other gem or implement your own pagination. If you have your values for `page` and `per_page` its quite easy. – Bohdan Oct 13 '11 at 14:14
  • Even will_paginate has the same behaviour. So how would one go about displaying a "Top 50", with pagination. 10 items per page? – Christian Fazzini Oct 14 '11 at 20:03
  • It's the same as displaying all records you just have to delete links to pages with numbers grater than six from rendered HTML. It can be done each time when the pagination is rendered or only if number of records is greater than 50. – Bohdan Oct 17 '11 at 08:50
  • also some filter in action is necessary in case user manually changes page value in URL – Bohdan Oct 17 '11 at 08:54
  • Yea but on the last page, I would still like the pagination to display.. And since we can't limit the pagination items, it will always show pagination link to all items – Christian Fazzini Oct 17 '11 at 10:53
2

If you have 100 videos in the db and you want to paginate only the first 50 records, lets say 25 per page – as an idea you may limit the number of pages in the view.

# videos_controller.rb
def index
  @videos = Video.page(params[:page]).per(25)
end

# index.html.erb
<%= paginate @videos, :num_pages => 2 %>

# index.html.erb using Kaminari 0.14 or higher
<%= paginate @videos, :total_pages => 2 %>

In recent versions of Kaminari (>= 0.14), :num_pages has been renamed to :total_pages. For more information, please refer to https://github.com/errbit/errbit/pull/282 and https://github.com/amatsuda/kaminari/issues/284.

Community
  • 1
  • 1
peresleguine
  • 2,343
  • 2
  • 31
  • 34
0

This is my solution:

Controller:

class Frontend::FirmsController < Frontend::BaseController
  helper_method :max_pages

  def search_with_city
    city = City.find_by_symbol_name(params[:symbol_name])
    raise ActiveRecord::RecordNotFound if city.nil?
    @firms = Firm.in_city(city.id).page(current_page).per(20)
    render 'index'
  end

  def max_pages
    5
  end

  private

  def current_page
    [(params[:page] || 1).to_i, max_pages].min
  end
end

View:

<%= paginate @firms, total_pages: [@firms.total_pages, max_pages].min %>
Xiaohui Zhang
  • 985
  • 8
  • 12