Created
July 29, 2010 13:54
-
-
Save karmi/498177 to your computer and use it in GitHub Desktop.
WillPaginate adapter for paginating CouchPotato views
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # = WillPaginate adapter for CouchPotato views | |
| # | |
| # Pagination for CouchPotato[http://github.com/langalex/couch_potato] views | |
| # compatible with the will_paginate[http://github.com/mislav/will_paginate] gem. | |
| # | |
| # See http://github.com/mislav/will_paginate/blob/rails3/lib/will_paginate/finders/data_mapper.rb | |
| # for example adapter. | |
| # | |
| # Just `require` this file in your code and you'll have the `paginate` method available. | |
| # | |
| # TODO: Research if pagination can be done via "fast pagination" as described in | |
| # http://books.couchdb.org/relax/reference/recipes#Pagination. | |
| # We need the "Jump to Page" functionality for WillPaginate. | |
| # | |
| # TODO: Make ordering work (descending=true, have to flip startkey/endkey etc) | |
| # | |
| require 'rubygems' | |
| require 'will_paginate/finders/base' | |
| require 'couch_potato' | |
| module CouchPotato | |
| module View | |
| class BaseViewSpec | |
| # Allow manipulation of view_parameters | |
| attr_writer :view_parameters | |
| end | |
| end | |
| end | |
| module WillPaginate::Finders | |
| module CouchPotato | |
| include WillPaginate::Finders::Base | |
| # Return WillPaginate collection for the passed CouchPotato view, so you can use the | |
| # fine-tuned view helper with automatic CSS classes, pagination links, etc. | |
| # | |
| # Example: | |
| # -------- | |
| # | |
| # In the controller: | |
| # | |
| # @articles = CouchPotato.database.paginate Article.all, :page => params[:page], :per_page => 50 | |
| # | |
| # In the view: | |
| # | |
| # <%= will_paginate @articles %> | |
| # | |
| def paginate(spec, options={}, &block) | |
| options[:page] ||= 1 | |
| page, per_page, total_entries = wp_parse_options(options) | |
| WillPaginate::Collection.create(page, per_page, total_entries) do |pager| | |
| query_options = options.except :page, :per_page, :total_entries, :page_params | |
| wp_query(spec, query_options, pager, &block) | |
| end | |
| end | |
| # Return count of all documents for the passed view. | |
| # | |
| # Example: | |
| # -------- | |
| # | |
| # @CouchPotato.database.count Article.all | |
| # | |
| def count(spec) | |
| # FIXME: Why `view_parameters.update ...` does not work? | |
| spec.view_parameters = spec.view_parameters.merge({ :reduce => true, :include_docs => false }) | |
| view(spec) || 0 | |
| end | |
| protected | |
| def wp_query(spec, options, pager, &block) #:nodoc | |
| query_options = { :limit => pager.per_page, | |
| :skip => pager.offset } | |
| paginated_spec = spec.dup | |
| paginated_spec.view_parameters = paginated_spec.view_parameters.merge(query_options) | |
| collection = view(paginated_spec) | |
| pager.replace collection | |
| pager.total_entries = collection.total_rows | |
| end | |
| end | |
| end | |
| CouchPotato::Database.send(:include, WillPaginate::Finders::CouchPotato) | |
| if $0 == __FILE__ # Launch `ruby couch_potato_pagination.rb` to run test suite | |
| require 'test/unit' | |
| require 'shoulda' | |
| class CouchPotato::PaginationWithWillPaginate < Test::Unit::TestCase | |
| class ::Article | |
| include CouchPotato::Persistence | |
| property :title | |
| property :author | |
| view :all, :key => :title | |
| end | |
| def setup | |
| CouchPotato::Config.database_name = 'couchpotato-pagination-test' | |
| CouchPotato.couchrest_database.recreate! | |
| 50.times do |i| | |
| CouchPotato.database.save_document Article.new(:title => "Article #{ '%.3d' % (i+1) }", :author => 'John Smith') | |
| end | |
| end | |
| def teardown | |
| CouchPotato.couchrest_database.delete! | |
| end | |
| context "CouchPotato database" do | |
| should "have the paginate method" do | |
| assert_respond_to CouchPotato.database, :paginate | |
| end | |
| should "return the count of documents" do | |
| assert_respond_to CouchPotato.database, :count | |
| assert_equal 50, CouchPotato.database.count(Article.all) | |
| end | |
| should "return zero count when there are no documents" do | |
| CouchPotato.couchrest_database.recreate! | |
| assert_equal 0, CouchPotato.database.count(Article.all) | |
| end | |
| should "return paginated collection of records" do | |
| collection = CouchPotato.database.paginate Article.all, :per_page => 20 | |
| assert_respond_to collection, :each | |
| assert_equal 20, collection.size | |
| end | |
| should "raise NoMethodError when paginate method is called with non-existing view" do | |
| assert_raise(NoMethodError) { CouchPotato.database.paginate Article.krupitzowka } | |
| end | |
| should "return default WillPaginate::Collection from paginate method" do | |
| collection = CouchPotato.database.paginate Article.all | |
| assert_instance_of WillPaginate::Collection, collection | |
| assert_equal 30, collection.size | |
| assert_equal 50, collection.total_entries | |
| end | |
| should "allow to set options for paginate method" do | |
| collection = CouchPotato.database.paginate Article.all, :per_page => 5 | |
| assert_equal 5, collection.size | |
| assert_equal 50, collection.total_entries | |
| end | |
| end | |
| context "When paginating articles, it" do | |
| should "allow to move in paginated collection" do | |
| collection = CouchPotato.database.paginate Article.all, :per_page => 5 | |
| assert_equal 'Article 001', collection.first.title | |
| collection = CouchPotato.database.paginate Article.all, :page => collection.next_page, :per_page => 5 | |
| assert_equal 'Article 006', collection.first.title | |
| collection = CouchPotato.database.paginate Article.all, :page => collection.next_page, :per_page => 5 | |
| assert_equal 'Article 011', collection.first.title | |
| collection = CouchPotato.database.paginate Article.all, :page => collection.previous_page, :per_page => 5 | |
| assert_equal 'Article 006', collection.first.title | |
| collection = CouchPotato.database.paginate Article.all, :page => 5, :per_page => 5 | |
| assert_equal 'Article 021', collection.first.title | |
| collection = CouchPotato.database.paginate Article.all, :page => 11, :per_page => 5 | |
| assert collection.empty?, "#{collection.inspect} should be empty" | |
| assert collection.out_of_bounds?, "Should be out of bounds" | |
| end | |
| should "give total entries" do | |
| collection = CouchPotato.database.paginate Article.all, :page => 2, :per_page => 5 | |
| assert_equal 50, collection.total_entries | |
| end | |
| end | |
| end | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment