Search code examples
rubysinatrawill-paginatesequel

How to see paging results with Sequel and Sinatra


I am using will_paginate and attempting to page a dataset from Sequel. The requires are:

require 'will_paginate'
require 'will_paginate/sequel'
require 'will_paginate/collection'
require 'will_paginate/version'
require 'sequel/extensions/pagination'

The Ruby code is:

get '/candidate' do
     @items = DB[:candidates].order(:id).extension(:pagination).paginate(1, 10)
     erb :candidate
end

In the view: <%= will_paginate @items %>

The dataset renders correctly with 10 records and when I click "2" or "Next" the address in the browser changes to http://localhost:4567/candidate?page=2 but the records remain the same. Effectively, the results are not paged and I cannot get past page 1.


Solution

  • The numbers for the page and the number of records are hardcoded in your example using paginate(1, 10), so it will always bring back page 1 with 10 records. You need to pass on the page=2 parameter from the query-string. This is done via the params helper:

    get '/candidate' do
      @items = DB[:candidates].order(:id).paginate(:page => params["page"].to_i, :per_page => 10)
      erb :candidate
    end
    

    If you wanted, you could also pass on the per_page in the query-string by adding this code:

    get '/candidate' do
       @items = DB[:candidates].order(:id).paginate(:page => params["page"].to_i, :per_page => params["per_page"].to_i)
       erb :candidate
    end
    

    I'd add a default for both in case they're not given. I understand you can do this via the library, e.g. WillPaginate.per_page = 10, but you could also do this in the route, via:

    get '/candidate' do
      page = params.fetch "page", 1
      per_page = params.fetch "per_page", 10
      @items = DB[:candidates].order(:id).paginate(:page => page.to_i, :per_page => per_page.to_i)
      erb :candidate
    end
    

    I didn't notice before you were also using the Sinatra helper provided by will_paginate.

    I'd either call paginate on the dataset or get a dataset, unpaginated, and pass it to the helper. So either this:

    get '/candidate' do
      page = params.fetch "page", 1
      per_page = params.fetch "per_page", 10
      @items = DB[:candidates].order(:id).paginate(:page => page.to_i, :per_page => per_page.to_i)
      erb :candidate
    end
    
    # in the view
    <%= @items %>
    

    or this:

    get '/candidate' do
      @items = DB[:candidates].order(:id)
      erb :candidate
    end
    
    # in the view
    <%= will_paginate @items, params %>
    

    So, from what I can see, the Sequel paginate method is not overwritten or wrapped/overloaded, so its method signature is the same as it would be if you were just using Sequel and not will_paginate as well. Which means that this code worked for me:

    require 'will_paginate'
    require 'will_paginate/sequel'
    get '/candidate' do
      page = params.fetch "page", 1
      per_page = params.fetch "per_page", 10
      @items = Repo.db[:candidates].order(:id).paginate(page.to_i, per_page.to_i)
      haml :candidate
    end
    

    In the Haml view:

    - @items.each do |i|
      = i[:title]
    

    Since the method signature is the same I'm not sure what advantage you gain from using will_paginate over Sequel's paginate at all. I couldn't find a way to get the Sinatra helper to work.