Thursday, August 19, 2010

Active Record And Will Paginate for Non-Rails Application

I'm new to Sinatra and I want to use it together with Active Record and Will Paginate. After hours searching, I've finally found out to use active_record and will_paginate for non Rails application. Before I explain use Active Record and Will Paginate for non-Rails app, I assume that you use bundler and your database migration is already setup and working.

Step 1. Gemfile
First thing first, edit your Gemfile.
# Gemfile
source :rubygems
gem 'sinatra', '1.0.0', :require => 'sinatra/base'
gem 'activerecord', '3.0.0.rc', :require => 'active_record'
gem 'haml'
gem 'will_paginate', :git => 'git://github.com/mislav/will_paginate.git', 
  :tag => 'v3.0.pre2', 
  :require => 'will_paginate/finders/base'

Step 2. Edit Your Model
You must extend your class model with Will Paginate module.
# your_model.rb
class Article < ActiveRecord::Base
  extend WillPaginate::Finders::Base
end
Step 3. Edit your Sinatra Application Because Will Paginate helper does not work with Sinatra Application, so you need to write your own helper.
# your_sinatra_app.rb
require 'rubygems'
require 'bundler/setup'
Bundler.require :default
require 'your_model.rb'

class Application < Sinatra::Base
  get '/' do
    @articles = Article.order("created_at desc").
      paginate :page => params[:page], :per_page => 10
    haml :articles
  end

  helpers do
    # helper for pagination
    def paginate(resources)
      if !resources.next_page.nil? and !resources.previous_page.nil?
        html = "« Prev "
        html += "#{params[:page]} of #{resources.total_pages} "
        html += "Next »"
      elsif !resources.next_page.nil? and resources.previous_page.nil?
        html = "Next »"
      elsif resources.next_page.nil? and !resources.previous_page.nil?
        html = "« Prev "
        html += "#{params[:page]} of #{resources.total_pages}"
      end
      return html
    end
  end
end
Step 4. Edit Your View
# views/articles.haml
%div
  %header
    %h2
      Article list
  .content
    %table
      %thead
        %tr
          %th
            Title
          %th
            Content
          %th
            Author
      %tbody
        - @articles.each do |article|
          %tr
            %td
              = article.title
            %td
              = article.content
            %td
              = article.author
        = paginate @articles
Done. Sinatra, Will Paginate, and Active Record are ready to use. Note: The above code is extracted from my Sinatrails project, feel free to use it.

Update:
Here is an update for step 3:
http://pastie.org/1194928

5 comments:

  1. I changed this a bit for my need which was having a search facility that needed the params in the pagination links

    So I changed the helper a bit and took a stringify hash function from merb

    helpers do
    # helper for pagination
    def paginate(resources,options)

    params=to_params( options[:params])
    p params.class
    p params

    if !resources.next_page.nil? and !resources.previous_page.nil?
    html = %^ << Prev ^
    html += "#{params[:page]} of #{resources.total_pages} "
    html += %^Next>>^
    elsif !resources.next_page.nil? and resources.previous_page.nil?
    html = %^Next>>^
    elsif resources.next_page.nil? and !resources.previous_page.nil?
    html = %^ << Prev ^
    html += "#{params[:page]} of #{resources.total_pages}"
    end
    return html
    end
    end

    There may be a better way to do this, as i am just beginning to learn programming and all, so any suggestions are welcome :)

    ReplyDelete
  2. the above comment got html contents which didn't go well

    so here it is http://pastie.org/1192729

    ReplyDelete
  3. Nice. I already applied your code for my Sinatrails project - http://bit.ly/b6CNgV .
    Thanks for sharing your code, Krishna.

    ReplyDelete
  4. @krishna: I modified a bit your code and here is the final version: http://pastie.org/1194928

    ReplyDelete
  5. oh that's a cool way to do..thank you will add that to my code too :)

    ReplyDelete

© Railsmine