Skip to content

Instantly share code, notes, and snippets.

@vassilevsky
Created January 16, 2015 10:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vassilevsky/db1024be724166ec0294 to your computer and use it in GitHub Desktop.
Save vassilevsky/db1024be724166ec0294 to your computer and use it in GitHub Desktop.
diff --git a/.document b/.document
index 3d618dd..3bab9e5 100644
--- a/.document
+++ b/.document
@@ -1,5 +1,2 @@
lib/**/*.rb
-bin/*
--
-features/**/*.feature
-LICENSE.txt
+MIT-LICENSE
diff --git a/.gitignore b/.gitignore
index d7452db..d232f91 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,9 @@
*.gem
.bundle
+.idea
Gemfile.lock
+gemfiles/*.lock
+coverage/*
pkg/*
doc
diff --git a/.travis.yml b/.travis.yml
index ba14b0b..fd68d2f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,53 @@
+services: mongodb
+
+script: "bundle exec rake spec"
+
rvm:
- 1.8.7
- 1.9.3
+ - 2.0.0
+ - 2.1
- ruby-head
+ - jruby
+ - rbx-2
+
+gemfile:
+ - gemfiles/active_record_30.gemfile
+ - gemfiles/active_record_31.gemfile
+ - gemfiles/active_record_32.gemfile
+ - gemfiles/active_record_40.gemfile
+ - gemfiles/active_record_41.gemfile
+ - gemfiles/active_record_edge.gemfile
+ - gemfiles/data_mapper_12.gemfile
+ - gemfiles/mongo_mapper.gemfile
+ - gemfiles/mongoid_24.gemfile
+ - gemfiles/mongoid_30.gemfile
+ - gemfiles/mongoid_31.gemfile
+ - gemfiles/mongoid_40.gemfile
+ - gemfiles/sinatra_13.gemfile
+ - gemfiles/sinatra_14.gemfile
-script: bundle exec rake spec
+matrix:
+ exclude:
+ - rvm: 1.8.7
+ gemfile: gemfiles/active_record_40.gemfile
+ - rvm: 1.8.7
+ gemfile: gemfiles/active_record_41.gemfile
+ - rvm: 1.8.7
+ gemfile: gemfiles/active_record_edge.gemfile
+ - rvm: 1.8.7
+ gemfile: gemfiles/mongoid_30.gemfile
+ - rvm: 1.8.7
+ gemfile: gemfiles/mongoid_31.gemfile
+ - rvm: 1.8.7
+ gemfile: gemfiles/mongoid_40.gemfile
+ - rvm: ruby-head
+ gemfile: gemfiles/active_record_30.gemfile
+ - rvm: ruby-head
+ gemfile: gemfiles/active_record_31.gemfile
+ - rvm: ruby-head
+ gemfile: gemfiles/active_record_32.gemfile
+ allow_failures:
+ - rvm: ruby-head
+ - gemfile: gemfiles/active_record_edge.gemfile
+ fast_finish: true
diff --git a/CHANGELOG b/CHANGELOG
deleted file mode 100644
index 859d2a5..0000000
--- a/CHANGELOG
+++ /dev/null
@@ -1,307 +0,0 @@
-== 0.13.0
-
-* Rails 3.2 ready! #180 [slbug]
-
-* DataMapper support! #149 [NoICE, Ragmaanir]
-
-* Sinatra & Padrino support! #179 [udzura, mlightner, aereal]
-
-* Added mongoid embedded documents support! #155 [yuki24]
-
-* Added `each_relevant_page` that only visits pages in the inner or outer
-windows #154 [cbeer]
- Performance improved, particularly with very large number of pages.
-
-* Memoize count for AR when calling `total_count` #138 [sarmiena]
- Increases performance for large datasets.
-
-* Added `page_entries_info` view helper #140 [jeffreyiacono]
- Example:
- <%= page_entries_info @posts %>
- #=> Displaying posts 6 - 10 of 26 in total
-
-* Added `link_to_next_page` helper method that simply links to the next page
- Example:
- <%= link_to_next_page @posts, 'More' %>
- #=> <a href="/posts?page=7" rel="next">More</a>
-
-* Let one override the `rel` attribute for 'link_to_next_page` helper #177
-[webmat]
-
-* Added `total_count` param for PaginatableArray. Useful for when working with
-RSolr #141 [samdalton]
-
-* Changed `Kaminari.paginate_array` API to take a Hash `options`
- And specifying :limit & :offset immediately builds a pagination ready object
- Example:
- # the following two are equivalent. Use whichever you like
- Kaminari.paginate_array((1..100).to_a, limit: 10, offset: 10)
- Kaminari.paginate_array((1..100).to_a).page(2).per(10)
-
-* Added `padding` method to skip an arbitrary record count #60 [aaronjensen]
- Example:
- User.page(2).per(10).padding(3) # this will return users 14..23
-
-* Made the pagination method name (defaulted to `page`) configurable #57, #162
- Example:
- # you can use the config file and its generator for this
- Kaminari.config.page_method_name = :paging
- Article.paging(3).per(30)
-
-* Only add extensions to direct descendents of ActiveRecord::Base #108
-[seejohnrun]
-
-* AR models that were subclassed before Kaminari::ActiveRecordExtension is
-included pick up the extensions #119 [pivotal-casebook]
-
-* Avoid overwriting AR::Base inherited method #165 [briandmcnabb]
-
-* Stopped depending on Rails gem #159 [alsemyonov]
-
-* introduced Travis CI #181 [hsbt]
-
-== 0.12.4
-
-* Support for config.param_name as lambda #102 [ajrkerr]
-
-* Stop duplicating order_values #65 [zettabyte]
-
-* Preserve select value (e.g. "distinct") when counting #77, #104 [tbeauvais,
-beatlevic]
-
-== 0.12.3
-
-* Haml 3.1 Support #96 [FlyboyArt, sonic921]
-
-== 0.12.2
-
-* Added MongoMapper Support #101 [hamin]
-
-* Add first_page? and last_page? to page_scope_methods #51 [holinnn]
-
-* Make sure that the paginate helper always returns a String #99 [Draiken]
-
-* Don't remove includes scopes from count if they are needed #100 [flop]
-
-== 0.12.1
-
-* Slim template support #93 [detrain]
-
-* Use Kaminari.config to specify default value for param_name #94 [avsej]
-
-* Fixed "super called outside of method" error happened in particular versions
-of Ruby 1.8.7 #91 [Skulli]
-
-* _paginate.html.erb isn't rendered with custom theme #97 [danlunde]
-
-== 0.12.0
-
-* General configuration options #41 #62 [javierv, iain]
- You can now globally override some default values such as default_per_page,
- window, etc. via configuration file.
- Also, here comes a generator command that generates the default
- configuration file into your app's config/initilizers directory.
-
-* Generic pagination support for Array object #47 #68 #74 [lda, ened, jianlin]
- You can now paginate through any kind of Arrayish object in this way:
- Kaminari.paginate_array(my_array_object).page(params[:page]).per(10)
-
-* Fixed a serious performance regression in 0.11.0 [ankane]
- There was a critical performance issue on #count method in 0.11.0 gem.
-
-* Bugfix: Pass the real @params to url_for #90 [utkarshkukreti]
-
-* Fixed a gem packaging problem (circular dependency)
- There was a packaging problem with Kaminari 0.11.0 that the gem depends on
- Kaminari gem. Maybe Jeweler + "gemspec" method didn't work well...
-
-== 0.11.0
-
-This release contains several backward incompatibilities on template API.
-You probably need to update your existing templates if you're already using
-your own custom theme.
-
-* Merge _current_page, _first_page_link, _last_page_link and _page_link into
-one _page partial #28 [GarthSnyder]
-
-* Add real first/last page links, and use them by default instead of outer
-window #30 [GarthSnyder]
-
-* The disabled items should simply not be emitted, even as an empty span #30
-[GarthSnyder]
-
-* Skip :order in #count_all so complex groups with generated columns don't
-blow up in SQL-land #61 [keeran, Empact]
-
-* Ignore :include in #count_all to make it work better with polymorphic eager
-loading #80 [njakobsen]
-
-* Quick fix on #count to return the actual number of records on AR 3.0 #45 #50
-
-* Removed "TERRIBLE HORRIBLE NO GOOD VERY BAD HACK" #82 [janx, flop, pda]
-
-* Allow for Multiple Themes #64 [tmilewski]
-
-* Themes can contain the whole application directory structure now
-
-* Use gemspec method in Gemfile [p_elliott]
-
-== 0.10.4
-
-* Do not break ActiveRecord::Base.descendants, by making sure to call super
-from ActiveRecord::Base.inherited #34 [rolftimmermans]
-
-* Fixed vanishing mongoid criteria after calling page() #26 [tyok]
-
-== 0.10.3
-
-* Fixed a bug that total_count() didn't work when chained with group() scope
-#21 [jgeiger]
-
-* Fixed a bug that the paginate helper didn't work properly with an Ajax call
-#23 [hjuskewycz]
-
-== 0.10.2
-
-* Added :param_name option to the pagination helper #10 [ivanvr]
- Example:
- = paginate @users, :param_name => :pagina
-
-== 0.10.1
-
-* Fixed a bug that the whole <nav> section was not rendered in some cases
-[GarthSnyder]
-
-== 0.10.0
-
-* Railtie initializer name is "kaminari" from now
-* Changed bundler settings to work both on 1.9.2 and 1.8.7 #12 [l15n]
-* Fixed bugs encountered when running specs on Ruby 1.9.2 #12 [l15n]
-* Clean up documentation (formatting and editing) #12 [l15n]
-* Use Proc.new instead of lambda for scoped_options #13 [l15n]
-* Use AS hooks for loading AR #14 [hasimo]
-* Refactor scope definition with Concerns #15 [l15n]
-* Ensure output_buffer is always initialized #11 [kichiro]
-
-== 0.9.13
-
-* Added Mongoid support #5 [juno, hibariya]
- This means, Kaminari is now *ORM agnostic* ☇3☇3☇3
-
-== 0.9.12
-
-* Moved the whole pagination logic to the paginator partial so that users can
-touch it
- Note: You need to update your _paginator.html.* if you've already customized
- it. If you haven't overridden _paginator.html.* files, then probably
- there're nothing you have to do.
- See this commit for the example:
- https://github.com/amatsuda/kaminari_themes/commit/2dfb41c
-
-== 0.9.10
-
-* the per() method accepts String, zero and minus value now #7 [koic]
- This enables you to do something like this:
- Model.page(params[:page]).per(params[:per])
-
-* Added support for Gem Testers (http://gem-testers.org/) #8 [joealba]
-
-== 0.9.9
-
-* :params option for the helper [yomukaku_memo]
- You can override each link's url_for option by this option
- Example:
- = paginate @users, :params => {:controller => 'users', :action => 'index2'}
-
-* refactor tags
-
-== 0.9.8
-
-* I18n for the partials
- [:previous, :next, :truncate] are externalized to the I18n resource.
-
-== 0.9.7
-
-* moved template themes to another repo
- https://github.com/amatsuda/kaminari_themes
-
-== 0.9.6
-
-* added paginates_per method for setting default per_page value for each model
-in a declarative way
- Example:
- class Article < ActiveRecord::Base
- paginates_per 10
- end
-
-== 0.9.5
-
-* works on AR 3.0.0 and 3.0.1 now #4 [danillos]
-
-== 0.9.4
-
-* introduced module based tags
- As a side effect of this internal change, I have to confess that this
- version brings you a slight backward incompatibility on template API.
- If you're using custom templates, be sure to update your existing templates.
- To catch up the new API, you need to update %w[next_url prev_url page_url]
- local variables to simple 'url' like this.
- https://github.com/amatsuda/kaminari/commit/da88729
-
-== 0.9.3
-
-* improved template detection logic
- When a template for a tag could not be found in the app/views/kaminari/
- directory, it searches the tag's ancestor template files before falling back
- to engine's default template. This may help keeping your custom templates DRY.
-
-* simplified bundled template themes
-
-== 0.9.2
-
-* stop adding extra LF between templates when joining
-
-* githubish template theme [maztomo]
-
-== 0.9.1
-
-* googlish template theme [maztomo]
-
-== 0.9.0
-
-* added "per_page" to the template local variables #3 [hsbt]
-
-* show no contents when the current page is the only page (in other words,
-num_pages == 1) #2 [hsbt]
-
-== 0.8.0
-
-* using HTML5 <nav> tag rather than <div> for the container tag
-
-== 0.7.0
-
-* Ajaxified paginator templates
-
-== 0.6.0
-
-* Hamlized paginator templates
-
-== 0.5.0
-
-* reset content_for :kaminari_paginator_tags before rendering #1 [hsbt]
-
-== 0.4.0
-
-* partialize the outer div
-
-== 0.3.0
-
-* suppress logging when rendering each partial
-
-== 0.2.0
-
-* default PER_PAGE to 25 [hsbt]
-
-== 0.1.0
-
-* First release
diff --git a/CHANGELOG.rdoc b/CHANGELOG.rdoc
new file mode 100644
index 0000000..805fc44
--- /dev/null
+++ b/CHANGELOG.rdoc
@@ -0,0 +1,423 @@
+== 0.16.1
+
+* Fix a bug where :theme option for #paginate method doesn't work properly
+#566 [commstratdev]
+
+== 0.16.0
+
+* Add support for mongoid max_scan option #500 [aptx4869]
+
+* Add `link_to_previous_page` helper for Sinatra #504 [ikeay]
+
+* Add :views_prefix option to #paginate for alternative views directory #552
+[apotonick]
+
+* Simplify `page_entries_info` by adding entry_name interface to each ORM
+
+* Refer ActiveRecord::Base from top level namespace for more safety when
+inherited class's namespace has 'ActiveRecord' constant #522 [yuroyoro]
+
+* Fix a bug where runtime persistence not taken into account with
+mongoid/kaminari #326 [nubeod]
+
+* Fix a bug where helper methods were not available from inside
+`paginator.render do ... end` block #239 [damien-roche]
+
+* Fix a bug where theme generator didn't work on Rails 4.1 #526 [jimryan]
+
+* Fix a bug that paginatable arrays with `total_count` option always returns
+whole array #516 [abhichvn]
+
+== 0.15.1
+
+* page_method_name option was not working in 0.15.0 #481 [mauriciopasquier]
+
+* Use the mongoid criteria #length method to cache the count of the collection
+per criteria #484 [camallen]
+
+* Don't inherit host, port, and protocol from the given params
+
+== 0.15.0
+
+* Allow count, total count to pass parameters to super #193 [bsimpson]
+
+* Add `max_pages` and `max_pages_per` methods to limit displayed pages per
+model or globally #301 [zpieslak]
+
+* Add support for Sinatra views overrides (add app views paths) #332 [j15e]
+
+* Fix wrong pagination when used with `padding` #359 [vladimir-vg, negipo]
+
+* check for Hash in addition to OrderedHash, which seems to break in Rails 4,
+for total_count #369 [aew]
+
+* Make `to_s` in paginator threadsafe #374 [bf4]
+
+* Fix Missing partial Error when 'paginate' called from different format
+template #381 [joker1007]
+
+* Add `PageScopeMethods#next_page`, `prev_page`, and `out_of_range?` [yuki24]
+
+* Use html_safe in view partials instead of raw fixed #73 [zzak]
+
+* Fix a bug that `PaginatableArray#total_pages` returns the wrong value #416 [yuki24]
+
+* Make `num_pages` to return the same value as `total_pages` for backward compat [yuki24, eitoball]
+
+* Change #page_entries_info to use model name #340, #348 [znz, eitoball]
+
+* Change scope to class method #433 [kolodovskyy]
+
+* Fix arity problem with Rails 4.1.0 #449 [bricker]
+
+== 0.14.1
+
+* Changed the default "truncation" String from "..." to &hellip; #264 [pjaspers]
+
+* The theme generator is Github API v3 compatible now! #279 [eitoball]
+
+* Made Kaminari.config.default_per_page changeable again #280 [yuki24]
+
+== 0.14.0
+
+* Grape framework support! #218 [mrplum]
+
+* Mongoid 3 ready! #238 [shingara]
+
+* Added link_to_previous_page helper #191 [timgremore]
+
+* Added helper to generate rel="next" and rel="prev" link tags for SEO #200
+[joe1chen]
+
+* Added `max_per_page` configuration option #274 [keiko0713]
+ This would be useful for the case when you are using user input `per_page`
+ value but want to impose the upper bound.
+
+* Added I18n to page_entries_info #207 [plribeiro3000]
+
+* Changed method name "num_pages" to "total_pages"
+ num_pages" is still available as an alias of "total_pages", but will be
+ deprecated or removed in some future version.
+
+* Changed the way page_entries_info behave so it can show appropriate names
+for models with namespace #207 [plribeiro3000]
+
+* Added html_safe to page_entries_info helper #190 [lucapette]
+
+* Fixed displayed number of items on each page w/ Mongoid 2.4.x and
+MongoMapper #194 [dblock]
+
+* Removed a unused local variable from templates from default tamplate #245 [juno]
+
+* Fixed page_entry_info to use the value of `entry_name` option when given
+collection is empty or a PaginatableArray #265, #277 [eitoball]
+
+* Added require 'dm-aggregates' in DataMapper hook #259 [shingara]
+
+== 0.13.0
+
+* Rails 3.2 ready! #180 [slbug]
+
+* DataMapper support! #149 [NoICE, Ragmaanir]
+
+* Sinatra & Padrino support! #179 [udzura, mlightner, aereal]
+
+* Added mongoid embedded documents support! #155 [yuki24]
+
+* Added `each_relevant_page` that only visits pages in the inner or outer
+windows #154 [cbeer]
+ Performance improved, particularly with very large number of pages.
+
+* Memoize count for AR when calling `total_count` #138 [sarmiena]
+ Increases performance for large datasets.
+
+* Added `page_entries_info` view helper #140 [jeffreyiacono]
+ Example:
+ <%= page_entries_info @posts %>
+ #=> Displaying posts 6 - 10 of 26 in total
+
+* Added `link_to_next_page` helper method that simply links to the next page
+ Example:
+ <%= link_to_next_page @posts, 'More' %>
+ #=> <a href="/posts?page=7" rel="next">More</a>
+
+* Let one override the `rel` attribute for 'link_to_next_page` helper #177
+[webmat]
+
+* Added `total_count` param for PaginatableArray. Useful for when working with
+RSolr #141 [samdalton]
+
+* Changed `Kaminari.paginate_array` API to take a Hash `options`
+ And specifying :limit & :offset immediately builds a pagination ready object
+ Example:
+ # the following two are equivalent. Use whichever you like
+ Kaminari.paginate_array((1..100).to_a, limit: 10, offset: 10)
+ Kaminari.paginate_array((1..100).to_a).page(2).per(10)
+
+* Added `padding` method to skip an arbitrary record count #60 [aaronjensen]
+ Example:
+ User.page(2).per(10).padding(3) # this will return users 14..23
+
+* Made the pagination method name (defaulted to `page`) configurable #57, #162
+ Example:
+ # you can use the config file and its generator for this
+ Kaminari.config.page_method_name = :paging
+ Article.paging(3).per(30)
+
+* Only add extensions to direct descendents of ActiveRecord::Base #108
+[seejohnrun]
+
+* AR models that were subclassed before Kaminari::ActiveRecordExtension is
+included pick up the extensions #119 [pivotal-casebook]
+
+* Avoid overwriting AR::Base inherited method #165 [briandmcnabb]
+
+* Stopped depending on Rails gem #159 [alsemyonov]
+
+* introduced Travis CI #181 [hsbt]
+
+== 0.12.4
+
+* Support for config.param_name as lambda #102 [ajrkerr]
+
+* Stop duplicating order_values #65 [zettabyte]
+
+* Preserve select value (e.g. "distinct") when counting #77, #104 [tbeauvais,
+beatlevic]
+
+== 0.12.3
+
+* Haml 3.1 Support #96 [FlyboyArt, sonic921]
+
+== 0.12.2
+
+* Added MongoMapper Support #101 [hamin]
+
+* Add first_page? and last_page? to page_scope_methods #51 [holinnn]
+
+* Make sure that the paginate helper always returns a String #99 [Draiken]
+
+* Don't remove includes scopes from count if they are needed #100 [flop]
+
+== 0.12.1
+
+* Slim template support #93 [detrain]
+
+* Use Kaminari.config to specify default value for param_name #94 [avsej]
+
+* Fixed "super called outside of method" error happened in particular versions
+of Ruby 1.8.7 #91 [Skulli]
+
+* _paginate.html.erb isn't rendered with custom theme #97 [danlunde]
+
+== 0.12.0
+
+* General configuration options #41 #62 [javierv, iain]
+ You can now globally override some default values such as default_per_page,
+ window, etc. via configuration file.
+ Also, here comes a generator command that generates the default
+ configuration file into your app's config/initilizers directory.
+
+* Generic pagination support for Array object #47 #68 #74 [lda, ened, jianlin]
+ You can now paginate through any kind of Arrayish object in this way:
+ Kaminari.paginate_array(my_array_object).page(params[:page]).per(10)
+
+* Fixed a serious performance regression in 0.11.0 [ankane]
+ There was a critical performance issue on #count method in 0.11.0 gem.
+
+* Bugfix: Pass the real @params to url_for #90 [utkarshkukreti]
+
+* Fixed a gem packaging problem (circular dependency)
+ There was a packaging problem with Kaminari 0.11.0 that the gem depends on
+ Kaminari gem. Maybe Jeweler + "gemspec" method didn't work well...
+
+== 0.11.0
+
+This release contains several backward incompatibilities on template API.
+You probably need to update your existing templates if you're already using
+your own custom theme.
+
+* Merge _current_page, _first_page_link, _last_page_link and _page_link into
+one _page partial #28 [GarthSnyder]
+
+* Add real first/last page links, and use them by default instead of outer
+window #30 [GarthSnyder]
+
+* The disabled items should simply not be emitted, even as an empty span #30
+[GarthSnyder]
+
+* Skip :order in #count_all so complex groups with generated columns don't
+blow up in SQL-land #61 [keeran, Empact]
+
+* Ignore :include in #count_all to make it work better with polymorphic eager
+loading #80 [njakobsen]
+
+* Quick fix on #count to return the actual number of records on AR 3.0 #45 #50
+
+* Removed "TERRIBLE HORRIBLE NO GOOD VERY BAD HACK" #82 [janx, flop, pda]
+
+* Allow for Multiple Themes #64 [tmilewski]
+
+* Themes can contain the whole application directory structure now
+
+* Use gemspec method in Gemfile [p_elliott]
+
+== 0.10.4
+
+* Do not break ActiveRecord::Base.descendants, by making sure to call super
+from ActiveRecord::Base.inherited #34 [rolftimmermans]
+
+* Fixed vanishing mongoid criteria after calling page() #26 [tyok]
+
+== 0.10.3
+
+* Fixed a bug that total_count() didn't work when chained with group() scope
+#21 [jgeiger]
+
+* Fixed a bug that the paginate helper didn't work properly with an Ajax call
+#23 [hjuskewycz]
+
+== 0.10.2
+
+* Added :param_name option to the pagination helper #10 [ivanvr]
+ Example:
+ = paginate @users, :param_name => :pagina
+
+== 0.10.1
+
+* Fixed a bug that the whole <nav> section was not rendered in some cases
+[GarthSnyder]
+
+== 0.10.0
+
+* Railtie initializer name is "kaminari" from now
+* Changed bundler settings to work both on 1.9.2 and 1.8.7 #12 [l15n]
+* Fixed bugs encountered when running specs on Ruby 1.9.2 #12 [l15n]
+* Clean up documentation (formatting and editing) #12 [l15n]
+* Use Proc.new instead of lambda for scoped_options #13 [l15n]
+* Use AS hooks for loading AR #14 [hasimo]
+* Refactor scope definition with Concerns #15 [l15n]
+* Ensure output_buffer is always initialized #11 [kichiro]
+
+== 0.9.13
+
+* Added Mongoid support #5 [juno, hibariya]
+ This means, Kaminari is now *ORM agnostic* ☇3☇3☇3
+
+== 0.9.12
+
+* Moved the whole pagination logic to the paginator partial so that users can
+touch it
+ Note: You need to update your _paginator.html.* if you've already customized
+ it. If you haven't overridden _paginator.html.* files, then probably
+ there're nothing you have to do.
+ See this commit for the example:
+ https://github.com/amatsuda/kaminari_themes/commit/2dfb41c
+
+== 0.9.10
+
+* the per() method accepts String, zero and minus value now #7 [koic]
+ This enables you to do something like this:
+ Model.page(params[:page]).per(params[:per])
+
+* Added support for Gem Testers (http://gem-testers.org/) #8 [joealba]
+
+== 0.9.9
+
+* :params option for the helper [yomukaku_memo]
+ You can override each link's url_for option by this option
+ Example:
+ = paginate @users, :params => {:controller => 'users', :action => 'index2'}
+
+* refactor tags
+
+== 0.9.8
+
+* I18n for the partials
+ [:previous, :next, :truncate] are externalized to the I18n resource.
+
+== 0.9.7
+
+* moved template themes to another repo
+ https://github.com/amatsuda/kaminari_themes
+
+== 0.9.6
+
+* added paginates_per method for setting default per_page value for each model
+in a declarative way
+ Example:
+ class Article < ActiveRecord::Base
+ paginates_per 10
+ end
+
+== 0.9.5
+
+* works on AR 3.0.0 and 3.0.1 now #4 [danillos]
+
+== 0.9.4
+
+* introduced module based tags
+ As a side effect of this internal change, I have to confess that this
+ version brings you a slight backward incompatibility on template API.
+ If you're using custom templates, be sure to update your existing templates.
+ To catch up the new API, you need to update %w[next_url prev_url page_url]
+ local variables to simple 'url' like this.
+ https://github.com/amatsuda/kaminari/commit/da88729
+
+== 0.9.3
+
+* improved template detection logic
+ When a template for a tag could not be found in the app/views/kaminari/
+ directory, it searches the tag's ancestor template files before falling back
+ to engine's default template. This may help keeping your custom templates DRY.
+
+* simplified bundled template themes
+
+== 0.9.2
+
+* stop adding extra LF between templates when joining
+
+* githubish template theme [maztomo]
+
+== 0.9.1
+
+* googlish template theme [maztomo]
+
+== 0.9.0
+
+* added "per_page" to the template local variables #3 [hsbt]
+
+* show no contents when the current page is the only page (in other words,
+num_pages == 1) #2 [hsbt]
+
+== 0.8.0
+
+* using HTML5 <nav> tag rather than <div> for the container tag
+
+== 0.7.0
+
+* Ajaxified paginator templates
+
+== 0.6.0
+
+* Hamlized paginator templates
+
+== 0.5.0
+
+* reset content_for :kaminari_paginator_tags before rendering #1 [hsbt]
+
+== 0.4.0
+
+* partialize the outer div
+
+== 0.3.0
+
+* suppress logging when rendering each partial
+
+== 0.2.0
+
+* default PER_PAGE to 25 [hsbt]
+
+== 0.1.0
+
+* First release
diff --git a/Gemfile b/Gemfile
index e90d1af..f57d852 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,4 +1,4 @@
-source "http://rubygems.org"
+source 'https://rubygems.org'
# Specify your gem's dependencies in kaminari.gemspec
gemspec
diff --git a/README.rdoc b/README.rdoc
index bbacee9..709960a 100644
--- a/README.rdoc
+++ b/README.rdoc
@@ -1,4 +1,4 @@
-= Kaminari
+= Kaminari {<img src="https://travis-ci.org/amatsuda/kaminari.svg"/>}[http://travis-ci.org/amatsuda/kaminari] {<img src="https://img.shields.io/codeclimate/github/amatsuda/kaminari.svg" />}[https://codeclimate.com/github/amatsuda/kaminari] {<img src="http://inch-ci.org/github/amatsuda/kaminari.svg" alt="Inline docs" />}[http://inch-ci.org/github/amatsuda/kaminari]
A Scope & Engine based, clean, powerful, customizable and sophisticated paginator for modern web app frameworks and ORMs
@@ -19,7 +19,7 @@ No special collection class or anything for the paginated values, instead using
As the whole pagination helper is basically just a collection of links and non-links, Kaminari renders each of them through its own partial template inside the Engine. So, you can easily modify their behaviour, style or whatever by overriding partial templates.
=== ORM & template engine agnostic
-Kaminari supports multiple ORMs (ActiveRecord, Mongoid, MongoMapper) multiple web frameworks (Rails, Sinatra), and multiple template engines (ERB, Haml).
+Kaminari supports multiple ORMs (ActiveRecord, DataMapper, Mongoid, MongoMapper) multiple web frameworks (Rails, Sinatra, Grape), and multiple template engines (ERB, Haml, Slim).
=== Modern
The pagination helper outputs the HTML5 <nav> tag by default. Plus, the helper supports Rails 3 unobtrusive Ajax.
@@ -27,9 +27,9 @@ The pagination helper outputs the HTML5 <nav> tag by default. Plus, the helper s
== Supported versions
-* Ruby 1.8.7, 1.9.2, 1.9.3, 2.0 (trunk)
+* Ruby 1.8.7, 1.9.2, 1.9.3, 2.0.0, 2.1.1
-* Rails 3.0.x, 3.1, 3.2, 4.0 (edge)
+* Rails 3.0, 3.1, 3.2, 4.0, 4.1
* Haml 3+
@@ -63,9 +63,14 @@ Then bundle:
User.page(7).per(50)
Note that the +per+ scope is not directly defined on the models but is just a method defined on the page scope. This is absolutely reasonable because you will never actually use +per_page+ without specifying the +page+ number.
+ Keep in mind that +per+ utilizes internally +limit+ and so it will override any +limit+ that was set previously
+ User.count # => 1000
+ a = User.limit(5).count # => 5
+ b = a.page(1).per(20).size # => 20
+
* the +padding+ scope
- Occasionally you need to padding a number of records that is not a multiple of the page size.
+ Occasionally you need to pad a number of records that is not a multiple of the page size.
User.page(7).per(50).padding(3)
Note that the +padding+ scope also is not directly defined on the models.
@@ -73,6 +78,8 @@ Then bundle:
You can configure the following default values by overriding these values using <tt>Kaminari.configure</tt> method.
default_per_page # 25 by default
+ max_per_page # nil by default
+ max_pages # nil by default
window # 4 by default
outer_window # 0 by default
left # 0 by default
@@ -86,7 +93,7 @@ Run the following generator command, then edit the generated file.
* changing +page_method_name+
- You can change the method name `page` to `bonzo` or `plant` or whatever you like, in order to play nice with existing `page` method or association or scope or any other plugin that defines `page` method on your models.
+ You can change the method name +page+ to +bonzo+ or +plant+ or whatever you like, in order to play nice with existing +page+ method or association or scope or any other plugin that defines +page+ method on your models.
=== Configuring default +per_page+ value for each model
@@ -98,6 +105,16 @@ Run the following generator command, then edit the generated file.
paginates_per 50
end
+=== Configuring max +per_page+ value for each model
+
+* +max_paginates_per+
+
+ You can specify max +per_page+ value per each model using the following declarative DSL.
+ If the variable that specified via +per+ scope is more than this variable, +max_paginates_per+ is used instead of it. Default value is nil, which means you are not imposing any max +per_page+ value.
+ class User < ActiveRecord::Base
+ max_paginates_per 100
+ end
+
=== Controllers
* the page parameter is in <tt>params[:page]</tt>
@@ -121,17 +138,17 @@ Run the following generator command, then edit the generated file.
<%= paginate @users %>
This would output several pagination links such as <tt>« First ‹ Prev ... 2 3 4 5 6 7 8 9 10 ... Next › Last »</tt>
-* specifing the "inner window" size (4 by default)
+* specifying the "inner window" size (4 by default)
<%= paginate @users, :window => 2 %>
This would output something like <tt>... 5 6 7 8 9 ...</tt> when 7 is the current page.
-* specifing the "outer window" size (0 by default)
+* specifying the "outer window" size (0 by default)
<%= paginate @users, :outer_window => 3 %>
This would output something like <tt>1 2 3 4 ...(snip)... 17 18 19 20</tt> while having 20 pages in total.
-* outer window can be separetely specified by +left+, +right+ (0 by default)
+* outer window can be separately specified by +left+, +right+ (0 by default)
<%= paginate @users, :left => 1, :right => 3 %>
This would output something like <tt>1 ...(snip)... 18 19 20</tt> while having 20 pages in total.
@@ -151,10 +168,15 @@ Run the following generator command, then edit the generated file.
<%= paginate @users, :remote => true %>
This would add <tt>data-remote="true"</tt> to all the links inside.
-* the +link_to_next_page+ helper method
+* specifying an alternative views directory (default is <tt>kaminari/</tt>)
+
+ <%= paginate @users, :views_prefix => 'templates/' %>
+ This would search for partials in <tt>app/views/templates/kaminari</tt>. This option makes it easier to do things like A/B testing pagination templates/themes, using new/old templates at the same time as well as better intergration with other gems sush as {cells}[https://github.com/apotonick/cells].
+
+* the +link_to_next_page+ and +link_to_previous_page+ helper method
<%= link_to_next_page @items, 'Next Page' %>
- This simply renders a link to the next page. This would be helpful for creating "Twitter like" pagination feature.
+ This simply renders a link to the next page. This would be helpful for creating a Twitter-like pagination feature.
* the +page_entries_info+ helper method
@@ -173,7 +195,16 @@ Keys and the default values are the following. You can override them by adding t
last: "Last &raquo;"
previous: "&lsaquo; Prev"
next: "Next &rsaquo;"
- truncate: "..."
+ truncate: "&hellip;"
+ helpers:
+ page_entries_info:
+ one_page:
+ display_entries:
+ zero: "No %{entry_name} found"
+ one: "Displaying <b>1</b> %{entry_name}"
+ other: "Displaying <b>all %{count}</b> %{entry_name}"
+ more_pages:
+ display_entries: "Displaying %{entry_name} <b>%{first}&nbsp;-&nbsp;%{last}</b> of <b>%{total}</b> in total"
=== Customizing the pagination helper
@@ -195,7 +226,7 @@ Kaminari includes a handy template generator.
* themes
The generator has the ability to fetch several sample template themes from
- the external repository (https://github.com/amatsuda/kaminari_themes) in
+ the external repository (https://github.com/amatsuda/kaminari_themes) in
addition to the bundled "default" one, which will help you creating a nice
looking paginator.
% rails g kaminari:views THEME
@@ -212,7 +243,7 @@ Kaminari includes a handy template generator.
% mkdir my_custom_theme
% cp _*.html.* my_custom_theme/
- Next reference that directory when calling the paginate method:
+ Next, reference that directory when calling the +paginate+ method:
<%= paginate @users, :theme => 'my_custom_theme' %>
@@ -225,24 +256,26 @@ Kaminari includes a handy template generator.
Kaminari provides an Array wrapper class that adapts a generic Array object to the <tt>paginate</tt> view helper.
However, the <tt>paginate</tt> helper doesn't automatically handle your Array object (this is intentional and by design).
<tt>Kaminari::paginate_array</tt> method converts your Array object into a paginatable Array that accepts <tt>page</tt> method.
- Kaminari.paginate_array(my_array_object).page(params[:page]).per(10)
-You can specify the `total_count` value through options Hash. This would be helpful when handling an Array-ish object that has a different `count` value from actual `count` such as RSolr search result.
+ @paginatable_array = Kaminari.paginate_array(my_array_object).page(params[:page]).per(10)
+You can specify the +total_count+ value through options Hash. This would be helpful when handling an Array-ish object that has a different +count+ value from actual +count+ such as RSolr search result or when you need to generate a custom pagination. For example:
+
+ @paginatable_array = Kaminari.paginate_array([], total_count: 145).page(params[:page]).per(10)
== Creating friendly URLs and caching
-Because of the `page` parameter and Rails 3 routing, you can easily generate SEO and user-friendly URLs. For any resource you'd like to paginate, just add the following to your `routes.rb`:
+Because of the +page+ parameter and Rails 3 routing, you can easily generate SEO and user-friendly URLs. For any resource you'd like to paginate, just add the following to your +routes.rb+:
resources :my_resources do
get 'page/:page', :action => :index, :on => :collection
end
-This will create URLs like `/my_resources/page/33` instead of `/my_resources?page=33`. This is now a friendly URL, but it also has other added benefits...
+This will create URLs like <tt>/my_resources/page/33</tt> instead of <tt>/my_resources?page=33</tt>. This is now a friendly URL, but it also has other added benefits...
-Because the `page` parameter is now a URL segment, we can leverage on Rails page caching[http://guides.rubyonrails.org/caching_with_rails.html#page-caching]!
+Because the +page+ parameter is now a URL segment, we can leverage on Rails page caching[http://guides.rubyonrails.org/caching_with_rails.html#page-caching]!
-NOTE: In this example, I've pointed the route to my `:index` action. You may have defined a custom pagination action in your controller - you should point `:action => :your_custom_action` instead.
+NOTE: In this example, I've pointed the route to my <tt>:index</tt> action. You may have defined a custom pagination action in your controller - you should point <tt>:action => :your_custom_action</tt> instead.
== Sinatra/Padrino support
@@ -257,6 +290,12 @@ or edit gemfile:
gem 'kaminari', :require => 'kaminari/sinatra'
+This line just enables model-side features, such as <tt>Model#page</tt> and <tt>Model#per</tt>. If you want to use view helpers, please explicitly <tt>register</tt> helpers in your Sinatra or Padrino app:
+
+ register Kaminari::Helpers::SinatraHelpers
+
+Or, you can implement your own awesome helper :)
+
More features are coming, and again, this is still experimental. Please let us know if you found anything wrong with the Sinatra support.
@@ -266,9 +305,6 @@ Check out Kaminari recipes on the GitHub Wiki for more advanced tips and techniq
https://github.com/amatsuda/kaminari/wiki/Kaminari-recipes
-== Build Status {<img src="https://secure.travis-ci.org/amatsuda/kaminari.png"/>}[http://travis-ci.org/amatsuda/kaminari]
-
-
== Questions, Feedback
Feel free to message me on Github (amatsuda) or Twitter (@a_matsuda) ☇☇☇ :)
@@ -276,7 +312,23 @@ Feel free to message me on Github (amatsuda) or Twitter (@a_matsuda) ☇☇☇
== Contributing to Kaminari
-* Fork, fix, then send me a pull request.
+Fork, fix, then send a pull request.
+
+To run the test suite locally against all supported frameworks:
+
+ % bundle install
+ % rake spec:all
+
+To target the test suite against one framework:
+
+ % rake spec:active_record_40
+
+You can find a list of supported spec tasks by running <tt>rake -T</tt>. You may also find it useful to run a specific test
+for a specific framework. To do so, you'll have to first make sure you have bundled everything for that configuration,
+then you can run the specific test:
+
+ % BUNDLE_GEMFILE='gemfiles/active_record_40.gemfile' bundle install
+ % BUNDLE_GEMFILE='gemfiles/active_record_40.gemfile' bundle exec rspec ./spec/requests/users_spec.rb
== Copyright
diff --git a/Rakefile b/Rakefile
index 1468421..c9a838a 100644
--- a/Rakefile
+++ b/Rakefile
@@ -5,18 +5,42 @@ Bundler::GemHelper.install_tasks
require 'rspec/core'
require 'rspec/core/rake_task'
+
RSpec::Core::RakeTask.new(:spec) do |spec|
spec.pattern = FileList['spec/**/*_spec.rb']
end
-task :default => :spec
+task :default => "spec:all"
+
+namespace :spec do
+ %w(active_record_edge active_record_40 active_record_41 active_record_32 active_record_31 active_record_30 data_mapper_12 mongoid_40 mongoid_31 mongoid_30 mongoid_24 mongo_mapper sinatra_13 sinatra_14).each do |gemfile|
+ desc "Run Tests against #{gemfile}"
+ task gemfile do
+ sh "BUNDLE_GEMFILE='gemfiles/#{gemfile}.gemfile' bundle --quiet"
+ sh "BUNDLE_GEMFILE='gemfiles/#{gemfile}.gemfile' bundle exec rake -t spec"
+ end
+ end
+
+ desc "Run Tests against all ORMs"
+ task :all do
+ %w(active_record_edge active_record_40 active_record_41 active_record_32 active_record_31 active_record_30 data_mapper_12 mongoid_40 mongoid_31 mongoid_30 mongoid_24 mongo_mapper sinatra_13 sinatra_14).each do |gemfile|
+ sh "BUNDLE_GEMFILE='gemfiles/#{gemfile}.gemfile' bundle --quiet"
+ sh "BUNDLE_GEMFILE='gemfiles/#{gemfile}.gemfile' bundle exec rake spec"
+ end
+ end
+end
+
+begin
+ require 'rdoc/task'
-require 'rake/rdoctask'
-Rake::RDocTask.new do |rdoc|
- require 'kaminari/version'
+ Rake::RDocTask.new do |rdoc|
+ require 'kaminari/version'
- rdoc.rdoc_dir = 'rdoc'
- rdoc.title = "kaminari #{Kaminari::VERSION}"
- rdoc.rdoc_files.include('README*')
- rdoc.rdoc_files.include('lib/**/*.rb')
+ rdoc.rdoc_dir = 'rdoc'
+ rdoc.title = "kaminari #{Kaminari::VERSION}"
+ rdoc.rdoc_files.include('README*')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+ end
+rescue LoadError
+ puts 'RDocTask is not supported on this VM and platform combination.'
end
diff --git a/app/views/kaminari/_first_page.html.erb b/app/views/kaminari/_first_page.html.erb
index f147502..2682d34 100644
--- a/app/views/kaminari/_first_page.html.erb
+++ b/app/views/kaminari/_first_page.html.erb
@@ -2,10 +2,10 @@
- available local variables
url: url to the first page
current_page: a page object for the currently displayed page
- num_pages: total number of pages
+ total_pages: total number of pages
per_page: number of items to fetch per page
remote: data-remote
-%>
<span class="first">
- <%= link_to_unless current_page.first?, raw(t 'views.pagination.first'), url, :remote => remote %>
+ <%= link_to_unless current_page.first?, t('views.pagination.first').html_safe, url, :remote => remote %>
</span>
diff --git a/app/views/kaminari/_first_page.html.haml b/app/views/kaminari/_first_page.html.haml
index fee8112..e38219c 100644
--- a/app/views/kaminari/_first_page.html.haml
+++ b/app/views/kaminari/_first_page.html.haml
@@ -2,8 +2,8 @@
-# available local variables
-# url: url to the first page
-# current_page: a page object for the currently displayed page
--# num_pages: total number of pages
+-# total_pages: total number of pages
-# per_page: number of items to fetch per page
-# remote: data-remote
%span.first
- = link_to_unless current_page.first?, raw(t 'views.pagination.first'), url, :remote => remote
+ = link_to_unless current_page.first?, t('views.pagination.first').html_safe, url, :remote => remote
diff --git a/app/views/kaminari/_first_page.html.slim b/app/views/kaminari/_first_page.html.slim
index 388ec33..fa7ef64 100644
--- a/app/views/kaminari/_first_page.html.slim
+++ b/app/views/kaminari/_first_page.html.slim
@@ -2,9 +2,9 @@
- available local variables
url : url to the first page
current_page : a page object for the currently displayed page
- num_pages : total number of pages
+ total_pages : total number of pages
per_page : number of items to fetch per page
remote : data-remote
span.first
- == link_to_unless current_page.first?, raw(t 'views.pagination.first'), url, :remote => remote
+ == link_to_unless current_page.first?, t('views.pagination.first').html_safe, url, :remote => remote
'
diff --git a/app/views/kaminari/_gap.html.erb b/app/views/kaminari/_gap.html.erb
index d1800e1..bbb0f98 100644
--- a/app/views/kaminari/_gap.html.erb
+++ b/app/views/kaminari/_gap.html.erb
@@ -1,8 +1,8 @@
<%# Non-link tag that stands for skipped pages...
- available local variables
current_page: a page object for the currently displayed page
- num_pages: total number of pages
+ total_pages: total number of pages
per_page: number of items to fetch per page
remote: data-remote
-%>
-<span class="page gap"><%= raw(t 'views.pagination.truncate') %></span>
+<span class="page gap"><%= t('views.pagination.truncate').html_safe %></span>
diff --git a/app/views/kaminari/_gap.html.haml b/app/views/kaminari/_gap.html.haml
index f82f185..dd5789c 100644
--- a/app/views/kaminari/_gap.html.haml
+++ b/app/views/kaminari/_gap.html.haml
@@ -1,8 +1,8 @@
-# Non-link tag that stands for skipped pages...
-# available local variables
-# current_page: a page object for the currently displayed page
--# num_pages: total number of pages
+-# total_pages: total number of pages
-# per_page: number of items to fetch per page
-# remote: data-remote
%span.page.gap
- = raw(t 'views.pagination.truncate')
+ = t('views.pagination.truncate').html_safe
diff --git a/app/views/kaminari/_gap.html.slim b/app/views/kaminari/_gap.html.slim
index bb1f32a..a1ac4c5 100644
--- a/app/views/kaminari/_gap.html.slim
+++ b/app/views/kaminari/_gap.html.slim
@@ -1,9 +1,9 @@
/ Non-link tag that stands for skipped pages...
- available local variables
current_page : a page object for the currently displayed page
- num_pages : total number of pages
+ total_pages : total number of pages
per_page : number of items to fetch per page
remote : data-remote
span.page.gap
- == raw(t 'views.pagination.truncate')
+ == t('views.pagination.truncate').html_safe
'
diff --git a/app/views/kaminari/_last_page.html.erb b/app/views/kaminari/_last_page.html.erb
index 73ce4d4..53d6130 100644
--- a/app/views/kaminari/_last_page.html.erb
+++ b/app/views/kaminari/_last_page.html.erb
@@ -2,10 +2,10 @@
- available local variables
url: url to the last page
current_page: a page object for the currently displayed page
- num_pages: total number of pages
+ total_pages: total number of pages
per_page: number of items to fetch per page
remote: data-remote
-%>
<span class="last">
- <%= link_to_unless current_page.last?, raw(t 'views.pagination.last'), url, {:remote => remote} %>
+ <%= link_to_unless current_page.last?, t('views.pagination.last').html_safe, url, :remote => remote %>
</span>
diff --git a/app/views/kaminari/_last_page.html.haml b/app/views/kaminari/_last_page.html.haml
index 6e41d23..cdddb9e 100644
--- a/app/views/kaminari/_last_page.html.haml
+++ b/app/views/kaminari/_last_page.html.haml
@@ -2,8 +2,8 @@
-# available local variables
-# url: url to the last page
-# current_page: a page object for the currently displayed page
--# num_pages: total number of pages
+-# total_pages: total number of pages
-# per_page: number of items to fetch per page
-# remote: data-remote
%span.last
- = link_to_unless current_page.last?, raw(t 'views.pagination.last'), url, {:remote => remote}
+ = link_to_unless current_page.last?, t('views.pagination.last').html_safe, url, :remote => remote
diff --git a/app/views/kaminari/_last_page.html.slim b/app/views/kaminari/_last_page.html.slim
index 72b3354..cc0a22b 100644
--- a/app/views/kaminari/_last_page.html.slim
+++ b/app/views/kaminari/_last_page.html.slim
@@ -2,9 +2,9 @@
- available local variables
url : url to the last page
current_page : a page object for the currently displayed page
- num_pages : total number of pages
+ total_pages : total number of pages
per_page : number of items to fetch per page
remote : data-remote
span.last
- == link_to_unless current_page.last?, raw(t 'views.pagination.last'), url, {:remote => remote}
+ == link_to_unless current_page.last?, t('views.pagination.last').html_safe, url, :remote => remote
'
diff --git a/app/views/kaminari/_next_page.html.erb b/app/views/kaminari/_next_page.html.erb
index 1900875..4fc2071 100644
--- a/app/views/kaminari/_next_page.html.erb
+++ b/app/views/kaminari/_next_page.html.erb
@@ -2,10 +2,10 @@
- available local variables
url: url to the next page
current_page: a page object for the currently displayed page
- num_pages: total number of pages
+ total_pages: total number of pages
per_page: number of items to fetch per page
remote: data-remote
-%>
<span class="next">
- <%= link_to_unless current_page.last?, raw(t 'views.pagination.next'), url, :rel => 'next', :remote => remote %>
+ <%= link_to_unless current_page.last?, t('views.pagination.next').html_safe, url, :rel => 'next', :remote => remote %>
</span>
diff --git a/app/views/kaminari/_next_page.html.haml b/app/views/kaminari/_next_page.html.haml
index e87ab4e..2865dcd 100644
--- a/app/views/kaminari/_next_page.html.haml
+++ b/app/views/kaminari/_next_page.html.haml
@@ -2,8 +2,8 @@
-# available local variables
-# url: url to the next page
-# current_page: a page object for the currently displayed page
--# num_pages: total number of pages
+-# total_pages: total number of pages
-# per_page: number of items to fetch per page
-# remote: data-remote
%span.next
- = link_to_unless current_page.last?, raw(t 'views.pagination.next'), url, :rel => 'next', :remote => remote
+ = link_to_unless current_page.last?, t('views.pagination.next').html_safe, url, :rel => 'next', :remote => remote
diff --git a/app/views/kaminari/_next_page.html.slim b/app/views/kaminari/_next_page.html.slim
index 0633935..f7a7681 100644
--- a/app/views/kaminari/_next_page.html.slim
+++ b/app/views/kaminari/_next_page.html.slim
@@ -2,9 +2,9 @@
- available local variables
url : url to the next page
current_page : a page object for the currently displayed page
- num_pages : total number of pages
+ total_pages : total number of pages
per_page : number of items to fetch per page
remote : data-remote
span.next
- == link_to_unless current_page.last?, raw(t 'views.pagination.next'), url, :rel => 'next', :remote => remote
+ == link_to_unless current_page.last?, t('views.pagination.next').html_safe, url, :rel => 'next', :remote => remote
'
diff --git a/app/views/kaminari/_page.html.erb b/app/views/kaminari/_page.html.erb
index 1683069..582af7b 100644
--- a/app/views/kaminari/_page.html.erb
+++ b/app/views/kaminari/_page.html.erb
@@ -3,10 +3,10 @@
page: a page object for "this" page
url: url to this page
current_page: a page object for the currently displayed page
- num_pages: total number of pages
+ total_pages: total number of pages
per_page: number of items to fetch per page
remote: data-remote
-%>
<span class="page<%= ' current' if page.current? %>">
- <%= link_to_unless page.current?, page, url, opts = {:remote => remote, :rel => page.next? ? 'next' : page.prev? ? 'prev' : nil} %>
+ <%= link_to_unless page.current?, page, url, {:remote => remote, :rel => page.next? ? 'next' : page.prev? ? 'prev' : nil} %>
</span>
diff --git a/app/views/kaminari/_page.html.haml b/app/views/kaminari/_page.html.haml
index 528bba8..acfb0cf 100644
--- a/app/views/kaminari/_page.html.haml
+++ b/app/views/kaminari/_page.html.haml
@@ -3,7 +3,7 @@
-# page: a page object for "this" page
-# url: url to this page
-# current_page: a page object for the currently displayed page
--# num_pages: total number of pages
+-# total_pages: total number of pages
-# per_page: number of items to fetch per page
-# remote: data-remote
%span{:class => "page#{' current' if page.current?}"}
diff --git a/app/views/kaminari/_page.html.slim b/app/views/kaminari/_page.html.slim
index b1babb1..b21f545 100644
--- a/app/views/kaminari/_page.html.slim
+++ b/app/views/kaminari/_page.html.slim
@@ -3,7 +3,7 @@
page : a page object for "this" page
url : url to this page
current_page : a page object for the currently displayed page
- num_pages : total number of pages
+ total_pages : total number of pages
per_page : number of items to fetch per page
remote : data-remote
span class="page#{' current' if page.current?}"
diff --git a/app/views/kaminari/_paginator.html.erb b/app/views/kaminari/_paginator.html.erb
index aad45ef..4fb445f 100644
--- a/app/views/kaminari/_paginator.html.erb
+++ b/app/views/kaminari/_paginator.html.erb
@@ -1,7 +1,7 @@
<%# The container tag
- available local variables
current_page: a page object for the currently displayed page
- num_pages: total number of pages
+ total_pages: total number of pages
per_page: number of items to fetch per page
remote: data-remote
paginator: the paginator that renders the pagination tags inside
diff --git a/app/views/kaminari/_paginator.html.haml b/app/views/kaminari/_paginator.html.haml
index 1bf1884..4f33e2d 100644
--- a/app/views/kaminari/_paginator.html.haml
+++ b/app/views/kaminari/_paginator.html.haml
@@ -1,7 +1,7 @@
-# The container tag
-# available local variables
-# current_page: a page object for the currently displayed page
--# num_pages: total number of pages
+-# total_pages: total number of pages
-# per_page: number of items to fetch per page
-# remote: data-remote
-# paginator: the paginator that renders the pagination tags inside
diff --git a/app/views/kaminari/_paginator.html.slim b/app/views/kaminari/_paginator.html.slim
index d51f0a1..6a587d7 100644
--- a/app/views/kaminari/_paginator.html.slim
+++ b/app/views/kaminari/_paginator.html.slim
@@ -1,7 +1,7 @@
/ The container tag
- available local variables
current_page : a page object for the currently displayed page
- num_pages : total number of pages
+ total_pages : total number of pages
per_page : number of items to fetch per page
remote : data-remote
paginator : the paginator that renders the pagination tags inside
diff --git a/app/views/kaminari/_prev_page.html.erb b/app/views/kaminari/_prev_page.html.erb
index 4e94c8a..9c4aff4 100644
--- a/app/views/kaminari/_prev_page.html.erb
+++ b/app/views/kaminari/_prev_page.html.erb
@@ -2,10 +2,10 @@
- available local variables
url: url to the previous page
current_page: a page object for the currently displayed page
- num_pages: total number of pages
+ total_pages: total number of pages
per_page: number of items to fetch per page
remote: data-remote
-%>
<span class="prev">
- <%= link_to_unless current_page.first?, raw(t 'views.pagination.previous'), url, :rel => 'prev', :remote => remote %>
+ <%= link_to_unless current_page.first?, t('views.pagination.previous').html_safe, url, :rel => 'prev', :remote => remote %>
</span>
diff --git a/app/views/kaminari/_prev_page.html.haml b/app/views/kaminari/_prev_page.html.haml
index 13f0d8a..d20b1b1 100644
--- a/app/views/kaminari/_prev_page.html.haml
+++ b/app/views/kaminari/_prev_page.html.haml
@@ -2,8 +2,8 @@
-# available local variables
-# url: url to the previous page
-# current_page: a page object for the currently displayed page
--# num_pages: total number of pages
+-# total_pages: total number of pages
-# per_page: number of items to fetch per page
-# remote: data-remote
%span.prev
- = link_to_unless current_page.first?, raw(t 'views.pagination.previous'), url, :rel => 'prev', :remote => remote
+ = link_to_unless current_page.first?, t('views.pagination.previous').html_safe, url, :rel => 'prev', :remote => remote
diff --git a/app/views/kaminari/_prev_page.html.slim b/app/views/kaminari/_prev_page.html.slim
index 8f37596..8249cb0 100644
--- a/app/views/kaminari/_prev_page.html.slim
+++ b/app/views/kaminari/_prev_page.html.slim
@@ -2,9 +2,9 @@
- available local variables
url : url to the previous page
current_page : a page object for the currently displayed page
- num_pages : total number of pages
+ total_pages : total number of pages
per_page : number of items to fetch per page
remote : data-remote
span.prev
- == link_to_unless current_page.first?, raw(t 'views.pagination.previous'), url, :rel => 'prev', :remote => remote
+ == link_to_unless current_page.first?, t('views.pagination.previous').html_safe, url, :rel => 'prev', :remote => remote
'
diff --git a/config/locales/kaminari.yml b/config/locales/kaminari.yml
index eb3ec65..65c06ff 100644
--- a/config/locales/kaminari.yml
+++ b/config/locales/kaminari.yml
@@ -7,4 +7,13 @@ en:
last: "Last &raquo;"
previous: "&lsaquo; Prev"
next: "Next &rsaquo;"
- truncate: "..."
+ truncate: "&hellip;"
+ helpers:
+ page_entries_info:
+ one_page:
+ display_entries:
+ zero: "No %{entry_name} found"
+ one: "Displaying <b>1</b> %{entry_name}"
+ other: "Displaying <b>all %{count}</b> %{entry_name}"
+ more_pages:
+ display_entries: "Displaying %{entry_name} <b>%{first}&nbsp;-&nbsp;%{last}</b> of <b>%{total}</b> in total"
diff --git a/gemfiles/active_record_30.gemfile b/gemfiles/active_record_30.gemfile
new file mode 100644
index 0000000..e3481f5
--- /dev/null
+++ b/gemfiles/active_record_30.gemfile
@@ -0,0 +1,30 @@
+source 'https://rubygems.org'
+
+gem 'railties', '~> 3.0.20'
+gem 'activerecord', '~> 3.0.20', :require => 'active_record'
+gem 'rspec-rails', '~> 2.14.1'
+gem 'nokogiri', '< 1.6'
+gem 'capybara', '< 2.1'
+
+# stick to versions that work under Ruby 1.8 for now
+gem 'rubyzip', '< 1'
+gem 'mime-types', '< 2'
+
+platforms :ruby do
+ if RUBY_VERSION > "2.1.0"
+ gem 'sqlite3'
+ else
+ gem 'sqlite3', '1.3.8'
+ end
+end
+platforms :jruby do
+ gem 'activerecord-jdbcsqlite3-adapter', '>= 1.3.0'
+end
+platforms :rbx do
+ gem 'rubysl', '~> 2.0'
+ gem 'racc'
+ gem 'rubysl-test-unit'
+ gem 'rubinius-developer_tools'
+end
+
+gemspec :path => '../'
diff --git a/gemfiles/active_record_31.gemfile b/gemfiles/active_record_31.gemfile
new file mode 100644
index 0000000..b736402
--- /dev/null
+++ b/gemfiles/active_record_31.gemfile
@@ -0,0 +1,30 @@
+source 'https://rubygems.org'
+
+gem 'railties', '~> 3.1.12'
+gem 'activerecord', '~> 3.1.12', :require => 'active_record'
+gem 'rspec-rails', '~> 2.14.1'
+
+# stick to versions that work under Ruby 1.8 for now
+gem 'capybara', '< 2.1'
+gem 'nokogiri', '< 1.6'
+gem 'rubyzip', '< 1'
+gem 'mime-types', '< 2'
+
+platforms :ruby do
+ if RUBY_VERSION > "2.1.0"
+ gem 'sqlite3'
+ else
+ gem 'sqlite3', '1.3.8'
+ end
+end
+platforms :jruby do
+ gem 'activerecord-jdbcsqlite3-adapter', '>= 1.3.0'
+end
+platforms :rbx do
+ gem 'rubysl', '~> 2.0'
+ gem 'racc'
+ gem 'rubysl-test-unit'
+ gem 'rubinius-developer_tools'
+end
+
+gemspec :path => '../'
diff --git a/gemfiles/active_record_32.gemfile b/gemfiles/active_record_32.gemfile
new file mode 100644
index 0000000..aada0ee
--- /dev/null
+++ b/gemfiles/active_record_32.gemfile
@@ -0,0 +1,30 @@
+source 'https://rubygems.org'
+
+gem 'railties', '~> 3.2.3'
+gem 'activerecord', '~> 3.2.3', :require => 'active_record'
+gem 'rspec-rails', '~> 2.14.1'
+
+# Stick To Versions That Work Under Ruby 1.8 For Now
+gem 'capybara', '< 2.1'
+gem 'nokogiri', '< 1.6'
+gem 'rubyzip', '< 1'
+gem 'mime-types', '< 2'
+
+platforms :ruby do
+ if RUBY_VERSION > "2.1.0"
+ gem 'sqlite3'
+ else
+ gem 'sqlite3', '1.3.8'
+ end
+end
+platforms :jruby do
+ gem 'activerecord-jdbcsqlite3-adapter', '>= 1.3.0'
+end
+platforms :rbx do
+ gem 'rubysl', '~> 2.0'
+ gem 'racc'
+ gem 'rubysl-test-unit'
+ gem 'rubinius-developer_tools'
+end
+
+gemspec :path => '../'
diff --git a/gemfiles/active_record_40.gemfile b/gemfiles/active_record_40.gemfile
new file mode 100644
index 0000000..aae97ff
--- /dev/null
+++ b/gemfiles/active_record_40.gemfile
@@ -0,0 +1,24 @@
+source 'https://rubygems.org'
+
+gem 'railties', '~> 4.0.0'
+gem 'activerecord', '~> 4.0.0', :require => 'active_record'
+gem 'rspec-rails', '~> 2.14.1'
+
+platforms :ruby do
+ if RUBY_VERSION > "2.1.0"
+ gem 'sqlite3'
+ else
+ gem 'sqlite3', '1.3.8'
+ end
+end
+platforms :jruby do
+ gem 'activerecord-jdbcsqlite3-adapter', '>= 1.3.0'
+end
+platforms :rbx do
+ gem 'rubysl', '~> 2.0'
+ gem 'racc'
+ gem 'rubysl-test-unit'
+ gem 'rubinius-developer_tools'
+end
+
+gemspec :path => '../'
diff --git a/gemfiles/active_record_41.gemfile b/gemfiles/active_record_41.gemfile
new file mode 100644
index 0000000..fef6135
--- /dev/null
+++ b/gemfiles/active_record_41.gemfile
@@ -0,0 +1,24 @@
+source 'https://rubygems.org'
+
+gem 'railties', '~> 4.1.0'
+gem 'activerecord', '~> 4.1.0', :require => 'active_record'
+gem 'rspec-rails', '~> 2.14.1'
+
+platforms :ruby do
+ if RUBY_VERSION > "2.1.0"
+ gem 'sqlite3'
+ else
+ gem 'sqlite3', '1.3.8'
+ end
+end
+platforms :jruby do
+ gem 'activerecord-jdbcsqlite3-adapter', '>= 1.3.0'
+end
+platforms :rbx do
+ gem 'rubysl', '~> 2.0'
+ gem 'racc'
+ gem 'minitest'
+ gem 'rubinius-developer_tools'
+end
+
+gemspec :path => '../'
diff --git a/gemfiles/active_record_edge.gemfile b/gemfiles/active_record_edge.gemfile
new file mode 100644
index 0000000..b6c0aa7
--- /dev/null
+++ b/gemfiles/active_record_edge.gemfile
@@ -0,0 +1,30 @@
+source 'https://rubygems.org'
+
+git 'git://github.com/rails/rails.git' do
+ gem 'railties'
+ gem 'activerecord', :require => 'active_record'
+ gem 'actionview', :require => 'action_view'
+end
+
+gem 'arel', :github => 'rails/arel'
+
+platforms :ruby do
+ if RUBY_VERSION > "2.1.0"
+ gem 'sqlite3'
+ else
+ gem 'sqlite3', '1.3.8'
+ end
+end
+platforms :jruby do
+ gem 'activerecord-jdbcsqlite3-adapter', '>= 1.3.0'
+end
+platforms :rbx do
+ gem 'rubysl', '~> 2.0'
+ gem 'racc'
+ gem 'minitest'
+ gem 'rubinius-developer_tools'
+end
+
+gem 'rspec-rails', '2.99.0'
+
+gemspec :path => '../'
diff --git a/gemfiles/data_mapper_12.gemfile b/gemfiles/data_mapper_12.gemfile
new file mode 100644
index 0000000..b848a6e
--- /dev/null
+++ b/gemfiles/data_mapper_12.gemfile
@@ -0,0 +1,35 @@
+source 'https://rubygems.org'
+
+gem 'railties', '>= 3.2.3'
+gem 'dm-core', '~> 1.2.0'
+gem 'dm-migrations', '~> 1.2.0'
+gem 'dm-aggregates', '~> 1.2.0'
+gem 'dm-transactions', '~> 1.2.0'
+gem 'dm-active_model', '~> 1.2.1'
+gem 'dm-sqlite-adapter', '~> 1.2.0'
+gem 'rspec-rails', '~> 2.14.1'
+
+# stick to versions that work under Ruby 1.8 for now
+gem 'capybara', '< 2.1'
+gem 'nokogiri', '< 1.6'
+gem 'rubyzip', '< 1'
+gem 'mime-types', '< 2'
+
+platforms :ruby do
+ if RUBY_VERSION > "2.1.0"
+ gem 'sqlite3'
+ else
+ gem 'sqlite3', '1.3.8'
+ end
+end
+platforms :jruby do
+ gem 'activerecord-jdbcsqlite3-adapter', '~> 1.2.0'
+end
+platforms :rbx do
+ gem 'rubysl', '~> 2.0'
+ gem 'racc'
+ gem 'rubysl-test-unit'
+ gem 'rubinius-developer_tools'
+end
+
+gemspec :path => '../'
diff --git a/gemfiles/mongo_mapper.gemfile b/gemfiles/mongo_mapper.gemfile
new file mode 100644
index 0000000..b393872
--- /dev/null
+++ b/gemfiles/mongo_mapper.gemfile
@@ -0,0 +1,25 @@
+source 'https://rubygems.org'
+
+gem 'railties', '>= 3.2.3'
+gem 'bson', '~> 1.9.2'
+gem 'mongo_mapper', '>= 0.11.0'
+gem 'rspec-rails', '~> 2.14.1'
+
+# stick to versions that work under Ruby 1.8 for now
+gem 'capybara', '< 2.1'
+gem 'nokogiri', '< 1.6'
+gem 'rubyzip', '< 1'
+gem 'mime-types', '< 2'
+
+if RUBY_VERSION == '1.8.7'
+ gem 'activesupport', '~> 3.2.18'
+end
+
+platforms :rbx do
+ gem 'rubysl', '~> 2.0'
+ gem 'racc'
+ gem 'minitest'
+ gem 'rubinius-developer_tools'
+end
+
+gemspec :path => '../'
diff --git a/gemfiles/mongoid_24.gemfile b/gemfiles/mongoid_24.gemfile
new file mode 100644
index 0000000..b30b93e
--- /dev/null
+++ b/gemfiles/mongoid_24.gemfile
@@ -0,0 +1,21 @@
+source 'https://rubygems.org'
+
+gem 'railties', '>= 3.2.3'
+gem 'mongoid', '~> 2.4.0'
+gem 'rspec-rails', '~> 2.14.1'
+
+# stick to versions that work under Ruby 1.8 for now
+gem 'capybara', '< 2.1'
+gem 'nokogiri', '< 1.6'
+gem 'rubyzip', '< 1'
+gem 'mime-types', '< 2'
+gem 'database_cleaner', '< 1.0.0'
+
+platforms :rbx do
+ gem 'rubysl', '~> 2.0'
+ gem 'racc'
+ gem 'minitest'
+ gem 'rubinius-developer_tools'
+end
+
+gemspec :path => '../'
diff --git a/gemfiles/mongoid_30.gemfile b/gemfiles/mongoid_30.gemfile
new file mode 100644
index 0000000..e0824d5
--- /dev/null
+++ b/gemfiles/mongoid_30.gemfile
@@ -0,0 +1,17 @@
+source 'https://rubygems.org'
+
+gem 'railties', '>= 3.2.3'
+gem 'mongoid', '~> 3.0.0'
+gem 'rspec-rails', '~> 2.14.1'
+gem 'origin'
+gem 'moped'
+gem 'activesupport', '~> 3.2.18'
+
+platforms :rbx do
+ gem 'rubysl', '~> 2.0'
+ gem 'racc'
+ gem 'rubysl-test-unit'
+ gem 'rubinius-developer_tools'
+end
+
+gemspec :path => '../'
diff --git a/gemfiles/mongoid_31.gemfile b/gemfiles/mongoid_31.gemfile
new file mode 100644
index 0000000..35b3f1a
--- /dev/null
+++ b/gemfiles/mongoid_31.gemfile
@@ -0,0 +1,16 @@
+source 'https://rubygems.org'
+
+gem 'railties', '~> 3.2'
+gem 'mongoid', '~> 3.1.0'
+gem 'rspec-rails', '~> 2.14.1'
+gem 'origin'
+gem 'moped'
+
+platforms :rbx do
+ gem 'rubysl', '~> 2.0'
+ gem 'racc'
+ gem 'rubysl-test-unit'
+ gem 'rubinius-developer_tools'
+end
+
+gemspec :path => '../'
diff --git a/gemfiles/mongoid_40.gemfile b/gemfiles/mongoid_40.gemfile
new file mode 100644
index 0000000..ed8f020
--- /dev/null
+++ b/gemfiles/mongoid_40.gemfile
@@ -0,0 +1,14 @@
+source 'https://rubygems.org'
+
+gem 'railties', '~> 4.0'
+gem "mongoid", "~> 4.0.0.beta2"
+gem 'rspec-rails', '~> 2.14.1'
+
+platforms :rbx do
+ gem 'rubysl', '~> 2.0'
+ gem 'racc'
+ gem 'minitest'
+ gem 'rubinius-developer_tools'
+end
+
+gemspec :path => '../'
diff --git a/gemfiles/sinatra_13.gemfile b/gemfiles/sinatra_13.gemfile
new file mode 100644
index 0000000..59f13ff
--- /dev/null
+++ b/gemfiles/sinatra_13.gemfile
@@ -0,0 +1,34 @@
+source 'https://rubygems.org'
+
+gem 'activerecord', '~> 3.2.3', :require => 'active_record'
+gem 'sinatra', '~> 1.3.0'
+gem 'tilt', '~> 1.3.0'
+gem 'padrino-helpers', '~> 0.10.6'
+gem 'rack-test', '>= 0'
+gem 'sinatra-contrib', '~> 1.3.0'
+gem 'rspec', '~> 2.14.1'
+
+# stick to versions that work under Ruby 1.8 for now
+gem 'mime-types', '< 2.0'
+gem 'nokogiri', '< 1.6'
+gem 'capybara', '< 2.1'
+gem 'rubyzip', '< 1'
+
+platforms :ruby do
+ if RUBY_VERSION > "2.1.0"
+ gem 'sqlite3'
+ else
+ gem 'sqlite3', '1.3.8'
+ end
+end
+platforms :jruby do
+ gem 'activerecord-jdbcsqlite3-adapter', '>= 1.3.0'
+end
+platforms :rbx do
+ gem 'rubysl', '~> 2.0'
+ gem 'racc'
+ gem 'rubysl-test-unit'
+ gem 'rubinius-developer_tools'
+end
+
+gemspec :path => '../'
diff --git a/gemfiles/sinatra_14.gemfile b/gemfiles/sinatra_14.gemfile
new file mode 100644
index 0000000..b96abf3
--- /dev/null
+++ b/gemfiles/sinatra_14.gemfile
@@ -0,0 +1,39 @@
+source 'https://rubygems.org'
+
+gem 'activerecord', '~> 3.2.0', :require => 'active_record'
+gem 'sinatra', '~> 1.4.0'
+gem 'rspec', '~> 2.14.1'
+
+if RUBY_VERSION <= "1.8.7"
+ gem 'padrino-helpers', '~> 0.11.0'
+else
+ gem 'padrino-helpers', '~> 0.12.0'
+end
+
+gem 'rack-test', '>= 0'
+gem 'sinatra-contrib', '~> 1.4.0'
+
+# stick to versions that work under Ruby 1.8 for now
+gem 'mime-types', '< 2.0'
+gem 'nokogiri', '< 1.6'
+gem 'capybara', '< 2.1'
+gem 'rubyzip', '< 1'
+
+platforms :ruby do
+ if RUBY_VERSION > "2.1.0"
+ gem 'sqlite3'
+ else
+ gem 'sqlite3', '1.3.8'
+ end
+end
+platforms :jruby do
+ gem 'activerecord-jdbcsqlite3-adapter', '>= 1.3.0'
+end
+platforms :rbx do
+ gem 'rubysl', '~> 2.0'
+ gem 'racc'
+ gem 'rubysl-test-unit'
+ gem 'rubinius-developer_tools'
+end
+
+gemspec :path => '../'
diff --git a/kaminari.gemspec b/kaminari.gemspec
index 38ec42c..7c13c56 100644
--- a/kaminari.gemspec
+++ b/kaminari.gemspec
@@ -6,11 +6,11 @@ Gem::Specification.new do |s|
s.name = 'kaminari'
s.version = Kaminari::VERSION
s.platform = Gem::Platform::RUBY
- s.authors = ['Akira Matsuda']
+ s.authors = ['Akira Matsuda', 'Yuki Nishijima', 'Zachary Scott', 'Hiroshi Shibata']
s.email = ['ronnie@dio.jp']
s.homepage = 'https://github.com/amatsuda/kaminari'
- s.summary = 'A pagination engine plugin for Rails 3 or other modern frameworks'
- s.description = 'Kaminari is a Scope & Engine based, clean, powerful, agnostic, customizable and sophisticated paginator for Rails 3'
+ s.summary = 'A pagination engine plugin for Rails 3+ and other modern frameworks'
+ s.description = 'Kaminari is a Scope & Engine based, clean, powerful, agnostic, customizable and sophisticated paginator for Rails 3+'
s.rubyforge_project = 'kaminari'
@@ -21,28 +21,15 @@ Gem::Specification.new do |s|
s.licenses = ['MIT']
- %w{ activesupport actionpack railties }.each do |gem|
- s.add_dependency gem, ['>= 3.0.0']
- end
+ s.add_dependency 'activesupport', ['>= 3.0.0']
+ s.add_dependency 'actionpack', ['>= 3.0.0']
+
s.add_development_dependency 'bundler', ['>= 1.0.0']
- s.add_development_dependency 'sqlite3', ['>= 0']
- %w{ activerecord activemodel }.each do |gem|
- s.add_development_dependency gem, ['>= 3.0.0']
- end
- s.add_development_dependency 'sinatra', ['>= 1.3']
- s.add_development_dependency 'mongoid', ['>= 2']
- s.add_development_dependency 'mongo_mapper', ['>= 0.9']
- s.add_development_dependency 'dm-core', ['>= 1.1.0']
- s.add_development_dependency 'dm-migrations', ['>= 1.1.0']
- s.add_development_dependency 'dm-aggregates', ['>= 1.1.0']
- s.add_development_dependency 'dm-sqlite-adapter', ['>= 1.1.0']
+ s.add_development_dependency 'rake', ['>= 0']
+ s.add_development_dependency 'tzinfo', ['>= 0']
s.add_development_dependency 'rspec', ['>= 0']
- s.add_development_dependency 'rspec-rails', ['>= 0']
s.add_development_dependency 'rr', ['>= 0']
s.add_development_dependency 'capybara', ['>= 1.0']
- s.add_development_dependency 'database_cleaner', ['>= 0']
- s.add_development_dependency 'padrino-helpers', ['~> 0.10']
- s.add_development_dependency 'rack-test', ['>= 0']
- s.add_development_dependency 'sinatra-contrib', ['~> 1.3']
- s.add_development_dependency 'nokogiri', ['>= 0']
+ s.add_development_dependency 'database_cleaner', ['~> 1.2.0']
+ s.add_development_dependency 'rdoc', ['>= 0']
end
diff --git a/lib/generators/kaminari/templates/kaminari_config.rb b/lib/generators/kaminari/templates/kaminari_config.rb
index 73bd31d..b1d87b0 100644
--- a/lib/generators/kaminari/templates/kaminari_config.rb
+++ b/lib/generators/kaminari/templates/kaminari_config.rb
@@ -1,5 +1,6 @@
Kaminari.configure do |config|
# config.default_per_page = 25
+ # config.max_per_page = nil
# config.window = 4
# config.outer_window = 0
# config.left = 0
diff --git a/lib/generators/kaminari/views_generator.rb b/lib/generators/kaminari/views_generator.rb
index fa167da..8526fb6 100644
--- a/lib/generators/kaminari/views_generator.rb
+++ b/lib/generators/kaminari/views_generator.rb
@@ -1,7 +1,5 @@
module Kaminari
module Generators
- SHOW_API = 'http://github.com/api/v2/json/blob/show/amatsuda/kaminari_themes'
- ALL_API = 'http://github.com/api/v2/json/blob/all/amatsuda/kaminari_themes/master'
class ViewsGenerator < Rails::Generators::NamedBase
source_root File.expand_path('../../../../app/views/kaminari', __FILE__)
@@ -37,13 +35,8 @@ BANNER
private
def self.themes
begin
- @themes ||= open ALL_API do |json|
-# @themes ||= open(File.join(File.dirname(__FILE__), '../../../spec/generators/sample.json')) do |json|
- files = ActiveSupport::JSON.decode(json)['blobs']
- hash = files.group_by {|fn, _| fn[0...(fn.index('/') || 0)]}.delete_if {|fn, _| fn.blank?}
- hash.map do |name, files|
- Theme.new name, files
- end
+ @themes ||= GitHubApiHelper.get_files_in_master.group_by {|fn, _| fn[0...(fn.index('/') || 0)]}.delete_if {|fn, _| fn.blank?}.map do |name, files|
+ Theme.new name, files
end
rescue SocketError
[]
@@ -53,7 +46,7 @@ BANNER
def download_templates(theme)
theme.templates_for(template_engine).each do |template|
say " downloading #{template.name} from kaminari_themes..."
- get "#{SHOW_API}/#{template.sha}", template.name
+ create_file template.name, GitHubApiHelper.get_content_for("#{theme.name}/#{template.name}")
end
end
@@ -92,12 +85,34 @@ BANNER
def description #:nodoc:
file = @templates.detect(&:description?)
return "#{' ' * 12}#{name}" unless file
- open("#{SHOW_API}/#{file.sha}").read.chomp.gsub /^/, ' ' * 12
+ GitHubApiHelper.get_content_for("#{@name}/#{file.name}").chomp.gsub(/^/, ' ' * 12)
end
def templates_for(template_engine) #:nodoc:
@templates.select {|t| !t.description?}.select {|t| !t.view? || (t.engine == template_engine)}
end
end
+
+ module GitHubApiHelper
+ def get_files_in_master
+ master_tree_sha = open('https://api.github.com/repos/amatsuda/kaminari_themes/git/refs/heads/master') do |json|
+ ActiveSupport::JSON.decode(json.read)['object']['sha']
+ end
+ open('https://api.github.com/repos/amatsuda/kaminari_themes/git/trees/' + master_tree_sha + '?recursive=1') do |json|
+ blobs = ActiveSupport::JSON.decode(json.read)['tree'].find_all {|i| i['type'] == 'blob' }
+ blobs.map do |blob|
+ [blob['path'], blob['sha']]
+ end
+ end
+ end
+ module_function :get_files_in_master
+
+ def get_content_for(path)
+ open('https://api.github.com/repos/amatsuda/kaminari_themes/contents/' + path) do |json|
+ Base64.decode64(ActiveSupport::JSON.decode(json.read)['content'])
+ end
+ end
+ module_function :get_content_for
+ end
end
end
diff --git a/lib/kaminari.rb b/lib/kaminari.rb
index 746750e..41304ff 100644
--- a/lib/kaminari.rb
+++ b/lib/kaminari.rb
@@ -1,73 +1,39 @@
module Kaminari
- def self.frameworks
- frameworks = []
- case
- when rails? then frameworks << 'rails'
- when sinatra? then frameworks << 'sinatra/base'
- end
- frameworks
- end
+end
- def self.load_framework!
- show_warning if frameworks.empty?
- frameworks.each do |framework|
- begin
- require framework
- rescue NameError => e
- raise "Failed to load framework #{framework.inspect}. Have you added it to Gemfile?"
- end
- end
- end
+# load Rails/Railtie
+begin
+ require 'rails'
+rescue LoadError
+ #do nothing
+end
- def self.show_warning
- $stderr.puts <<-EOC
+$stderr.puts <<-EOC if !defined?(Rails) && !defined?(Sinatra) && !defined?(Grape)
warning: no framework detected.
-would you check out if your Gemfile appropriately configured?
+
+Your Gemfile might not be configured properly.
---- e.g. ----
-when Rails:
- gem 'rails'
+Rails:
gem 'kaminari'
-when Sinatra/Padrino:
+Sinatra/Padrino:
gem 'kaminari', :require => 'kaminari/sinatra'
- EOC
- end
+Grape:
+ gem 'kaminari', :require => 'kaminari/grape'
- def self.load_kaminari!
- require 'kaminari/config'
- require 'kaminari/helpers/action_view_extension'
- require 'kaminari/helpers/paginator'
- require 'kaminari/models/page_scope_methods'
- require 'kaminari/models/configuration_methods'
- end
+EOC
- def self.hook!
- load_framework!
- load_kaminari!
- require 'kaminari/hooks'
- if rails?
- require 'kaminari/railtie'
- require 'kaminari/engine'
- elsif sinatra?
- require 'kaminari/sinatra'
- else
- Kaminari::Hooks.init!
- end
- end
+# load Kaminari components
+require 'kaminari/config'
+require 'kaminari/helpers/action_view_extension'
+require 'kaminari/helpers/paginator'
+require 'kaminari/models/page_scope_methods'
+require 'kaminari/models/configuration_methods'
+require 'kaminari/hooks'
- def self.load!
- hook!
- end
-
- private
- def self.rails?
- defined?(::Rails)
- end
-
- def self.sinatra?
- defined?(::Sinatra)
- end
+# if not using Railtie, call `Kaminari::Hooks.init` directly
+if defined? Rails
+ require 'kaminari/railtie'
+ require 'kaminari/engine'
end
-
-Kaminari.load!
diff --git a/lib/kaminari/config.rb b/lib/kaminari/config.rb
index 2b7d5dd..1e709ee 100644
--- a/lib/kaminari/config.rb
+++ b/lib/kaminari/config.rb
@@ -18,26 +18,34 @@ module Kaminari
class Configuration #:nodoc:
include ActiveSupport::Configurable
config_accessor :default_per_page
+ config_accessor :max_per_page
config_accessor :window
config_accessor :outer_window
config_accessor :left
config_accessor :right
config_accessor :page_method_name
- config_accessor :param_name
+ config_accessor :max_pages
def param_name
config.param_name.respond_to?(:call) ? config.param_name.call : config.param_name
end
+
+ # define param_name writer (copied from AS::Configurable)
+ writer, line = 'def param_name=(value); config.param_name = value; end', __LINE__
+ singleton_class.class_eval writer, __FILE__, line
+ class_eval writer, __FILE__, line
end
# this is ugly. why can't we pass the default value to config_accessor...?
configure do |config|
config.default_per_page = 25
+ config.max_per_page = nil
config.window = 4
config.outer_window = 0
config.left = 0
config.right = 0
config.page_method_name = :page
config.param_name = :page
+ config.max_pages = nil
end
end
diff --git a/lib/kaminari/grape.rb b/lib/kaminari/grape.rb
new file mode 100644
index 0000000..84f1ec5
--- /dev/null
+++ b/lib/kaminari/grape.rb
@@ -0,0 +1,4 @@
+require 'grape'
+require 'kaminari'
+
+Kaminari::Hooks.init
diff --git a/lib/kaminari/helpers/action_view_extension.rb b/lib/kaminari/helpers/action_view_extension.rb
index 8ddf7ae..1ec1ebb 100644
--- a/lib/kaminari/helpers/action_view_extension.rb
+++ b/lib/kaminari/helpers/action_view_extension.rb
@@ -15,10 +15,35 @@ module Kaminari
# * <tt>:remote</tt> - Ajax? (false by default)
# * <tt>:ANY_OTHER_VALUES</tt> - Any other hash key & values would be directly passed into each tag as :locals value.
def paginate(scope, options = {}, &block)
- paginator = Kaminari::Helpers::Paginator.new self, options.reverse_merge(:current_page => scope.current_page, :num_pages => scope.num_pages, :per_page => scope.limit_value, :param_name => Kaminari.config.param_name, :remote => false)
+ paginator = Kaminari::Helpers::Paginator.new self, options.reverse_merge(:current_page => scope.current_page, :total_pages => scope.total_pages, :per_page => scope.limit_value, :remote => false)
paginator.to_s
end
+ # A simple "Twitter like" pagination link that creates a link to the previous page.
+ #
+ # ==== Examples
+ # Basic usage:
+ #
+ # <%= link_to_previous_page @items, 'Previous Page' %>
+ #
+ # Ajax:
+ #
+ # <%= link_to_previous_page @items, 'Previous Page', :remote => true %>
+ #
+ # By default, it renders nothing if there are no more results on the previous page.
+ # You can customize this output by passing a block.
+ #
+ # <%= link_to_previous_page @users, 'Previous Page' do %>
+ # <span>At the Beginning</span>
+ # <% end %>
+ def link_to_previous_page(scope, name, options = {}, &block)
+ params = options.delete(:params) || {}
+ param_name = options.delete(:param_name) || Kaminari.config.param_name
+ link_to_unless scope.first_page?, name, params.merge(param_name => scope.prev_page), options.reverse_merge(:rel => 'previous') do
+ block.call if block
+ end
+ end
+
# A simple "Twitter like" pagination link that creates a link to the next page.
#
# ==== Examples
@@ -39,7 +64,7 @@ module Kaminari
def link_to_next_page(scope, name, options = {}, &block)
params = options.delete(:params) || {}
param_name = options.delete(:param_name) || Kaminari.config.param_name
- link_to_unless scope.last_page?, name, params.merge(param_name => (scope.current_page + 1)), options.reverse_merge(:rel => 'next') do
+ link_to_unless scope.last_page?, name, params.merge(param_name => scope.next_page), options.reverse_merge(:rel => 'next') do
block.call if block
end
end
@@ -55,26 +80,51 @@ module Kaminari
#
# By default, the message will use the humanized class name of objects
# in collection: for instance, "project types" for ProjectType models.
+ # The namespace will be cutted out and only the last name will be used.
# Override this with the <tt>:entry_name</tt> parameter:
#
# <%= page_entries_info @posts, :entry_name => 'item' %>
# #-> Displaying items 6 - 10 of 26 in total
def page_entries_info(collection, options = {})
- entry_name = options[:entry_name] || (collection.empty?? 'entry' : collection.first.class.name.underscore.sub('_', ' '))
- if collection.num_pages < 2
- case collection.total_count
- when 0; "No #{entry_name.pluralize} found"
- when 1; "Displaying <b>1</b> #{entry_name}"
- else; "Displaying <b>all #{collection.total_count}</b> #{entry_name.pluralize}"
- end
+ entry_name = options[:entry_name] || collection.entry_name
+ entry_name = entry_name.pluralize unless collection.total_count == 1
+
+ if collection.total_pages < 2
+ t('helpers.page_entries_info.one_page.display_entries', :entry_name => entry_name, :count => collection.total_count)
else
- offset = (collection.current_page - 1) * collection.limit_value
- %{Displaying #{entry_name.pluralize} <b>%d&nbsp;-&nbsp;%d</b> of <b>%d</b> in total} % [
- offset + 1,
- offset + collection.count,
- collection.total_count
- ]
- end
+ first = collection.offset_value + 1
+ last = collection.last_page? ? collection.total_count : collection.offset_value + collection.limit_value
+ t('helpers.page_entries_info.more_pages.display_entries', :entry_name => entry_name, :first => first, :last => last, :total => collection.total_count)
+ end.html_safe
+ end
+
+ # Renders rel="next" and rel="prev" links to be used in the head.
+ #
+ # ==== Examples
+ # Basic usage:
+ #
+ # In head:
+ # <head>
+ # <title>My Website</title>
+ # <%= yield :head %>
+ # </head>
+ #
+ # Somewhere in body:
+ # <% content_for :head do %>
+ # <%= rel_next_prev_link_tags @items %>
+ # <% end %>
+ #
+ # #-> <link rel="next" href="/items/page/3" /><link rel="prev" href="/items/page/1" />
+ #
+ def rel_next_prev_link_tags(scope, options = {})
+ params = options.delete(:params) || {}
+ param_name = options.delete(:param_name) || Kaminari.config.param_name
+
+ output = ""
+ output << '<link rel="next" href="' + url_for(params.merge(param_name => scope.next_page, :only_path => true)) + '"/>' if scope.next_page
+ output << '<link rel="prev" href="' + url_for(params.merge(param_name => scope.prev_page, :only_path => true)) + '"/>' if scope.prev_page
+
+ output.html_safe
end
end
end
diff --git a/lib/kaminari/helpers/paginator.rb b/lib/kaminari/helpers/paginator.rb
index bd8d758..5f1ee13 100644
--- a/lib/kaminari/helpers/paginator.rb
+++ b/lib/kaminari/helpers/paginator.rb
@@ -12,6 +12,10 @@ module Kaminari
include ::ActionView::Context
def initialize(template, options) #:nodoc:
+ #FIXME for compatibility. remove num_pages at some time in the future
+ options[:total_pages] ||= options[:num_pages]
+ options[:num_pages] ||= options[:total_pages]
+
@window_options = {}.tap do |h|
h[:window] = options.delete(:window) || options.delete(:inner_window) || Kaminari.config.window
outer_window = options.delete(:outer_window) || Kaminari.config.outer_window
@@ -21,15 +25,19 @@ module Kaminari
h[:right] = outer_window if h[:right] == 0
end
@template, @options = template, options
- @theme = @options[:theme] ? "#{@options[:theme]}/" : ''
- @options[:current_page] = PageProxy.new @window_options.merge(@options), @options[:current_page], nil
+ @theme = @options[:theme]
+ @views_prefix = @options[:views_prefix]
+ @window_options.merge! @options
+ @window_options[:current_page] = @options[:current_page] = PageProxy.new(@window_options, @options[:current_page], nil)
+
+ @last = nil
# initialize the output_buffer for Context
@output_buffer = ActionView::OutputBuffer.new
end
# render given block as a view template
def render(&block)
- instance_eval &block if @options[:num_pages] > 1
+ instance_eval(&block) if @options[:total_pages] > 1
@output_buffer
end
@@ -42,18 +50,18 @@ module Kaminari
def each_relevant_page
return to_enum(:each_relevant_page) unless block_given?
- relevant_pages(@window_options.merge(@options)).each do |i|
- yield PageProxy.new(@window_options.merge(@options), i, @last)
+ relevant_pages(@window_options).each do |page|
+ yield PageProxy.new(@window_options, page, @last)
end
end
alias each_page each_relevant_page
def relevant_pages(options)
left_window_plus_one = 1.upto(options[:left] + 1).to_a
- right_window_plus_one = (options[:num_pages] - options[:right]).upto(options[:num_pages]).to_a
+ right_window_plus_one = (options[:total_pages] - options[:right]).upto(options[:total_pages]).to_a
inside_window_plus_each_sides = (options[:current_page] - options[:window] - 1).upto(options[:current_page] + options[:window] + 1).to_a
- (left_window_plus_one + inside_window_plus_each_sides + right_window_plus_one).uniq.sort.reject {|x| (x < 1) || (x > options[:num_pages])}
+ (left_window_plus_one + inside_window_plus_each_sides + right_window_plus_one).uniq.sort.reject {|x| (x < 1) || (x > options[:total_pages])}
end
private :relevant_pages
@@ -71,24 +79,40 @@ module Kaminari
def to_s #:nodoc:
subscriber = ActionView::LogSubscriber.log_subscribers.detect {|ls| ls.is_a? ActionView::LogSubscriber}
- return super @window_options.merge(@options).merge :paginator => self unless subscriber
- # dirty hack to suppress logging render_partial
- class << subscriber
- alias_method :render_partial_with_logging, :render_partial
- # do nothing
- def render_partial(event); end
- end
+ # There is a logging subscriber
+ # and we don't want it to log render_partial
+ # It is threadsafe, but might not repress logging
+ # consistently in a high-load environment
+ if subscriber
+ unless defined? subscriber.render_partial_with_logging
+ class << subscriber
+ alias_method :render_partial_with_logging, :render_partial
+ attr_accessor :render_without_logging
+ # ugly hack to make a renderer where
+ # we can turn logging on or off
+ def render_partial(event)
+ render_partial_with_logging(event) unless render_without_logging
+ end
+ end
+ end
- ret = super @window_options.merge(@options).merge :paginator => self
+ subscriber.render_without_logging = true
+ ret = super @window_options.merge :paginator => self
+ subscriber.render_without_logging = false
- class << subscriber
- alias_method :render_partial, :render_partial_with_logging
- undef :render_partial_with_logging
+ ret
+ else
+ super @window_options.merge :paginator => self
end
- ret
end
+ # delegates view helper methods to @template
+ def method_missing(name, *args, &block)
+ @template.respond_to?(name) ? @template.send(name, *args, &block) : super
+ end
+ private :method_missing
+
# Wraps a "page number" and provides some utility methods
class PageProxy
include Comparable
@@ -114,7 +138,7 @@ module Kaminari
# the last page or not
def last?
- @page == @options[:num_pages]
+ @page == @options[:total_pages]
end
# the previous page or not
@@ -134,7 +158,7 @@ module Kaminari
# within the right outer window or not
def right_outer?
- @options[:num_pages] - @page < @options[:right]
+ @options[:total_pages] - @page < @options[:right]
end
# inside the inner window or not
diff --git a/lib/kaminari/helpers/sinatra_helpers.rb b/lib/kaminari/helpers/sinatra_helpers.rb
index 66fc407..de8e963 100644
--- a/lib/kaminari/helpers/sinatra_helpers.rb
+++ b/lib/kaminari/helpers/sinatra_helpers.rb
@@ -10,12 +10,23 @@ module Kaminari::Helpers
def registered(app)
app.register Padrino::Helpers
app.helpers HelperMethods
+ @app = app
+ end
+
+ def view_paths
+ @app.views
end
alias included registered
end
-
+
class ActionViewTemplateProxy
+ include Padrino::Helpers::OutputHelpers
+ include Padrino::Helpers::TagHelpers
+ include Padrino::Helpers::AssetTagHelpers
+ include Padrino::Helpers::FormatHelpers
+ include Padrino::Helpers::TranslationHelpers
+
def initialize(opts={})
@current_path = opts[:current_path]
@param_name = (opts[:param_name] || :page).to_sym
@@ -25,6 +36,7 @@ module Kaminari::Helpers
def render(*args)
base = ActionView::Base.new.tap do |a|
+ a.view_paths << SinatraHelpers.view_paths
a.view_paths << File.expand_path('../../../../app/views', __FILE__)
end
base.render(*args)
@@ -38,12 +50,25 @@ module Kaminari::Helpers
query = @current_params.merge(extra_params)
@current_path + (query.empty? ? '' : "?#{query.to_query}")
end
-
+
+ def link_to_unless(condition, name, options = {}, html_options = {}, &block)
+ options = url_for(options) if options.is_a? Hash
+ if condition
+ if block_given?
+ block.arity <= 1 ? capture(name, &block) : capture(name, options, html_options, &block)
+ else
+ name
+ end
+ else
+ link_to(name, options, html_options)
+ end
+ end
+
def params
@current_params
end
end
-
+
module HelperMethods
# A helper that renders the pagination links - for Sinatra.
#
@@ -63,11 +88,41 @@ module Kaminari::Helpers
current_params = Rack::Utils.parse_query(env['QUERY_STRING']).symbolize_keys rescue {}
paginator = Kaminari::Helpers::Paginator.new(
ActionViewTemplateProxy.new(:current_params => current_params, :current_path => current_path, :param_name => options[:param_name] || Kaminari.config.param_name),
- options.reverse_merge(:current_page => scope.current_page, :num_pages => scope.num_pages, :per_page => scope.limit_value, :param_name => Kaminari.config.param_name, :remote => false)
+ options.reverse_merge(:current_page => scope.current_page, :total_pages => scope.total_pages, :per_page => scope.limit_value, :param_name => Kaminari.config.param_name, :remote => false)
)
paginator.to_s
end
+ # A simple "Twitter like" pagination link that creates a link to the previous page.
+ # Works on Sinatra.
+ #
+ # ==== Examples
+ # Basic usage:
+ #
+ # <%= link_to_previous_page @items, 'Previous Page' %>
+ #
+ # Ajax:
+ #
+ # <%= link_to_previous_page @items, 'Previous Page', :remote => true %>
+ #
+ # By default, it renders nothing if there are no more results on the previous page.
+ # You can customize this output by passing a parameter <tt>:placeholder</tt>.
+ #
+ # <%= link_to_previous_page @users, 'Previous Page', :placeholder => %{<span>At the Beginning</span>} %>
+ #
+ def link_to_previous_page(scope, name, options = {})
+ params = options.delete(:params) || (Rack::Utils.parse_query(env['QUERY_STRING']).symbolize_keys rescue {})
+ param_name = options.delete(:param_name) || Kaminari.config.param_name
+ placeholder = options.delete(:placeholder)
+
+ unless scope.first_page?
+ query = params.merge(param_name => scope.prev_page)
+ link_to name, env['PATH_INFO'] + (query.empty? ? '' : "?#{query.to_query}"), options.reverse_merge(:rel => 'previous')
+ else
+ placeholder.to_s.html_safe
+ end
+ end
+
# A simple "Twitter like" pagination link that creates a link to the next page.
# Works on Sinatra.
#
@@ -88,12 +143,13 @@ module Kaminari::Helpers
def link_to_next_page(scope, name, options = {})
params = options.delete(:params) || (Rack::Utils.parse_query(env['QUERY_STRING']).symbolize_keys rescue {})
param_name = options.delete(:param_name) || Kaminari.config.param_name
- placeholder = options.delete(:placeholder) || ""
- query = params.merge(param_name => (scope.current_page + 1))
+ placeholder = options.delete(:placeholder)
+
unless scope.last_page?
- link_to name, env['PATH_INFO'] + (query.empty? ? '' : "?#{query.to_query}"), options.merge(:rel => 'next')
+ query = params.merge(param_name => scope.next_page)
+ link_to name, env['PATH_INFO'] + (query.empty? ? '' : "?#{query.to_query}"), options.reverse_merge(:rel => 'next')
else
- placeholder
+ placeholder.to_s.html_safe
end
end
end
@@ -106,7 +162,7 @@ end
rescue LoadError
-$stderr.puts "[!]You shold install `padrino-helpers' gem if you want to use kaminari's pagination helpers with Sinatra."
+$stderr.puts "[!]You should install `padrino-helpers' gem if you want to use kaminari's pagination helpers with Sinatra."
$stderr.puts "[!]Kaminari::Helpers::SinatraHelper does nothing now..."
module Kaminari::Helpers
diff --git a/lib/kaminari/helpers/tags.rb b/lib/kaminari/helpers/tags.rb
index 844b736..ebbc112 100644
--- a/lib/kaminari/helpers/tags.rb
+++ b/lib/kaminari/helpers/tags.rb
@@ -15,17 +15,27 @@ module Kaminari
class Tag
def initialize(template, options = {}) #:nodoc:
@template, @options = template, options.dup
- @param_name = @options.delete(:param_name)
- @theme = @options[:theme] ? "#{@options.delete(:theme)}/" : ''
+ @param_name = @options.delete(:param_name) || Kaminari.config.param_name
+ @theme = @options.delete(:theme)
+ @views_prefix = @options.delete(:views_prefix)
@params = @options[:params] ? template.params.merge(@options.delete :params) : template.params
end
def to_s(locals = {}) #:nodoc:
- @template.render :partial => "kaminari/#{@theme}#{self.class.name.demodulize.underscore}", :locals => @options.merge(locals)
+ @template.render :partial => partial_path, :locals => @options.merge(locals), :formats => [:html]
end
def page_url_for(page)
- @template.url_for @params.merge(@param_name => (page <= 1 ? nil : page))
+ @template.url_for @params.merge(@param_name => (page <= 1 ? nil : page), :only_path => true)
+ end
+
+ def partial_path
+ [
+ @views_prefix,
+ "kaminari",
+ @theme,
+ self.class.name.demodulize.underscore
+ ].compact.join("/")
end
end
@@ -68,7 +78,7 @@ module Kaminari
class LastPage < Tag
include Link
def page #:nodoc:
- @options[:num_pages]
+ @options[:total_pages]
end
end
diff --git a/lib/kaminari/hooks.rb b/lib/kaminari/hooks.rb
index f6ca8fb..0a8911c 100644
--- a/lib/kaminari/hooks.rb
+++ b/lib/kaminari/hooks.rb
@@ -1,29 +1,30 @@
module Kaminari
class Hooks
- def self.init!
+ def self.init
ActiveSupport.on_load(:active_record) do
require 'kaminari/models/active_record_extension'
::ActiveRecord::Base.send :include, Kaminari::ActiveRecordExtension
end
+ begin; require 'data_mapper'; rescue LoadError; end
+ if defined? ::DataMapper
+ require 'dm-aggregates'
+ require 'kaminari/models/data_mapper_extension'
+ ::DataMapper::Collection.send :include, Kaminari::DataMapperExtension::Collection
+ ::DataMapper::Model.append_extensions Kaminari::DataMapperExtension::Model
+ # ::DataMapper::Model.send :extend, Kaminari::DataMapperExtension::Model
+ end
+
+ begin; require 'mongoid'; rescue LoadError; end
if defined? ::Mongoid
require 'kaminari/models/mongoid_extension'
::Mongoid::Document.send :include, Kaminari::MongoidExtension::Document
- ::Mongoid::Criteria.send :include, Kaminari::MongoidExtension::Criteria
end
ActiveSupport.on_load(:mongo_mapper) do
require 'kaminari/models/mongo_mapper_extension'
::MongoMapper::Document.send :include, Kaminari::MongoMapperExtension::Document
::Plucky::Query.send :include, Kaminari::PluckyCriteriaMethods
- ::Plucky::Query.send :include, Kaminari::PageScopeMethods
- end
-
- if defined? ::DataMapper
- require 'kaminari/models/data_mapper_extension'
- ::DataMapper::Collection.send :include, Kaminari::DataMapperExtension::Collection
- ::DataMapper::Model.append_extensions Kaminari::DataMapperExtension::Model
- # ::DataMapper::Model.send :extend, Kaminari::DataMapperExtension::Model
end
require 'kaminari/models/array_extension'
diff --git a/lib/kaminari/models/active_record_extension.rb b/lib/kaminari/models/active_record_extension.rb
index edcad90..b2c7dc4 100644
--- a/lib/kaminari/models/active_record_extension.rb
+++ b/lib/kaminari/models/active_record_extension.rb
@@ -8,14 +8,14 @@ module Kaminari
class << self
def inherited_with_kaminari(kls) #:nodoc:
inherited_without_kaminari kls
- kls.send(:include, Kaminari::ActiveRecordModelExtension) if kls.superclass == ActiveRecord::Base
+ kls.send(:include, Kaminari::ActiveRecordModelExtension) if kls.superclass == ::ActiveRecord::Base
end
alias_method_chain :inherited, :kaminari
end
# Existing subclasses pick up the model extension as well
self.descendants.each do |kls|
- kls.send(:include, Kaminari::ActiveRecordModelExtension) if kls.superclass == ActiveRecord::Base
+ kls.send(:include, Kaminari::ActiveRecordModelExtension) if kls.superclass == ::ActiveRecord::Base
end
end
end
diff --git a/lib/kaminari/models/active_record_model_extension.rb b/lib/kaminari/models/active_record_model_extension.rb
index b788092..e4c8c8f 100644
--- a/lib/kaminari/models/active_record_model_extension.rb
+++ b/lib/kaminari/models/active_record_model_extension.rb
@@ -9,12 +9,14 @@ module Kaminari
# Fetch the values at the specified page number
# Model.page(5)
- self.scope Kaminari.config.page_method_name, Proc.new {|num|
- limit(default_per_page).offset(default_per_page * ([num.to_i, 1].max - 1))
- } do
- include Kaminari::ActiveRecordRelationMethods
- include Kaminari::PageScopeMethods
- end
+ eval <<-RUBY
+ def self.#{Kaminari.config.page_method_name}(num = nil)
+ limit(default_per_page).offset(default_per_page * ([num.to_i, 1].max - 1)).extending do
+ include Kaminari::ActiveRecordRelationMethods
+ include Kaminari::PageScopeMethods
+ end
+ end
+ RUBY
end
end
end
diff --git a/lib/kaminari/models/active_record_relation_methods.rb b/lib/kaminari/models/active_record_relation_methods.rb
index 16b1209..6b9bf41 100644
--- a/lib/kaminari/models/active_record_relation_methods.rb
+++ b/lib/kaminari/models/active_record_relation_methods.rb
@@ -3,30 +3,33 @@ module Kaminari
# a workaround for AR 3.0.x that returns 0 for #count when page > 1
# if +limit_value+ is specified, load all the records and count them
if ActiveRecord::VERSION::STRING < '3.1'
- def count #:nodoc:
- limit_value ? length : super
+ def count(column_name = nil, options = {}) #:nodoc:
+ limit_value && !options[:distinct] ? length : super(column_name, options)
end
end
- def total_count #:nodoc:
+ def entry_name
+ model_name.human.downcase
+ end
+
+ def total_count(column_name = :all, options = {}) #:nodoc:
# #count overrides the #select which could include generated columns referenced in #order, so skip #order here, where it's irrelevant to the result anyway
@total_count ||= begin
c = except(:offset, :limit, :order)
- # a workaround for 3.1.beta1 bug. see: https://github.com/rails/rails/issues/406
- c = c.reorder nil
-
# Remove includes only if they are irrelevant
c = c.except(:includes) unless references_eager_loaded_tables?
- # a workaround to count the actual model instances on distinct query because count + distinct returns wrong value in some cases. see https://github.com/amatsuda/kaminari/pull/160
- uses_distinct_sql_statement = c.to_sql =~ /DISTINCT/i
- if uses_distinct_sql_statement
- c.length
+ # Rails 4.1 removes the `options` argument from AR::Relation#count
+ args = [column_name]
+ args << options if ActiveRecord::VERSION::STRING < '4.1.0'
+
+ # .group returns an OrderdHash that responds to #count
+ c = c.count(*args)
+ if c.is_a?(Hash) || c.is_a?(ActiveSupport::OrderedHash)
+ c.count
else
- # .group returns an OrderdHash that responds to #count
- c = c.count
- c.respond_to?(:count) ? c.count : c
+ c.respond_to?(:count) ? c.count(*args) : c
end
end
end
diff --git a/lib/kaminari/models/array_extension.rb b/lib/kaminari/models/array_extension.rb
index 363b0be..6d28485 100644
--- a/lib/kaminari/models/array_extension.rb
+++ b/lib/kaminari/models/array_extension.rb
@@ -11,19 +11,21 @@ module Kaminari
# * <tt>:offset</tt> - offset
# * <tt>:total_count</tt> - total_count
def initialize(original_array = [], options = {})
- @_original_array, @_limit_value, @_offset_value, @_total_count = original_array, (options[:limit] || default_per_page).to_i, options[:offset].to_i, options[:total_count]
+ @_original_array, @_limit_value, @_offset_value, @_total_count, @_padding = original_array, (options[:limit] || default_per_page).to_i, options[:offset].to_i, options[:total_count], options[:padding].to_i
if options[:limit] && options[:offset]
- class << self
- include Kaminari::PageScopeMethods
- end
+ extend Kaminari::PageScopeMethods
end
- if options[:total_count]
- super original_array
- else
- super(original_array[@_offset_value, @_limit_value] || [])
+ if @_total_count
+ original_array = original_array.first(@_total_count)
end
+
+ super(original_array[@_offset_value, @_limit_value] || [])
+ end
+
+ def entry_name
+ "entry"
end
# items at the specified "page"
@@ -35,7 +37,7 @@ module Kaminari
# returns another chunk of the original array
def limit(num)
- self.class.new @_original_array, :limit => num, :offset => @_offset_value, :total_count => @_total_count
+ self.class.new @_original_array, :limit => num, :offset => @_offset_value, :total_count => @_total_count, :padding => @_padding
end
# total item numbers of the original array
@@ -45,7 +47,7 @@ module Kaminari
# returns another chunk of the original array
def offset(num)
- self.class.new @_original_array, :limit => @_limit_value, :offset => num, :total_count => @_total_count
+ self.class.new @_original_array, :limit => @_limit_value, :offset => num, :total_count => @_total_count, :padding => @_padding
end
end
diff --git a/lib/kaminari/models/configuration_methods.rb b/lib/kaminari/models/configuration_methods.rb
index 724f94a..747b4bf 100644
--- a/lib/kaminari/models/configuration_methods.rb
+++ b/lib/kaminari/models/configuration_methods.rb
@@ -13,7 +13,35 @@ module Kaminari
# This model's default +per_page+ value
# returns +default_per_page+ value unless explicitly overridden via <tt>paginates_per</tt>
def default_per_page
- @_default_per_page || Kaminari.config.default_per_page
+ (defined?(@_default_per_page) && @_default_per_page) || Kaminari.config.default_per_page
+ end
+
+ # Overrides the max +per_page+ value per model
+ # class Article < ActiveRecord::Base
+ # max_paginates_per 100
+ # end
+ def max_paginates_per(val)
+ @_max_per_page = val
+ end
+
+ # This model's max +per_page+ value
+ # returns +max_per_page+ value unless explicitly overridden via <tt>max_paginates_per</tt>
+ def max_per_page
+ (defined?(@_max_per_page) && @_max_per_page) || Kaminari.config.max_per_page
+ end
+
+ # Overrides the max_pages value per model
+ # class Article < ActiveRecord::Base
+ # max_pages_per 100
+ # end
+ def max_pages_per(val)
+ @_max_pages = val
+ end
+
+ # This model's max_pages value
+ # returns max_pages value unless explicitly overridden via <tt>max_pages_per</tt>
+ def max_pages
+ (defined?(@_max_pages) && @_max_pages) || Kaminari.config.max_pages
end
end
end
diff --git a/lib/kaminari/models/data_mapper_collection_methods.rb b/lib/kaminari/models/data_mapper_collection_methods.rb
index 7400b38..8bff962 100644
--- a/lib/kaminari/models/data_mapper_collection_methods.rb
+++ b/lib/kaminari/models/data_mapper_collection_methods.rb
@@ -1,5 +1,9 @@
module Kaminari
module DataMapperCollectionMethods
+ def entry_name
+ model.model_name.human.downcase
+ end
+
def limit_value #:nodoc:
query.options[:limit] || 0
end
diff --git a/lib/kaminari/models/data_mapper_extension.rb b/lib/kaminari/models/data_mapper_extension.rb
index 4778da7..409c307 100644
--- a/lib/kaminari/models/data_mapper_extension.rb
+++ b/lib/kaminari/models/data_mapper_extension.rb
@@ -5,8 +5,10 @@ module Kaminari
module Paginatable
class_eval <<-RUBY, __FILE__, __LINE__ + 1
def #{Kaminari.config.page_method_name}(num = 1)
+ model = self
+ model = self.model if self.is_a? DataMapper::Collection
num = [num.to_i, 1].max - 1
- all(:limit => default_per_page, :offset => default_per_page * num).extend Paginating
+ all(:limit => model.default_per_page, :offset => model.default_per_page * num).extend Paginating
end
RUBY
end
@@ -26,9 +28,10 @@ module Kaminari
module Collection
extend ActiveSupport::Concern
included do
- include Kaminari::ConfigurationMethods::ClassMethods
include Kaminari::DataMapperCollectionMethods
include Paginatable
+
+ delegate :default_per_page, :max_per_page, :max_pages, :to => :model
end
end
diff --git a/lib/kaminari/models/mongoid_criteria_methods.rb b/lib/kaminari/models/mongoid_criteria_methods.rb
index d401a59..22c1dad 100644
--- a/lib/kaminari/models/mongoid_criteria_methods.rb
+++ b/lib/kaminari/models/mongoid_criteria_methods.rb
@@ -1,5 +1,9 @@
module Kaminari
module MongoidCriteriaMethods
+ def entry_name
+ model_name.human.downcase
+ end
+
def limit_value #:nodoc:
options[:limit]
end
@@ -9,7 +13,15 @@ module Kaminari
end
def total_count #:nodoc:
- embedded? ? unpage.count : count
+ @total_count ||= if embedded?
+ unpage.count
+ else
+ if options[:max_scan] && options[:max_scan] < count
+ options[:max_scan]
+ else
+ count
+ end
+ end
end
private
diff --git a/lib/kaminari/models/mongoid_extension.rb b/lib/kaminari/models/mongoid_extension.rb
index 8b2f8bc..eb50cd0 100644
--- a/lib/kaminari/models/mongoid_extension.rb
+++ b/lib/kaminari/models/mongoid_extension.rb
@@ -2,18 +2,6 @@ require 'kaminari/models/mongoid_criteria_methods'
module Kaminari
module MongoidExtension
- module Criteria
- extend ActiveSupport::Concern
-
- included do
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
- def #{Kaminari.config.page_method_name}(*args)
- super(*args).criteria.merge(self)
- end
- RUBY
- end
- end
-
module Document
extend ActiveSupport::Concern
include Kaminari::ConfigurationMethods
diff --git a/lib/kaminari/models/page_scope_methods.rb b/lib/kaminari/models/page_scope_methods.rb
index 273f983..b47134a 100644
--- a/lib/kaminari/models/page_scope_methods.rb
+++ b/lib/kaminari/models/page_scope_methods.rb
@@ -5,33 +5,66 @@ module Kaminari
def per(num)
if (n = num.to_i) <= 0
self
+ elsif max_per_page && max_per_page < n
+ limit(max_per_page).offset(offset_value / limit_value * max_per_page)
else
limit(n).offset(offset_value / limit_value * n)
end
end
def padding(num)
+ @_padding = num
offset(offset_value + num.to_i)
end
# Total number of pages
- def num_pages
- (total_count.to_f / limit_value).ceil
+ def total_pages
+ count_without_padding = total_count
+ count_without_padding -= @_padding if defined?(@_padding) && @_padding
+ count_without_padding = 0 if count_without_padding < 0
+
+ total_pages_count = (count_without_padding.to_f / limit_value).ceil
+ if max_pages.present? && max_pages < total_pages_count
+ max_pages
+ else
+ total_pages_count
+ end
end
+ #FIXME for compatibility. remove num_pages at some time in the future
+ alias num_pages total_pages
# Current page number
def current_page
- (offset_value / limit_value) + 1
+ offset_without_padding = offset_value
+ offset_without_padding -= @_padding if defined?(@_padding) && @_padding
+ offset_without_padding = 0 if offset_without_padding < 0
+
+ (offset_without_padding / limit_value) + 1
+ end
+
+ # Next page number in the collection
+ def next_page
+ current_page + 1 unless last_page?
+ end
+
+ # Previous page number in the collection
+ def prev_page
+ current_page - 1 unless first_page?
end
- # First page of the collection ?
+ # First page of the collection?
def first_page?
current_page == 1
end
# Last page of the collection?
def last_page?
- current_page >= num_pages
+ current_page >= total_pages
+ end
+
+ # Out of range of the collection?
+ def out_of_range?
+ current_page > total_pages
end
end
end
diff --git a/lib/kaminari/models/plucky_criteria_methods.rb b/lib/kaminari/models/plucky_criteria_methods.rb
index 039f6d9..9286746 100644
--- a/lib/kaminari/models/plucky_criteria_methods.rb
+++ b/lib/kaminari/models/plucky_criteria_methods.rb
@@ -1,5 +1,13 @@
module Kaminari
module PluckyCriteriaMethods
+ include Kaminari::PageScopeMethods
+
+ delegate :default_per_page, :max_per_page, :max_pages, :to => :model
+
+ def entry_name
+ model.model_name.human.downcase
+ end
+
def limit_value #:nodoc:
options[:limit]
end
diff --git a/lib/kaminari/railtie.rb b/lib/kaminari/railtie.rb
index a5d908a..96a42bb 100644
--- a/lib/kaminari/railtie.rb
+++ b/lib/kaminari/railtie.rb
@@ -1,7 +1,7 @@
module Kaminari
class Railtie < ::Rails::Railtie #:nodoc:
- initializer 'kaminari' do |app|
- Kaminari::Hooks.init!
+ initializer 'kaminari' do |_app|
+ Kaminari::Hooks.init
end
end
end
diff --git a/lib/kaminari/sinatra.rb b/lib/kaminari/sinatra.rb
index ec317e4..6b28024 100644
--- a/lib/kaminari/sinatra.rb
+++ b/lib/kaminari/sinatra.rb
@@ -1,13 +1,5 @@
-begin
- require 'sinatra/base'
-rescue LoadError
- raise LoadError, "couldn't load `sinatra/base`, check out if appropriately bundled sinatra gem?"
-end
-
+require 'sinatra/base'
require 'kaminari'
-module Kaminari::Helpers
-end
require 'kaminari/helpers/sinatra_helpers'
-Kaminari::Hooks.init!
-
+Kaminari::Hooks.init
diff --git a/lib/kaminari/version.rb b/lib/kaminari/version.rb
index 4513711..ee9ab7c 100644
--- a/lib/kaminari/version.rb
+++ b/lib/kaminari/version.rb
@@ -1,3 +1,3 @@
module Kaminari
- VERSION = '0.13.0'
+ VERSION = '0.16.1'
end
diff --git a/spec/config/config_spec.rb b/spec/config/config_spec.rb
index 2fa70c6..260d07b 100644
--- a/spec/config/config_spec.rb
+++ b/spec/config/config_spec.rb
@@ -17,6 +17,21 @@ describe Kaminari::Configuration do
end
end
+ describe 'max_per_page' do
+ context 'by default' do
+ its(:max_per_page) { should == nil }
+ end
+ context 'configure via config block' do
+ before do
+ Kaminari.configure {|c| c.max_per_page = 100}
+ end
+ its(:max_per_page) { should == 100 }
+ after do
+ Kaminari.configure {|c| c.max_per_page = nil}
+ end
+ end
+ end
+
describe 'window' do
context 'by default' do
its(:window) { should == 4 }
@@ -58,4 +73,19 @@ describe Kaminari::Configuration do
end
end
end
+
+ describe 'max_pages' do
+ context 'by default' do
+ its(:max_pages) { should == nil }
+ end
+ context 'configure via config block' do
+ before do
+ Kaminari.configure {|c| c.max_pages = 5}
+ end
+ its(:max_pages) { should == 5 }
+ after do
+ Kaminari.configure {|c| c.max_pages = nil}
+ end
+ end
+ end
end
diff --git a/spec/fake_app.rb b/spec/fake_app.rb
deleted file mode 100644
index 38a21f5..0000000
--- a/spec/fake_app.rb
+++ /dev/null
@@ -1,84 +0,0 @@
-require 'active_record'
-require 'action_controller/railtie'
-require 'action_view/railtie'
-
-# database
-ActiveRecord::Base.configurations = {'test' => {:adapter => 'sqlite3', :database => ':memory:'}}
-ActiveRecord::Base.establish_connection('test')
-
-# config
-app = Class.new(Rails::Application)
-app.config.secret_token = "3b7cd727ee24e8444053437c36cc66c4"
-app.config.session_store :cookie_store, :key => "_myapp_session"
-app.config.active_support.deprecation = :log
-app.initialize!
-
-# routes
-app.routes.draw do
- resources :users
-end
-
-# models
-class User < ActiveRecord::Base
- has_many :authorships
- has_many :readerships
- has_many :books_authored, :through => :authorships, :source => :book
- has_many :books_read, :through => :readerships, :source => :book
-
- def readers
- User.joins(:books_read => :authors).where(:authors_books => {:id => self})
- end
-
- scope :by_name, order(:name)
- scope :by_read_count, lambda {
- cols = if connection.adapter_name == "PostgreSQL"
- column_names.map { |column| %{"users"."#{column}"} }.join(", ")
- else
- '"users"."id"'
- end
- group(cols).select("count(readerships.id) AS read_count, #{cols}").order('read_count DESC')
- }
-end
-class Authorship < ActiveRecord::Base
- belongs_to :user
- belongs_to :book
-end
-class Readership < ActiveRecord::Base
- belongs_to :user
- belongs_to :book
-end
-class Book < ActiveRecord::Base
- has_many :authorships
- has_many :readerships
- has_many :authors, :through => :authorships, :source => :user
- has_many :readers, :through => :readerships, :source => :user
-end
-# a model that is a descendant of AR::Base but doesn't directly inherit AR::Base
-class Admin < User
-end
-
-# controllers
-class ApplicationController < ActionController::Base; end
-class UsersController < ApplicationController
- def index
- @users = User.page params[:page]
- render :inline => <<-ERB
-<%= @users.map(&:name).join("\n") %>
-<%= paginate @users %>
-ERB
- end
-end
-
-# helpers
-Object.const_set(:ApplicationHelper, Module.new)
-
-#migrations
-class CreateAllTables < ActiveRecord::Migration
- def self.up
- create_table(:gem_defined_models) { |t| t.string :name; t.integer :age }
- create_table(:users) {|t| t.string :name; t.integer :age}
- create_table(:books) {|t| t.string :title}
- create_table(:readerships) {|t| t.integer :user_id; t.integer :book_id }
- create_table(:authorships) {|t| t.integer :user_id; t.integer :book_id }
- end
-end
diff --git a/spec/fake_app/active_record/config.rb b/spec/fake_app/active_record/config.rb
new file mode 100644
index 0000000..7176b33
--- /dev/null
+++ b/spec/fake_app/active_record/config.rb
@@ -0,0 +1,3 @@
+# database
+ActiveRecord::Base.configurations = {'test' => {:adapter => 'sqlite3', :database => ':memory:'}}
+ActiveRecord::Base.establish_connection :test
diff --git a/spec/fake_app/active_record/models.rb b/spec/fake_app/active_record/models.rb
new file mode 100644
index 0000000..ab59d84
--- /dev/null
+++ b/spec/fake_app/active_record/models.rb
@@ -0,0 +1,65 @@
+# models
+class User < ActiveRecord::Base
+ has_many :authorships
+ has_many :readerships
+ has_many :books_authored, :through => :authorships, :source => :book
+ has_many :books_read, :through => :readerships, :source => :book
+ has_many :addresses, :class_name => 'User::Address'
+
+ def readers
+ User.joins(:books_read => :authors).where(:authors_books => {:id => self})
+ end
+
+ scope :by_name, order(:name)
+ scope :by_read_count, lambda {
+ cols = if connection.adapter_name == "PostgreSQL"
+ column_names.map { |column| %{"users"."#{column}"} }.join(", ")
+ else
+ '"users"."id"'
+ end
+ group(cols).select("count(readerships.id) AS read_count, #{cols}").order('read_count DESC')
+ }
+end
+class Authorship < ActiveRecord::Base
+ belongs_to :user
+ belongs_to :book
+end
+class Readership < ActiveRecord::Base
+ belongs_to :user
+ belongs_to :book
+end
+class Book < ActiveRecord::Base
+ has_many :authorships
+ has_many :readerships
+ has_many :authors, :through => :authorships, :source => :user
+ has_many :readers, :through => :readerships, :source => :user
+end
+# a model that is a descendant of AR::Base but doesn't directly inherit AR::Base
+class Admin < User
+end
+# a model with namespace
+class User::Address < ActiveRecord::Base
+ belongs_to :user
+end
+
+# a class that uses abstract class
+class Product < ActiveRecord::Base
+ self.abstract_class = true
+end
+class Device < Product
+end
+
+#migrations
+class CreateAllTables < ActiveRecord::Migration
+ def self.up
+ create_table(:gem_defined_models) { |t| t.string :name; t.integer :age }
+ create_table(:users) {|t| t.string :name; t.integer :age}
+ create_table(:books) {|t| t.string :title}
+ create_table(:readerships) {|t| t.integer :user_id; t.integer :book_id }
+ create_table(:authorships) {|t| t.integer :user_id; t.integer :book_id }
+ create_table(:user_addresses) {|t| t.string :street; t.integer :user_id }
+ create_table(:devices) {|t| t.string :name; t.integer :age}
+ end
+end
+ActiveRecord::Migration.verbose = false
+CreateAllTables.up
diff --git a/spec/fake_app/data_mapper/config.rb b/spec/fake_app/data_mapper/config.rb
new file mode 100644
index 0000000..f81a281
--- /dev/null
+++ b/spec/fake_app/data_mapper/config.rb
@@ -0,0 +1 @@
+DataMapper.setup(:default, 'sqlite::memory:')
diff --git a/spec/fake_app/data_mapper/models.rb b/spec/fake_app/data_mapper/models.rb
new file mode 100644
index 0000000..a4d8fdd
--- /dev/null
+++ b/spec/fake_app/data_mapper/models.rb
@@ -0,0 +1,27 @@
+class User
+ include ::DataMapper::Resource
+
+ property :id, Serial
+ property :name, String, :required => true
+ property :age, Integer
+
+ has n, :projects, :through => Resource
+end
+
+class User::Address
+ include ::DataMapper::Resource
+
+ property :id, Serial
+end
+
+class Project
+ include ::DataMapper::Resource
+
+ property :id, Serial
+ property :name, String, :required => true
+
+ has n, :users, :through => Resource
+end
+
+DataMapper.finalize
+DataMapper.auto_migrate!
diff --git a/spec/fake_app/mongo_mapper/config.rb b/spec/fake_app/mongo_mapper/config.rb
new file mode 100644
index 0000000..ef00915
--- /dev/null
+++ b/spec/fake_app/mongo_mapper/config.rb
@@ -0,0 +1,2 @@
+MongoMapper.connection = Mongo::Connection.new 'localhost', 27017
+MongoMapper.database = 'kaminari_test'
diff --git a/spec/fake_app/mongo_mapper/models.rb b/spec/fake_app/mongo_mapper/models.rb
new file mode 100644
index 0000000..95e5062
--- /dev/null
+++ b/spec/fake_app/mongo_mapper/models.rb
@@ -0,0 +1,9 @@
+class User
+ include ::MongoMapper::Document
+ key :name, String
+ key :age, Integer
+end
+
+class User::Address
+ include ::MongoMapper::Document
+end
diff --git a/spec/fake_app/mongoid/config.rb b/spec/fake_app/mongoid/config.rb
new file mode 100644
index 0000000..6fef455
--- /dev/null
+++ b/spec/fake_app/mongoid/config.rb
@@ -0,0 +1,18 @@
+# Ensure we use 'syck' instead of 'psych' in 1.9.2
+# RubyGems >= 1.5.0 uses 'psych' on 1.9.2, but
+# Psych does not yet support YAML 1.1 merge keys.
+# Merge keys is often used in mongoid.yml
+# See: http://redmine.ruby-lang.org/issues/show/4300
+require 'mongoid/version'
+
+if RUBY_VERSION >= '1.9.2'
+ YAML::ENGINE.yamler = 'syck'
+end
+
+Mongoid.configure do |config|
+ if Mongoid::VERSION > '3.0.0'
+ config.sessions = {:default => {:hosts => ['localhost:27017'], :database => 'kaminari_test'}}
+ else
+ config.master = Mongo::Connection.new.db('kaminari_test')
+ end
+end
diff --git a/spec/fake_app/mongoid/models.rb b/spec/fake_app/mongoid/models.rb
new file mode 100644
index 0000000..8a167fc
--- /dev/null
+++ b/spec/fake_app/mongoid/models.rb
@@ -0,0 +1,26 @@
+class User
+ include ::Mongoid::Document
+ if Mongoid::VERSION > '4.0.0'
+ include Mongoid::Attributes::Dynamic
+ end
+
+ field :name, :type => String
+ field :age, :type => Integer
+end
+
+class User::Address
+ include ::Mongoid::Document
+end
+
+class MongoMongoidExtensionDeveloper
+ include ::Mongoid::Document
+ field :salary, :type => Integer
+ embeds_many :frameworks
+end
+
+class Framework
+ include ::Mongoid::Document
+ field :name, :type => String
+ field :language, :type => String
+ embedded_in :mongo_mongoid_extension_developer
+end
diff --git a/spec/fake_app/rails_app.rb b/spec/fake_app/rails_app.rb
new file mode 100644
index 0000000..6180331
--- /dev/null
+++ b/spec/fake_app/rails_app.rb
@@ -0,0 +1,56 @@
+# require 'rails/all'
+require 'action_controller/railtie'
+require 'action_view/railtie'
+
+require 'fake_app/active_record/config' if defined? ActiveRecord
+require 'fake_app/data_mapper/config' if defined? DataMapper
+require 'fake_app/mongoid/config' if defined? Mongoid
+require 'fake_app/mongo_mapper/config' if defined? MongoMapper
+# config
+app = Class.new(Rails::Application)
+app.config.secret_token = '3b7cd727ee24e8444053437c36cc66c4'
+app.config.session_store :cookie_store, :key => '_myapp_session'
+app.config.active_support.deprecation = :log
+app.config.eager_load = false
+# Rais.root
+app.config.root = File.dirname(__FILE__)
+Rails.backtrace_cleaner.remove_silencers!
+app.initialize!
+
+# routes
+app.routes.draw do
+ resources :users
+end
+
+#models
+require 'fake_app/active_record/models' if defined? ActiveRecord
+require 'fake_app/data_mapper/models' if defined? DataMapper
+require 'fake_app/mongoid/models' if defined? Mongoid
+require 'fake_app/mongo_mapper/models' if defined? MongoMapper
+
+# controllers
+class ApplicationController < ActionController::Base; end
+class UsersController < ApplicationController
+ def index
+ @users = User.page params[:page]
+ render :inline => <<-ERB
+<%= @users.map(&:name).join("\n") %>
+<%= paginate @users %>
+ERB
+ end
+end
+
+if defined? ActiveRecord
+ class AddressesController < ApplicationController
+ def index
+ @addresses = User::Address.page params[:page]
+ render :inline => <<-ERB
+ <%= @addresses.map(&:street).join("\n") %>
+ <%= paginate @addresses %>
+ ERB
+ end
+ end
+end
+
+# helpers
+Object.const_set(:ApplicationHelper, Module.new)
diff --git a/spec/fake_app/sinatra_app.rb b/spec/fake_app/sinatra_app.rb
new file mode 100644
index 0000000..1ee8e24
--- /dev/null
+++ b/spec/fake_app/sinatra_app.rb
@@ -0,0 +1,22 @@
+require 'fake_app/active_record/config' if defined? ActiveRecord
+require 'fake_app/data_mapper/config' if defined? DataMapper
+require 'fake_app/mongoid/config' if defined? Mongoid
+require 'fake_app/mongo_mapper/config' if defined? MongoMapper
+
+#models
+require 'fake_app/active_record/models' if defined? ActiveRecord
+require 'fake_app/data_mapper/models' if defined? DataMapper
+require 'fake_app/mongoid/models' if defined? Mongoid
+require 'fake_app/mongo_mapper/models' if defined? MongoMapper
+
+class SinatraApp < Sinatra::Base
+ register Kaminari::Helpers::SinatraHelpers
+
+ get '/users' do
+ @users = User.page params[:page]
+ erb <<-ERB
+<%= @users.map(&:name).join("\n") %>
+<%= paginate @users %>
+ERB
+ end
+end
diff --git a/spec/fake_app/views/alternative/kaminari/_first_page.html.erb b/spec/fake_app/views/alternative/kaminari/_first_page.html.erb
new file mode 100644
index 0000000..124343a
--- /dev/null
+++ b/spec/fake_app/views/alternative/kaminari/_first_page.html.erb
@@ -0,0 +1 @@
+<b><%= current_page %></b>
\ No newline at end of file
diff --git a/spec/fake_app/views/alternative/kaminari/_paginator.html.erb b/spec/fake_app/views/alternative/kaminari/_paginator.html.erb
new file mode 100644
index 0000000..8d6cbec
--- /dev/null
+++ b/spec/fake_app/views/alternative/kaminari/_paginator.html.erb
@@ -0,0 +1,3 @@
+<%= paginator.render do -%>
+ <%= first_page_tag %>
+<% end -%>
diff --git a/spec/fake_app/views/kaminari/bootstrap/_page.html.erb b/spec/fake_app/views/kaminari/bootstrap/_page.html.erb
new file mode 100644
index 0000000..bf46589
--- /dev/null
+++ b/spec/fake_app/views/kaminari/bootstrap/_page.html.erb
@@ -0,0 +1 @@
+<li class="bootstrap-page-link"><%= link_to page, url %></li>
diff --git a/spec/fake_app/views/kaminari/bootstrap/_paginator.html.erb b/spec/fake_app/views/kaminari/bootstrap/_paginator.html.erb
new file mode 100644
index 0000000..7022818
--- /dev/null
+++ b/spec/fake_app/views/kaminari/bootstrap/_paginator.html.erb
@@ -0,0 +1,7 @@
+<div class="bootstrap-paginator">
+<%= paginator.render do -%>
+<% each_page do |page| %>
+<%= page_tag(page) -%>
+<% end %>
+<% end %>
+</div>
diff --git a/spec/fake_gem.rb b/spec/fake_gem.rb
index a142811..fa3a1c2 100644
--- a/spec/fake_gem.rb
+++ b/spec/fake_gem.rb
@@ -1,6 +1,4 @@
# Simulate a gem providing a subclass of ActiveRecord::Base before the Railtie is loaded.
-require 'active_record'
-
class GemDefinedModel < ActiveRecord::Base
end
diff --git a/spec/generators/views_generator_spec.rb b/spec/generators/views_generator_spec.rb
new file mode 100644
index 0000000..02870d9
--- /dev/null
+++ b/spec/generators/views_generator_spec.rb
@@ -0,0 +1,18 @@
+require 'spec_helper'
+
+if defined?(Rails)
+ require 'rails/generators'
+ require 'generators/kaminari/views_generator'
+
+ describe Kaminari::Generators::GitHubApiHelper, :generator_spec => true do
+ describe '.get_files_in_master' do
+ subject { Kaminari::Generators::GitHubApiHelper.get_files_in_master }
+ it { should include(["README", "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"]) }
+ end
+
+ describe '.get_content_for' do
+ subject { Kaminari::Generators::GitHubApiHelper.get_content_for("README") }
+ it { should == "" }
+ end
+ end
+end
diff --git a/spec/helpers/action_view_extension_spec.rb b/spec/helpers/action_view_extension_spec.rb
index f82de3e..0c3285c 100644
--- a/spec/helpers/action_view_extension_spec.rb
+++ b/spec/helpers/action_view_extension_spec.rb
@@ -1,115 +1,301 @@
require 'spec_helper'
-describe 'Kaminari::ActionViewExtension' do
+describe 'Kaminari::ActionViewExtension', :if => defined?(Rails)do
describe '#paginate' do
before do
50.times {|i| User.create! :name => "user#{i}"}
@users = User.page(1)
end
+
subject { helper.paginate @users, :params => {:controller => 'users', :action => 'index'} }
it { should be_a String }
context 'escaping the pagination for javascript' do
it 'should escape for javascript' do
- lambda { escape_javascript(helper.paginate @users, :params => {:controller => 'users', :action => 'index'}) }.should_not raise_error
+ lambda { helper.escape_javascript(helper.paginate @users, :params => {:controller => 'users', :action => 'index'}) }.should_not raise_error
end
end
+
+ context 'accepts :theme option' do
+ before { helper.controller.append_view_path "spec/fake_app/views" }
+ subject { helper.paginate @users, :theme => "bootstrap", :params => {:controller => 'users', :action => 'index'} }
+ it { should match(/bootstrap-paginator/) }
+ it { should match(/bootstrap-page-link/) }
+ end
+
+ context 'accepts :view_prefix option' do
+ before { helper.controller.append_view_path "spec/fake_app/views" }
+ subject { helper.paginate @users, :views_prefix => "alternative/", :params => {:controller => 'users', :action => 'index'} }
+ it { should eq(" <b>1</b>\n") }
+ end
end
- describe '#link_to_next_page' do
+ describe '#link_to_previous_page' do
before do
50.times {|i| User.create! :name => "user#{i}"}
end
- context 'having more page' do
+
+ context 'having previous pages' do
before do
- @users = User.page(1)
+ @users = User.page(50)
end
+
context 'the default behaviour' do
- subject { helper.link_to_next_page @users, 'More', :params => {:controller => 'users', :action => 'index'} }
+ subject { helper.link_to_previous_page @users, 'Previous', :params => {:controller => 'users', :action => 'index'} }
it { should be_a String }
- it { should match /rel="next"/ }
+ it { should match(/rel="previous"/) }
end
+
context 'overriding rel=' do
- subject { helper.link_to_next_page @users, 'More', :rel => 'external', :params => {:controller => 'users', :action => 'index'} }
- it { should match /rel="external"/ }
+ subject { helper.link_to_previous_page @users, 'Previous', :rel => 'external', :params => {:controller => 'users', :action => 'index'} }
+ it { should match(/rel="external"/) }
end
end
- context 'the last page' do
+
+ context 'the first page' do
before do
- @users = User.page(2)
+ @users = User.page(1)
end
- subject { helper.link_to_next_page @users, 'More', :params => {:controller => 'users', :action => 'index'} }
+
+ subject { helper.link_to_previous_page @users, 'Previous', :params => {:controller => 'users', :action => 'index'} }
it { should_not be }
end
end
- describe '#page_entries_info' do
+ describe '#link_to_next_page' do
before do
- @users = User.page(1).per(25)
- end
- context 'having no entries' do
- subject { helper.page_entries_info @users, :params => {:controller => 'users', :action => 'index'} }
- it { should == 'No entries found' }
+ 50.times {|i| User.create! :name => "user#{i}"}
end
- context 'having 1 entry' do
+ context 'having more page' do
before do
- User.create!
- @users = User.page(1).per(25)
+ @users = User.page(1)
end
- subject { helper.page_entries_info @users, :params => {:controller => 'users', :action => 'index'} }
- it { should == 'Displaying <b>1</b> user' }
- context 'setting the entry name option to "member"' do
- subject { helper.page_entries_info @users, :entry_name => 'member', :params => {:controller => 'users', :action => 'index'} }
- it { should == 'Displaying <b>1</b> member' }
+ context 'the default behaviour' do
+ subject { helper.link_to_next_page @users, 'More', :params => {:controller => 'users', :action => 'index'} }
+ it { should be_a String }
+ it { should match(/rel="next"/) }
+ end
+
+ context 'overriding rel=' do
+ subject { helper.link_to_next_page @users, 'More', :rel => 'external', :params => {:controller => 'users', :action => 'index'} }
+ it { should match(/rel="external"/) }
end
end
- context 'having more than 1 but less than a page of entries' do
+ context 'the last page' do
before do
- 10.times {|i| User.create!}
- @users = User.page(1).per(25)
+ @users = User.page(2)
end
- subject { helper.page_entries_info @users, :params => {:controller => 'users', :action => 'index'} }
- it { should == 'Displaying <b>all 10</b> users' }
- context 'setting the entry name option to "member"' do
- subject { helper.page_entries_info @users, :entry_name => 'member', :params => {:controller => 'users', :action => 'index'} }
- it { should == 'Displaying <b>all 10</b> members' }
- end
+ subject { helper.link_to_next_page @users, 'More', :params => {:controller => 'users', :action => 'index'} }
+ it { should_not be }
end
+ end
- context 'having more than one page of entries' do
+ describe '#page_entries_info' do
+ context 'on a model without namespace' do
before do
- 50.times {|i| User.create!}
+ @users = User.page(1).per(25)
+ end
+
+ context 'having no entries' do
+ subject { helper.page_entries_info @users, :params => {:controller => 'users', :action => 'index'} }
+ it { should == 'No users found' }
+
+ context 'setting the entry name option to "member"' do
+ subject { helper.page_entries_info @users, :entry_name => 'member', :params => {:controller => 'users', :action => 'index'} }
+ it { should == 'No members found' }
+ end
end
- describe 'the first page' do
+ context 'having 1 entry' do
before do
+ User.create! :name => 'user1'
@users = User.page(1).per(25)
end
+
subject { helper.page_entries_info @users, :params => {:controller => 'users', :action => 'index'} }
- it { should == 'Displaying users <b>1&nbsp;-&nbsp;25</b> of <b>50</b> in total' }
+ it { should == 'Displaying <b>1</b> user' }
context 'setting the entry name option to "member"' do
subject { helper.page_entries_info @users, :entry_name => 'member', :params => {:controller => 'users', :action => 'index'} }
- it { should == 'Displaying members <b>1&nbsp;-&nbsp;25</b> of <b>50</b> in total' }
+ it { should == 'Displaying <b>1</b> member' }
end
end
- describe 'the next page' do
+ context 'having more than 1 but less than a page of entries' do
before do
- @users = User.page(2).per(25)
+ 10.times {|i| User.create! :name => "user#{i}"}
+ @users = User.page(1).per(25)
end
+
subject { helper.page_entries_info @users, :params => {:controller => 'users', :action => 'index'} }
- it { should == 'Displaying users <b>26&nbsp;-&nbsp;50</b> of <b>50</b> in total' }
+ it { should == 'Displaying <b>all 10</b> users' }
context 'setting the entry name option to "member"' do
subject { helper.page_entries_info @users, :entry_name => 'member', :params => {:controller => 'users', :action => 'index'} }
- it { should == 'Displaying members <b>26&nbsp;-&nbsp;50</b> of <b>50</b> in total' }
+ it { should == 'Displaying <b>all 10</b> members' }
end
end
+
+ context 'having more than one page of entries' do
+ before do
+ 50.times {|i| User.create! :name => "user#{i}"}
+ end
+
+ describe 'the first page' do
+ before do
+ @users = User.page(1).per(25)
+ end
+
+ subject { helper.page_entries_info @users, :params => {:controller => 'users', :action => 'index'} }
+ it { should == 'Displaying users <b>1&nbsp;-&nbsp;25</b> of <b>50</b> in total' }
+
+ context 'setting the entry name option to "member"' do
+ subject { helper.page_entries_info @users, :entry_name => 'member', :params => {:controller => 'users', :action => 'index'} }
+ it { should == 'Displaying members <b>1&nbsp;-&nbsp;25</b> of <b>50</b> in total' }
+ end
+ end
+
+ describe 'the next page' do
+ before do
+ @users = User.page(2).per(25)
+ end
+
+ subject { helper.page_entries_info @users, :params => {:controller => 'users', :action => 'index'} }
+ it { should == 'Displaying users <b>26&nbsp;-&nbsp;50</b> of <b>50</b> in total' }
+
+ context 'setting the entry name option to "member"' do
+ subject { helper.page_entries_info @users, :entry_name => 'member', :params => {:controller => 'users', :action => 'index'} }
+ it { should == 'Displaying members <b>26&nbsp;-&nbsp;50</b> of <b>50</b> in total' }
+ end
+ end
+ end
+ end
+ context 'on a model with namespace' do
+ before do
+ @addresses = User::Address.page(1).per(25)
+ end
+
+ context 'having no entries' do
+ subject { helper.page_entries_info @addresses, :params => {:controller => 'addresses', :action => 'index'} }
+ it { should == 'No addresses found' }
+ end
+
+ context 'having 1 entry' do
+ before do
+ User::Address.create!
+ @addresses = User::Address.page(1).per(25)
+ end
+
+ subject { helper.page_entries_info @addresses, :params => {:controller => 'addresses', :action => 'index'} }
+ it { should == 'Displaying <b>1</b> address' }
+
+ context 'setting the entry name option to "place"' do
+ subject { helper.page_entries_info @addresses, :entry_name => 'place', :params => {:controller => 'addresses', :action => 'index'} }
+ it { should == 'Displaying <b>1</b> place' }
+ end
+ end
+
+ context 'having more than 1 but less than a page of entries' do
+ before do
+ 10.times {|i| User::Address.create!}
+ @addresses = User::Address.page(1).per(25)
+ end
+
+ subject { helper.page_entries_info @addresses, :params => {:controller => 'addresses', :action => 'index'} }
+ it { should == 'Displaying <b>all 10</b> addresses' }
+
+ context 'setting the entry name option to "place"' do
+ subject { helper.page_entries_info @addresses, :entry_name => 'place', :params => {:controller => 'addresses', :action => 'index'} }
+ it { should == 'Displaying <b>all 10</b> places' }
+ end
+ end
+
+ context 'having more than one page of entries' do
+ before do
+ 50.times {|i| User::Address.create!}
+ end
+
+ describe 'the first page' do
+ before do
+ @addresses = User::Address.page(1).per(25)
+ end
+
+ subject { helper.page_entries_info @addresses, :params => {:controller => 'addresses', :action => 'index'} }
+ it { should == 'Displaying addresses <b>1&nbsp;-&nbsp;25</b> of <b>50</b> in total' }
+
+ context 'setting the entry name option to "place"' do
+ subject { helper.page_entries_info @addresses, :entry_name => 'place', :params => {:controller => 'addresses', :action => 'index'} }
+ it { should == 'Displaying places <b>1&nbsp;-&nbsp;25</b> of <b>50</b> in total' }
+ end
+ end
+
+ describe 'the next page' do
+ before do
+ @addresses = User::Address.page(2).per(25)
+ end
+
+ subject { helper.page_entries_info @addresses, :params => {:controller => 'addresses', :action => 'index'} }
+ it { should == 'Displaying addresses <b>26&nbsp;-&nbsp;50</b> of <b>50</b> in total' }
+
+ context 'setting the entry name option to "place"' do
+ subject { helper.page_entries_info @addresses, :entry_name => 'place', :params => {:controller => 'addresses', :action => 'index'} }
+ it { should == 'Displaying places <b>26&nbsp;-&nbsp;50</b> of <b>50</b> in total' }
+ end
+ end
+ end
+ end
+
+ context 'on a PaginatableArray' do
+ before do
+ @numbers = Kaminari.paginate_array(%w{one two three}).page(1)
+ end
+
+ subject { helper.page_entries_info @numbers }
+ it { should == 'Displaying <b>all 3</b> entries' }
+ end
+ end
+
+ describe '#rel_next_prev_link_tags' do
+ before do
+ 80.times {|i| User.create! :name => "user#{i}"}
+ end
+
+ context 'the first page' do
+ before do
+ @users = User.page(1).per(25)
+ end
+
+ subject { helper.rel_next_prev_link_tags @users, :params => {:controller => 'users', :action => 'index'} }
+ it { should_not match(/rel="prev"/) }
+ it { should match(/rel="next"/) }
+ it { should match(/\?page=2/) }
+ end
+
+ context 'the middle page' do
+ before do
+ @users = User.page(3).per(25)
+ end
+
+ subject { helper.rel_next_prev_link_tags @users, :params => {:controller => 'users', :action => 'index'} }
+ it { should match(/rel="prev"/) }
+ it { should match(/\?page=2/) }
+ it { should match(/rel="next"/) }
+ it { should match(/\?page=4/) }
+ end
+
+ context 'the last page' do
+ before do
+ @users = User.page(4).per(25)
+ end
+
+ subject { helper.rel_next_prev_link_tags @users, :params => {:controller => 'users', :action => 'index'} }
+ it { should match(/rel="prev"/) }
+ it { should match(/\?page=3"/) }
+ it { should_not match(/rel="next"/) }
end
end
end
diff --git a/spec/helpers/helpers_spec.rb b/spec/helpers/helpers_spec.rb
index d1ff21d..fe6d7ce 100644
--- a/spec/helpers/helpers_spec.rb
+++ b/spec/helpers/helpers_spec.rb
@@ -8,10 +8,19 @@ describe 'Kaminari::Helpers::Paginator' do
params { {} }
options { {} }
url_for {|h| "/foo?page=#{h[:page]}"}
+ link_to { "<a href='#'>link</a>" }
end
r
end
+ describe "view helper methods delegated to template" do
+ before do
+ @paginator = Paginator.new(template, :params => {})
+ end
+ subject { @paginator.link_to("link", "#") }
+ it { should == "<a href='#'>link</a>" }
+ end
+
describe '#params' do
before do
@paginator = Paginator.new(template, :params => {:controller => 'foo', :action => 'bar'})
@@ -35,13 +44,13 @@ describe 'Kaminari::Helpers::Paginator' do
# end
# context '1 page in total' do
-# subject { tags_with :num_pages => 1, :current_page => 1 }
+# subject { tags_with :total_pages => 1, :current_page => 1 }
# it { should have(0).tags }
# end
# context '10 pages in total' do
# context 'first page' do
-# subject { tags_with :num_pages => 10, :current_page => 1 }
+# subject { tags_with :total_pages => 10, :current_page => 1 }
# it { should_not contain_tag PrevLink }
# it { should contain_tag PrevSpan }
# it { should contain_tag CurrentPage }
@@ -54,7 +63,7 @@ describe 'Kaminari::Helpers::Paginator' do
# end
# context 'second page' do
-# subject { tags_with :num_pages => 10, :current_page => 2 }
+# subject { tags_with :total_pages => 10, :current_page => 2 }
# it { should contain_tag PrevLink }
# it { should_not contain_tag PrevSpan }
# it { should contain_tag CurrentPage }
@@ -67,7 +76,7 @@ describe 'Kaminari::Helpers::Paginator' do
# end
# context 'third page' do
-# subject { tags_with :num_pages => 10, :current_page => 3 }
+# subject { tags_with :total_pages => 10, :current_page => 3 }
# it { should contain_tag PrevLink }
# it { should_not contain_tag PrevSpan }
# it { should contain_tag CurrentPage }
@@ -80,7 +89,7 @@ describe 'Kaminari::Helpers::Paginator' do
# end
# context 'fourth page(no truncation)' do
-# subject { tags_with :num_pages => 10, :current_page => 4 }
+# subject { tags_with :total_pages => 10, :current_page => 4 }
# it { should contain_tag PrevLink }
# it { should_not contain_tag PrevSpan }
# it { should contain_tag CurrentPage }
@@ -93,7 +102,7 @@ describe 'Kaminari::Helpers::Paginator' do
# end
# context 'seventh page(no truncation)' do
-# subject { tags_with :num_pages => 10, :current_page => 7 }
+# subject { tags_with :total_pages => 10, :current_page => 7 }
# it { should contain_tag PrevLink }
# it { should_not contain_tag PrevSpan }
# it { should contain_tag CurrentPage }
@@ -106,7 +115,7 @@ describe 'Kaminari::Helpers::Paginator' do
# end
# context 'eighth page' do
-# subject { tags_with :num_pages => 10, :current_page => 8 }
+# subject { tags_with :total_pages => 10, :current_page => 8 }
# it { should contain_tag PrevLink }
# it { should_not contain_tag PrevSpan }
# it { should contain_tag CurrentPage }
@@ -119,7 +128,7 @@ describe 'Kaminari::Helpers::Paginator' do
# end
# context 'last page' do
-# subject { tags_with :num_pages => 10, :current_page => 10 }
+# subject { tags_with :total_pages => 10, :current_page => 10 }
# it { should contain_tag PrevLink }
# it { should_not contain_tag PrevSpan }
# it { should contain_tag CurrentPage }
diff --git a/spec/helpers/sinatra_helpers_spec.rb b/spec/helpers/sinatra_helpers_spec.rb
index 750e326..d189531 100644
--- a/spec/helpers/sinatra_helpers_spec.rb
+++ b/spec/helpers/sinatra_helpers_spec.rb
@@ -1,173 +1,222 @@
require 'spec_helper'
-require 'spec_helper_for_sinatra'
-
-ERB_TEMPLATE_FOR_PAGINATE = <<EOT
-<div>
-<ul>
-<% @users.each do |user| %>
- <li class="user_info"><%= user.id %></li>
-<% end %>
-</ul>
-<%= paginate @users, @options %>
-</div>
+
+if defined? Sinatra
+ ERB_TEMPLATE_FOR_PAGINATE = <<EOT
+ <div>
+ <ul>
+ <% @users.each do |user| %>
+ <li class="user_info"><%= user.id %></li>
+ <% end %>
+ </ul>
+ <%= paginate @users, @options %>
+ </div>
EOT
-ERB_TEMPLATE_FOR_NEXT_PAGE = <<EOT
-<div>
-<ul>
-<% @users.each do |user| %>
- <li class="user_info"><%= user.id %></li>
-<% end %>
-</ul>
-<%= link_to_next_page(@users, "Next!", {:id => 'next_page_link'}.merge(@options || {})) %>
-</div>
+ ERB_TEMPLATE_FOR_PREVIOUS_PAGE = <<EOT
+ <div>
+ <ul>
+ <% @users.each do |user| %>
+ <li class="user_info"><%= user.id %></li>
+ <% end %>
+ </ul>
+ <%= link_to_previous_page(@users, "Previous!", {:id => 'previous_page_link'}.merge(@options || {})) %>
+ </div>
EOT
-describe 'Kaminari::Helpers::SinatraHelper' do
- before do
- 50.times {|i| User.create! :name => "user#{i}"}
- end
+ ERB_TEMPLATE_FOR_NEXT_PAGE = <<EOT
+ <div>
+ <ul>
+ <% @users.each do |user| %>
+ <li class="user_info"><%= user.id %></li>
+ <% end %>
+ </ul>
+ <%= link_to_next_page(@users, "Next!", {:id => 'next_page_link'}.merge(@options || {})) %>
+ </div>
+EOT
- describe '#paginate' do
+ describe 'Kaminari::Helpers::SinatraHelper' do
before do
- mock_app do
- register Kaminari::Helpers::SinatraHelpers
- get '/users' do
- @page = params[:page] || 1
- @users = User.page(@page)
- @options = {}
- erb ERB_TEMPLATE_FOR_PAGINATE
+ 50.times {|i| User.create! :name => "user#{i}"}
+ end
+
+ describe '#paginate' do
+ before do
+ mock_app do
+ register Kaminari::Helpers::SinatraHelpers
+ get '/users' do
+ @page = params[:page] || 1
+ @users = User.page(@page)
+ @options = {}
+ erb ERB_TEMPLATE_FOR_PAGINATE
+ end
end
end
- end
- context 'normal paginations with Sinatra' do
- before { get '/users' }
+ context 'normal paginations with Sinatra' do
+ before { get '/users' }
- it 'should have a navigation tag' do
- last_document.search('nav.pagination').should_not be_empty
- end
+ it 'should have a navigation tag' do
+ last_document.search('nav.pagination').should_not be_empty
+ end
- it 'should have pagination links' do
- last_document.search('.page a').should have_at_least(1).items
- last_document.search('.next a').should have_at_least(1).items
- last_document.search('.last a').should have_at_least(1).items
- end
+ it 'should have pagination links' do
+ last_document.search('.page a').should have_at_least(1).items
+ last_document.search('.next a').should have_at_least(1).items
+ last_document.search('.last a').should have_at_least(1).items
+ end
- it 'should point to current page' do
- last_document.search('.current').text.should match /1/
+ it 'should point to current page' do
+ last_document.search('.current').text.should match(/1/)
- get '/users?page=2'
- last_document.search('.current').text.should match /2/
- end
+ get '/users?page=2'
+ last_document.search('.current').text.should match(/2/)
+ end
- it 'should load 25 users' do
- last_document.search('li.user_info').should have(25).items
- end
+ it 'should load 25 users' do
+ last_document.search('li.user_info').should have(25).items
+ end
- it 'should preserve params' do
- get '/users?foo=bar'
- last_document.search('.page a').should(be_all do |elm|
- elm.attribute('href').value =~ /foo=bar/
- end)
+ it 'should preserve params' do
+ get '/users?foo=bar'
+ last_document.search('.page a').should(be_all do |elm|
+ elm.attribute('href').value =~ /foo=bar/
+ end)
+ end
end
- end
- context 'optional paginations with Sinatra' do
- it 'should have 5 windows with 1 gap' do
- mock_app do
- register Kaminari::Helpers::SinatraHelpers
- get '/users' do
- @page = params[:page] || 1
- @users = User.page(@page).per(5)
- @options = {}
- erb ERB_TEMPLATE_FOR_PAGINATE
+ context 'optional paginations with Sinatra' do
+ it 'should have 5 windows with 1 gap' do
+ mock_app do
+ register Kaminari::Helpers::SinatraHelpers
+ get '/users' do
+ @page = params[:page] || 1
+ @users = User.page(@page).per(5)
+ @options = {}
+ erb ERB_TEMPLATE_FOR_PAGINATE
+ end
end
- end
- get '/users'
- last_document.search('.page').should have(6).items
- last_document.search('.gap').should have(1).item
- end
+ get '/users'
+ last_document.search('.page').should have(6).items
+ last_document.search('.gap').should have(1).item
+ end
- it 'should controll the inner window size' do
- mock_app do
- register Kaminari::Helpers::SinatraHelpers
- get '/users' do
- @page = params[:page] || 1
- @users = User.page(@page).per(3)
- @options = {:window => 10}
- erb ERB_TEMPLATE_FOR_PAGINATE
+ it 'should controll the inner window size' do
+ mock_app do
+ register Kaminari::Helpers::SinatraHelpers
+ get '/users' do
+ @page = params[:page] || 1
+ @users = User.page(@page).per(3)
+ @options = {:window => 10}
+ erb ERB_TEMPLATE_FOR_PAGINATE
+ end
end
+
+ get '/users'
+ last_document.search('.page').should have(12).items
+ last_document.search('.gap').should have(1).item
end
- get '/users'
- last_document.search('.page').should have(12).items
- last_document.search('.gap').should have(1).item
+ it 'should specify a page param name' do
+ mock_app do
+ register Kaminari::Helpers::SinatraHelpers
+ get '/users' do
+ @page = params[:page] || 1
+ @users = User.page(@page).per(3)
+ @options = {:param_name => :user_page}
+ erb ERB_TEMPLATE_FOR_PAGINATE
+ end
+ end
+
+ get '/users'
+ last_document.search('.page a').should(be_all do |elm|
+ elm.attribute('href').value =~ /user_page=\d+/
+ end)
+ end
end
+ end
- it 'should specify a page param name' do
+ describe '#link_to_previous_page' do
+ before do
mock_app do
register Kaminari::Helpers::SinatraHelpers
get '/users' do
- @page = params[:page] || 1
- @users = User.page(@page).per(3)
- @options = {:param_name => :user_page}
- erb ERB_TEMPLATE_FOR_PAGINATE
+ @page = params[:page] || 2
+ @users = User.page(@page)
+ erb ERB_TEMPLATE_FOR_PREVIOUS_PAGE
end
- end
- get '/users'
- last_document.search('.page a').should(be_all do |elm|
- elm.attribute('href').value =~ /user_page=\d+/
- end)
+ get '/users_placeholder' do
+ @page = params[:page] || 2
+ @options = {:placeholder => %{<span id='no_previous_page'>No Previous Page</span>}}
+ @users = User.page(@page)
+ erb ERB_TEMPLATE_FOR_PREVIOUS_PAGE
+ end
+ end
end
- end
- end
- describe '#link_to_next_page' do
- before do
- mock_app do
- register Kaminari::Helpers::SinatraHelpers
- get '/users' do
- @page = params[:page] || 1
- @users = User.page(@page)
- erb ERB_TEMPLATE_FOR_NEXT_PAGE
+ context 'having more page' do
+ it 'should have a more page link' do
+ get '/users'
+ last_document.search('a#previous_page_link').should be_present
+ last_document.search('a#previous_page_link').text.should match(/Previous!/)
end
+ end
- get '/users_placeholder' do
- @page = params[:page] || 1
- @options = {:placeholder => %{<span id='no_next_page'>No Next Page</span>}}
- @users = User.page(@page)
- erb ERB_TEMPLATE_FOR_NEXT_PAGE
+ context 'the first page' do
+ it 'should not have a more page link' do
+ get '/users?page=1'
+ last_document.search('a#previous_page_link').should be_empty
end
- end
- end
- context 'having more page' do
- it 'should have a more page link' do
- get '/users'
- last_document.search('a#next_page_link').should be_present
- last_document.search('a#next_page_link').text.should match /Next!/
+ it 'should have a no more page notation using placeholder' do
+ get '/users_placeholder?page=1'
+ last_document.search('a#previous_page_link').should be_empty
+ last_document.search('span#no_previous_page').should be_present
+ last_document.search('span#no_previous_page').text.should match(/No Previous Page/)
+ end
end
end
- context 'the last page' do
+ describe '#link_to_next_page' do
before do
- User.delete_all
- 50.times {|i| User.create! :name => "user#{i}"}
+ mock_app do
+ register Kaminari::Helpers::SinatraHelpers
+ get '/users' do
+ @page = params[:page] || 1
+ @users = User.page(@page)
+ erb ERB_TEMPLATE_FOR_NEXT_PAGE
+ end
+
+ get '/users_placeholder' do
+ @page = params[:page] || 1
+ @options = {:placeholder => %{<span id='no_next_page'>No Next Page</span>}}
+ @users = User.page(@page)
+ erb ERB_TEMPLATE_FOR_NEXT_PAGE
+ end
+ end
end
- it 'should not have a more page link' do
- get '/users?page=2'
- last_document.search('a#next_page_link').should be_empty
+ context 'having more page' do
+ it 'should have a more page link' do
+ get '/users'
+ last_document.search('a#next_page_link').should be_present
+ last_document.search('a#next_page_link').text.should match(/Next!/)
+ end
end
- it 'should have a no more page notation using placeholder' do
- get '/users_placeholder?page=2'
- last_document.search('a#next_page_link').should be_empty
- last_document.search('span#no_next_page').should be_present
- last_document.search('span#no_next_page').text.should match /No Next Page/
+ context 'the last page' do
+ it 'should not have a more page link' do
+ get '/users?page=2'
+ last_document.search('a#next_page_link').should be_empty
+ end
+
+ it 'should have a no more page notation using placeholder' do
+ get '/users_placeholder?page=2'
+ last_document.search('a#next_page_link').should be_empty
+ last_document.search('span#no_next_page').should be_present
+ last_document.search('span#no_next_page').text.should match(/No Next Page/)
+ end
end
end
end
diff --git a/spec/helpers/tags_spec.rb b/spec/helpers/tags_spec.rb
index f8a96d3..54e18f9 100644
--- a/spec/helpers/tags_spec.rb
+++ b/spec/helpers/tags_spec.rb
@@ -28,11 +28,11 @@ describe 'Kaminari::Helpers' do
describe '#last?' do
context 'current_page == page' do
- subject { Paginator::PageProxy.new({:num_pages => 39}, 39, nil) }
+ subject { Paginator::PageProxy.new({:total_pages => 39}, 39, nil) }
its(:last?) { should be_true }
end
context 'current_page != page' do
- subject { Paginator::PageProxy.new({:num_pages => 39}, 38, nil) }
+ subject { Paginator::PageProxy.new({:total_pages => 39}, 38, nil) }
its(:last?) { should_not be_true }
end
end
@@ -75,16 +75,16 @@ describe 'Kaminari::Helpers' do
end
describe '#right_outer?' do
- context 'num_pages - page > right' do
- subject { Paginator::PageProxy.new({:num_pages => 10, :right => 3}, 6, nil) }
+ context 'total_pages - page > right' do
+ subject { Paginator::PageProxy.new({:total_pages => 10, :right => 3}, 6, nil) }
its(:right_outer?) { should_not be_true }
end
- context 'num_pages - page == right' do
- subject { Paginator::PageProxy.new({:num_pages => 10, :right => 3}, 7, nil) }
+ context 'total_pages - page == right' do
+ subject { Paginator::PageProxy.new({:total_pages => 10, :right => 3}, 7, nil) }
its(:right_outer?) { should_not be_true }
end
- context 'num_pages - page < right' do
- subject { Paginator::PageProxy.new({:num_pages => 10, :right => 3}, 8, nil) }
+ context 'total_pages - page < right' do
+ subject { Paginator::PageProxy.new({:total_pages => 10, :right => 3}, 8, nil) }
its(:right_outer?) { should be_true }
end
end
diff --git a/spec/models/active_record/active_record_relation_methods_spec.rb b/spec/models/active_record/active_record_relation_methods_spec.rb
new file mode 100644
index 0000000..b53faea
--- /dev/null
+++ b/spec/models/active_record/active_record_relation_methods_spec.rb
@@ -0,0 +1,71 @@
+require 'spec_helper'
+
+if defined? ActiveRecord
+ describe Kaminari::ActiveRecordRelationMethods do
+ describe '#total_count' do
+ before do
+ @author = User.create! :name => 'author'
+ @author2 = User.create! :name => 'author2'
+ @author3 = User.create! :name => 'author3'
+ @books = 2.times.map {|i| @author.books_authored.create!(:title => "title%03d" % i) }
+ @books2 = 3.times.map {|i| @author2.books_authored.create!(:title => "title%03d" % i) }
+ @books3 = 4.times.map {|i| @author3.books_authored.create!(:title => "subject%03d" % i) }
+ @readers = 4.times.map { User.create! :name => 'reader' }
+ @books.each {|book| book.readers << @readers }
+ end
+
+ context "when the scope includes an order which references a generated column" do
+ it "should successfully count the results" do
+ @author.readers.by_read_count.page(1).total_count.should == @readers.size
+ end
+ end
+
+ context "when the scope use conditions on includes" do
+ it "should keep includes and successfully count the results" do
+ # Only @author and @author2 have books titled with the title00x partern
+ if ActiveRecord::VERSION::STRING >= "4.1.0"
+ User.includes(:books_authored).references(:books).where("books.title LIKE 'title00%'").page(1).total_count.should == 2
+ else
+ User.includes(:books_authored).where("books.title LIKE 'title00%'").page(1).total_count.should == 2
+ end
+ end
+ end
+
+ context 'when the Relation has custom select clause' do
+ specify do
+ lambda { User.select('*, 1 as one').page(1).total_count }.should_not raise_exception
+ end
+ end
+
+ context "when total_count receives options" do
+ it "should return a distinct total count for rails < 4.1" do
+ if ActiveRecord::VERSION::STRING < "4.1.0"
+ User.page(1).total_count(:name, :distinct => true).should == 4
+ end
+ end
+
+ it "should ignore the options for rails 4.1+" do
+ if ActiveRecord::VERSION::STRING >= "4.1.0"
+ User.page(1).total_count(:name, :distinct => true).should == 7
+ end
+ end
+ end
+
+ if ActiveRecord::VERSION::STRING < '4.1.0'
+ context 'when count receives options' do
+ it 'should return a distinct set by column for rails < 4.1' do
+ User.page(1).count(:name, :distinct => true).should == 4
+ end
+ end
+ end
+
+ context "when the scope returns an ActiveSupport::OrderedHash" do
+ it "should not throw exception by passing options to count" do
+ lambda {
+ @author.readers.by_read_count.page(1).total_count(:name, :distinct => true)
+ }.should_not raise_exception
+ end
+ end
+ end
+ end
+end
diff --git a/spec/models/active_record/scopes_spec.rb b/spec/models/active_record/scopes_spec.rb
new file mode 100644
index 0000000..44bfa64
--- /dev/null
+++ b/spec/models/active_record/scopes_spec.rb
@@ -0,0 +1,262 @@
+require 'spec_helper'
+
+if defined? ActiveRecord
+
+ describe Kaminari::ActiveRecordModelExtension do
+ before do
+ Kaminari.configure do |config|
+ config.page_method_name = :per_page_kaminari
+ end
+ class Comment < ActiveRecord::Base; end
+ end
+
+ subject { Comment }
+ it { should respond_to(:per_page_kaminari) }
+ it { should_not respond_to(:page) }
+
+ after do
+ Kaminari.configure do |config|
+ config.page_method_name = :page
+ end
+ end
+ end
+
+ shared_examples_for 'the first page' do
+ it { should have(25).users }
+ its('first.name') { should == 'user001' }
+ end
+
+ shared_examples_for 'blank page' do
+ it { should have(0).users }
+ end
+
+ describe Kaminari::ActiveRecordExtension do
+ before do
+ 1.upto(100) {|i| User.create! :name => "user#{'%03d' % i}", :age => (i / 10)}
+ 1.upto(100) {|i| GemDefinedModel.create! :name => "user#{'%03d' % i}", :age => (i / 10)}
+ 1.upto(100) {|i| Device.create! :name => "user#{'%03d' % i}", :age => (i / 10)}
+ end
+
+ [User, Admin, GemDefinedModel, Device].each do |model_class|
+ context "for #{model_class}" do
+ describe '#page' do
+ context 'page 1' do
+ subject { model_class.page 1 }
+ it_should_behave_like 'the first page'
+ end
+
+ context 'page 2' do
+ subject { model_class.page 2 }
+ it { should have(25).users }
+ its('first.name') { should == 'user026' }
+ end
+
+ context 'page without an argument' do
+ subject { model_class.page }
+ it_should_behave_like 'the first page'
+ end
+
+ context 'page < 1' do
+ subject { model_class.page 0 }
+ it_should_behave_like 'the first page'
+ end
+
+ context 'page > max page' do
+ subject { model_class.page 5 }
+ it_should_behave_like 'blank page'
+ end
+
+ describe 'ensure #order_values is preserved' do
+ subject { model_class.order('id').page 1 }
+ its('order_values.uniq') { should == ['id'] }
+ end
+ end
+
+ describe '#per' do
+ context 'page 1 per 5' do
+ subject { model_class.page(1).per(5) }
+ it { should have(5).users }
+ its('first.name') { should == 'user001' }
+ end
+
+ context "page 1 per nil (using default)" do
+ subject { model_class.page(1).per(nil) }
+ it { should have(model_class.default_per_page).users }
+ end
+ end
+
+ describe '#padding' do
+ context 'page 1 per 5 padding 1' do
+ subject { model_class.page(1).per(5).padding(1) }
+ it { should have(5).users }
+ its('first.name') { should == 'user002' }
+ end
+
+ context 'page 19 per 5 padding 5' do
+ subject { model_class.page(19).per(5).padding(5) }
+ its(:current_page) { should == 19 }
+ its(:total_pages) { should == 19 }
+ end
+ end
+
+ describe '#total_pages' do
+ context 'per 25 (default)' do
+ subject { model_class.page }
+ its(:total_pages) { should == 4 }
+ end
+
+ context 'per 7' do
+ subject { model_class.page(2).per(7) }
+ its(:total_pages) { should == 15 }
+ end
+
+ context 'per 65536' do
+ subject { model_class.page(50).per(65536) }
+ its(:total_pages) { should == 1 }
+ end
+
+ context 'per 0 (using default)' do
+ subject { model_class.page(50).per(0) }
+ its(:total_pages) { should == 4 }
+ end
+
+ context 'per -1 (using default)' do
+ subject { model_class.page(5).per(-1) }
+ its(:total_pages) { should == 4 }
+ end
+
+ context 'per "String value that can not be converted into Number" (using default)' do
+ subject { model_class.page(5).per('aho') }
+ its(:total_pages) { should == 4 }
+ end
+
+ context 'with max_pages < total pages count from database' do
+ before { model_class.max_pages_per 3 }
+ subject { model_class.page }
+ its(:total_pages) { should == 3 }
+ after { model_class.max_pages_per nil }
+ end
+
+ context 'with max_pages > total pages count from database' do
+ before { model_class.max_pages_per 11 }
+ subject { model_class.page }
+ its(:total_pages) { should == 4 }
+ after { model_class.max_pages_per nil }
+ end
+
+ context 'with max_pages is nil' do
+ before { model_class.max_pages_per nil }
+ subject { model_class.page }
+ its(:total_pages) { should == 4 }
+ end
+
+ context "with per(nil) using default" do
+ subject { model_class.page.per(nil) }
+ its(:total_pages) { should == 4 }
+ end
+ end
+
+ describe '#current_page' do
+ context 'page 1' do
+ subject { model_class.page }
+ its(:current_page) { should == 1 }
+ end
+
+ context 'page 2' do
+ subject { model_class.page(2).per 3 }
+ its(:current_page) { should == 2 }
+ end
+ end
+
+ describe '#next_page' do
+ context 'page 1' do
+ subject { model_class.page }
+ its(:next_page) { should == 2 }
+ end
+
+ context 'page 5' do
+ subject { model_class.page(5) }
+ its(:next_page) { should be_nil }
+ end
+ end
+
+ describe '#prev_page' do
+ context 'page 1' do
+ subject { model_class.page }
+ its(:prev_page) { should be_nil }
+ end
+
+ context 'page 5' do
+ subject { model_class.page(5) }
+ its(:prev_page) { should == 4 }
+ end
+ end
+
+ describe '#first_page?' do
+ context 'on first page' do
+ subject { model_class.page(1).per(10) }
+ its(:first_page?) { should == true }
+ end
+
+ context 'not on first page' do
+ subject { model_class.page(5).per(10) }
+ its(:first_page?) { should == false }
+ end
+ end
+
+ describe '#last_page?' do
+ context 'on last page' do
+ subject { model_class.page(10).per(10) }
+ its(:last_page?) { should == true }
+ end
+
+ context 'not on last page' do
+ subject { model_class.page(1).per(10) }
+ its(:last_page?) { should == false }
+ end
+ end
+
+ describe '#out_of_range?' do
+ context 'on last page' do
+ subject { model_class.page(10).per(10) }
+ its(:out_of_range?) { should == false }
+ end
+
+ context 'within range' do
+ subject { model_class.page(1).per(10) }
+ its(:out_of_range?) { should == false }
+ end
+
+ context 'out of range' do
+ subject { model_class.page(11).per(10) }
+ its(:out_of_range?) { should == true }
+ end
+ end
+
+ describe '#count' do
+ context 'page 1' do
+ subject { model_class.page }
+ its(:count) { should == 25 }
+ end
+
+ context 'page 2' do
+ subject { model_class.page 2 }
+ its(:count) { should == 25 }
+ end
+ end
+
+ context 'chained with .group' do
+ subject { model_class.group('age').page(2).per 5 }
+ # 0..10
+ its(:total_count) { should == 11 }
+ its(:total_pages) { should == 3 }
+ end
+
+ context 'activerecord descendants' do
+ subject { ActiveRecord::Base.descendants }
+ its(:length) { should_not == 0 }
+ end
+ end
+ end
+ end
+end
diff --git a/spec/models/active_record_relation_methods_spec.rb b/spec/models/active_record_relation_methods_spec.rb
deleted file mode 100644
index 1476389..0000000
--- a/spec/models/active_record_relation_methods_spec.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-require 'spec_helper'
-
-describe Kaminari::ActiveRecordRelationMethods do
- describe '#total_count' do
- before do
- @author = User.create! :name => 'author'
- @author2 = User.create! :name => 'author2'
- @author3 = User.create! :name => 'author3'
- @books = 2.times.map {|i| @author.books_authored.create!(:title => "title%03d" % i) }
- @books2 = 3.times.map {|i| @author2.books_authored.create!(:title => "title%03d" % i) }
- @books3 = 4.times.map {|i| @author3.books_authored.create!(:title => "subject%03d" % i) }
- @readers = 4.times.map { User.create! :name => 'reader' }
- @books.each {|book| book.readers << @readers }
- end
-
- context "when the scope includes an order which references a generated column" do
- it "should successfully count the results" do
- @author.readers.by_read_count.page(1).total_count.should == @readers.size
- end
- end
- context "when the scope use conditions on includes" do
- it "should keep includes and successfully count the results" do
- # Only @author and @author2 have books titled with the title00x partern
- User.includes(:books_authored).where("books.title LIKE 'title00%'").page(1).total_count.should == 2
- end
- end
- end
-end
diff --git a/spec/models/array_spec.rb b/spec/models/array_spec.rb
index a95c68c..30bd508 100644
--- a/spec/models/array_spec.rb
+++ b/spec/models/array_spec.rb
@@ -56,35 +56,40 @@ describe Kaminari::PaginatableArray do
end
end
- describe '#num_pages' do
+ describe '#total_pages' do
context 'per 25 (default)' do
subject { array.page }
- its(:num_pages) { should == 4 }
+ its(:total_pages) { should == 4 }
end
context 'per 7' do
subject { array.page(2).per(7) }
- its(:num_pages) { should == 15 }
+ its(:total_pages) { should == 15 }
end
context 'per 65536' do
subject { array.page(50).per(65536) }
- its(:num_pages) { should == 1 }
+ its(:total_pages) { should == 1 }
end
context 'per 0 (using default)' do
subject { array.page(50).per(0) }
- its(:num_pages) { should == 4 }
+ its(:total_pages) { should == 4 }
end
context 'per -1 (using default)' do
subject { array.page(5).per(-1) }
- its(:num_pages) { should == 4 }
+ its(:total_pages) { should == 4 }
end
context 'per "String value that can not be converted into Number" (using default)' do
subject { array.page(5).per('aho') }
- its(:num_pages) { should == 4 }
+ its(:total_pages) { should == 4 }
+ end
+
+ context 'per 25, padding 25' do
+ subject { array.page(1).padding(25) }
+ its(:total_pages) { should == 3 }
end
end
@@ -100,6 +105,30 @@ describe Kaminari::PaginatableArray do
end
end
+ describe '#next_page' do
+ context 'page 1' do
+ subject { array.page }
+ its(:next_page) { should == 2 }
+ end
+
+ context 'page 5' do
+ subject { array.page 5 }
+ its(:next_page) { should be_nil }
+ end
+ end
+
+ describe '#prev_page' do
+ context 'page 1' do
+ subject { array.page }
+ its(:prev_page) { should be_nil }
+ end
+
+ context 'page 5' do
+ subject { array.page 5 }
+ its(:prev_page) { should == 4 }
+ end
+ end
+
describe '#count' do
context 'page 1' do
subject { array.page }
@@ -113,9 +142,28 @@ describe Kaminari::PaginatableArray do
end
context 'when setting total count explicitly' do
- subject { Kaminari::PaginatableArray.new((1..10).to_a, :total_count => 9999).page(5).per(10) }
- it { should have(10).items }
- its(:first) { should == 1 }
- its(:total_count) { should == 9999 }
+ context "total_count > size of the given array" do
+ subject { Kaminari::PaginatableArray.new((1..10).to_a, :total_count => 9999).page(5).per(10) }
+
+ it { should have(0).items }
+ its(:first) { should be_nil }
+ its(:total_count) { should == 9999 }
+ end
+
+ context "total_count == size of the given array" do
+ subject { Kaminari.paginate_array((1..15).to_a, :total_count => 15).page(1).per(10) }
+
+ it { should have(10).items }
+ its(:first) { should == 1 }
+ its(:total_count) { should == 15 }
+ end
+
+ context "total_count < size of the given array" do
+ subject { Kaminari.paginate_array((1..25).to_a, :total_count => 15).page(2).per(10) }
+
+ it { should have(5).items }
+ its(:first) { should == 11 }
+ its(:total_count) { should == 15 }
+ end
end
end
diff --git a/spec/models/configuration_methods_spec.rb b/spec/models/configuration_methods_spec.rb
new file mode 100644
index 0000000..78c69ac
--- /dev/null
+++ b/spec/models/configuration_methods_spec.rb
@@ -0,0 +1,125 @@
+require 'spec_helper'
+
+describe "configuration methods" do
+ let(:model){ User }
+
+ describe "#default_per_page" do
+ if defined? ActiveRecord
+ describe 'AR::Base' do
+ subject { ActiveRecord::Base }
+ it { should_not respond_to :paginates_per }
+ end
+ end
+
+ subject { model.page(1) }
+
+ context "by default" do
+ its(:limit_value){ should == 25 }
+ end
+
+ context "when configuring both on global and model-level" do
+ before do
+ Kaminari.configure {|c| c.default_per_page = 50 }
+ model.paginates_per 100
+ end
+
+ its(:limit_value){ should == 100 }
+ end
+
+ context "when configuring multiple times" do
+ before do
+ Kaminari.configure {|c| c.default_per_page = 10 }
+ Kaminari.configure {|c| c.default_per_page = 20 }
+ end
+
+ its(:limit_value){ should == 20 }
+ end
+
+ after do
+ Kaminari.configure {|c| c.default_per_page = 25 }
+ model.paginates_per nil
+ end
+ end
+
+ describe "#max_per_page" do
+ if defined? ActiveRecord
+ describe 'AR::Base' do
+ subject { ActiveRecord::Base }
+ it { should_not respond_to :max_pages_per }
+ end
+ end
+
+ subject { model.page(1).per(1000) }
+
+ context "by default" do
+ its(:limit_value){ should == 1000 }
+ end
+
+ context "when configuring both on global and model-level" do
+ before do
+ Kaminari.configure {|c| c.max_per_page = 50 }
+ model.max_paginates_per 100
+ end
+
+ its(:limit_value){ should == 100 }
+ end
+
+ context "when configuring multiple times" do
+ before do
+ Kaminari.configure {|c| c.max_per_page = 10 }
+ Kaminari.configure {|c| c.max_per_page = 20 }
+ end
+
+ its(:limit_value){ should == 20 }
+ end
+
+ after do
+ Kaminari.configure {|c| c.max_per_page = nil }
+ model.max_paginates_per nil
+ end
+ end
+
+ describe "#max_pages" do
+ if defined? ActiveRecord
+ describe 'AR::Base' do
+ subject { ActiveRecord::Base }
+ it { should_not respond_to :max_paginates_per }
+ end
+ end
+
+ before do
+ 100.times do |count|
+ model.create!(:name => "User#{count}")
+ end
+ end
+
+ subject { model.page(1).per(5) }
+
+ context "by default" do
+ its(:total_pages){ should == 20 }
+ end
+
+ context "when configuring both on global and model-level" do
+ before do
+ Kaminari.configure {|c| c.max_pages = 10 }
+ model.max_pages_per 15
+ end
+
+ its(:total_pages){ should == 15 }
+ end
+
+ context "when configuring multiple times" do
+ before do
+ Kaminari.configure {|c| c.max_pages = 10 }
+ Kaminari.configure {|c| c.max_pages = 15 }
+ end
+
+ its(:total_pages){ should == 15 }
+ end
+
+ after do
+ Kaminari.configure {|c| c.max_pages = nil }
+ model.max_pages_per nil
+ end
+ end
+end
diff --git a/spec/models/data_mapper/data_mapper_spec.rb b/spec/models/data_mapper/data_mapper_spec.rb
new file mode 100644
index 0000000..3b5938e
--- /dev/null
+++ b/spec/models/data_mapper/data_mapper_spec.rb
@@ -0,0 +1,205 @@
+require 'spec_helper'
+
+if defined? DataMapper
+ # tests for issue #203
+ describe Kaminari::DataMapperCollectionMethods do
+ before do
+ 30.times do |i|
+ User.create(:name => "User#{i}", :age => i)
+ end
+ end
+
+ describe 'Model' do
+ subject { User }
+ it { User.all.count.should == 30 }
+ it { User.page(1).length.should == 25 }
+ it {
+ User.paginates_per(5)
+ User.page(1).length.should == 5
+ User.all.page(1).length.should == 5
+ User.paginates_per(nil) # reset to default
+ }
+ end
+
+ end
+
+ describe Kaminari::DataMapperExtension do
+ before do
+ 90.times do |i|
+ User.create(:name => "User#{i}", :age => i)
+ end
+ end
+
+ describe 'Collection' do
+ subject{ User.all }
+ it { should respond_to(:page) }
+ it { should_not respond_to(:per) }
+ end
+
+ describe 'Model' do
+ subject{ User }
+ it { should respond_to(:page) }
+ it { should respond_to(:default_per_page) }
+ it { should_not respond_to(:per) }
+ end
+
+ describe '#page' do
+ context 'page 0' do
+ subject { User.all(:age.gte => 60).page 0 }
+ it { should be_a DataMapper::Collection }
+ its(:current_page) { should == 1 }
+ its(:prev_page) { should be_nil }
+ its(:next_page) { should == 2 }
+ its('query.limit') { should == 25 }
+ its('query.offset') { should == 0 }
+ its(:total_count) { should == User.count(:age.gte => 60) }
+ its(:total_pages) { should == 2 }
+ end
+
+ context 'page 1' do
+ subject { User.all(:age.gte => 0).page 1 }
+ it { should be_a DataMapper::Collection }
+ its(:current_page) { should == 1 }
+ its(:prev_page) { should be_nil }
+ its(:next_page) { should == 2 }
+ its('query.limit') { should == 25 }
+ its('query.offset') { should == 0 }
+ its(:total_count) { should == 90 }
+ its(:total_pages) { should == 4 }
+ end
+
+ context 'page 2' do
+ subject { User.page 2 }
+ it { should be_a DataMapper::Collection }
+ its(:current_page) { should == 2 }
+ its(:prev_page) { should == 1 }
+ its(:next_page) { should == 3 }
+ its(:limit_value) { should == 25 }
+ its('query.limit') { should == 25 }
+ its('query.offset') { should == 25 }
+ its(:total_count) { should == 90 }
+ its(:total_pages) { should == 4 }
+ end
+
+ context 'page "foobar"' do
+ subject { User.page 'foobar' }
+ it { should be_a DataMapper::Collection }
+ its(:current_page) { should == 1 }
+ its(:prev_page) { should be_nil }
+ its(:next_page) { should == 2 }
+ its('query.limit') { should == 25 }
+ its('query.offset') { should == 0 }
+ its(:total_count) { should == 90 }
+ its(:total_pages) { should == 4 }
+ end
+
+ context 'with criteria before' do
+ subject { User.all(:age.gt => 60).page 2 }
+ it { should be_a DataMapper::Collection }
+ its(:current_page) { should == 2 }
+ its(:prev_page) { should == 1 }
+ its(:next_page) { should be_nil }
+ its('query.limit') { should == 25 }
+ its('query.offset') { should == 25 }
+ its(:total_count) { should == User.count(:age.gt => 60) }
+ its(:total_pages) { should == 2 }
+ end
+
+ context 'with criteria after' do
+ subject { User.page(2).all(:age.gt => 60) }
+ it { should be_a DataMapper::Collection }
+ its(:current_page) { should == 2 }
+ its(:prev_page) { should == 1 }
+ its(:next_page) { should be_nil }
+ its('query.limit') { should == 25 }
+ its('query.offset') { should == 25 }
+ its(:total_count) { should == User.count(:age.gt => 60) }
+ its(:total_pages) { should == 2 }
+ end
+ end
+
+ describe '#per' do
+ context 'on simple query' do
+ subject { User.page(2).per(20) }
+ it { should be_a DataMapper::Collection }
+ its(:current_page) { should == 2 }
+ its(:prev_page) { should == 1 }
+ its(:next_page) { should == 3 }
+ its('query.limit') { should == 20 }
+ its(:limit_value) { should == 20 }
+ its('query.offset') { should == 20 }
+ its(:total_count) { should == 90 }
+ its(:total_pages) { should == 5 }
+ end
+
+ context 'on query with condition' do
+ subject { User.page(5).all(:age.lte => 80).per(13) }
+ its(:current_page) { should == 5 }
+ its(:prev_page) { should == 4 }
+ its(:next_page) { should == 6 }
+ its('query.limit') { should == 13 }
+ its('query.offset') { should == 52 }
+ its(:total_count) { should == 81 }
+ its(:total_pages) { should == 7 }
+ end
+
+ context 'on query with order' do
+ subject { User.page(5).all(:age.lte => 80, :order => [:age.asc]).per(13) }
+ it('includes user with age 52') { should include(User.first(:age => 52)) }
+ it('does not include user with age 51') { should_not include(User.first(:age => 51)) }
+ it('includes user with age 52') { should include(User.first(:age => 64)) }
+ it('does not include user with age 51') { should_not include(User.first(:age => 65)) }
+ its(:current_page) { should == 5 }
+ its(:prev_page) { should == 4 }
+ its(:next_page) { should == 6 }
+ its('query.limit') { should == 13 }
+ its('query.offset') { should == 52 }
+ its(:total_count) { should == 81 }
+ its(:total_pages) { should == 7 }
+ end
+
+ context 'on chained queries' do
+ subject { User.all(:age.gte => 50).page(3).all(:age.lte => 80).per(13) }
+ its(:current_page) { should == 3 }
+ its(:prev_page) { should == 2 }
+ its(:next_page) { should be_nil }
+ its('query.limit') { should == 13 }
+ its('query.offset') { should == 26 }
+ its(:total_count) { should == 31 }
+ its(:total_pages) { should == 3 }
+ end
+
+ context 'for association' do
+ before do
+ worker0 = User[0]
+ 30.times do |i|
+ worker0.projects << Project.create(:name => "Project#{i}")
+ end
+ worker0.projects.save
+ end
+
+ context 'on query' do
+ subject { User[0].projects.page(3).all(:name.like => 'Project%').per(5) }
+ its(:current_page) { should == 3 }
+ its(:prev_page) { should == 2 }
+ its(:next_page) { should == 4 }
+ its('query.limit') { should == 5 }
+ its('query.offset') { should == 10 }
+ its(:total_count) { should == 30 }
+ its(:total_pages) { should == 6 }
+ end
+
+ context 'after association conditions' do
+ subject { User.page(3).all(:projects => Project.all).per(5) }
+ its(:current_page) { should == 3 }
+ its(:prev_page) { should == 2 }
+ its(:next_page) { should == 4 }
+ its('query.limit') { should == 5 }
+ its('query.offset') { should == 10 }
+ its(:total_count) { should == 30 }
+ its(:total_pages) { should == 6 }
+ end
+ end
+ end
+ end
+end
diff --git a/spec/models/data_mapper_spec.rb b/spec/models/data_mapper_spec.rb
deleted file mode 100644
index 5efe486..0000000
--- a/spec/models/data_mapper_spec.rb
+++ /dev/null
@@ -1,181 +0,0 @@
-require 'spec_helper'
-require 'dm-core'
-require 'dm-migrations'
-require 'dm-aggregates'
-require 'kaminari/models/data_mapper_extension'
-
-describe Kaminari::DataMapperExtension do
- before :all do
- DataMapper.setup(:default, 'sqlite::memory:')
-
- class Worker
- include ::DataMapper::Resource
-
- property :id, Serial
- property :name, String, :required => true
- property :age, Integer, :required => true
-
- has n, :projects, :through => Resource
- end
-
- class Project
- include ::DataMapper::Resource
-
- property :id, Serial
- property :name, String, :required => true
-
- has n, :workers, :through => Resource
- end
-
- DataMapper.finalize
- DataMapper.auto_migrate!
-
- 300.times do |i|
- Worker.create(:name => "Worker#{i}", :age => i)
- end
-
- worker0 = Worker[0]
- 50.times do |i|
- worker0.projects << Project.create(:name => "Project#{i}")
- end
- worker0.projects.save
- end
-
- describe 'Collection' do
- subject{ Worker.all }
- it { should respond_to(:page) }
- it { should_not respond_to(:per) }
- end
-
- describe 'Model' do
- subject{ Worker }
- it { should respond_to(:page) }
- it { should respond_to(:default_per_page) }
- it { should_not respond_to(:per) }
- end
-
- describe '#page' do
- context 'page 0' do
- subject { Worker.all(:age.gte => 200).page 0 }
- it { should be_a DataMapper::Collection }
- its(:current_page) { should == 1 }
- its('query.limit') { should == 25 }
- its('query.offset') { should == 0 }
- its(:total_count) { should == Worker.count(:age.gte => 200) }
- its(:num_pages) { should == 4 }
- end
-
- context 'page 1' do
- subject { Worker.all(:age.gte => 0).page 1 }
- it { should be_a DataMapper::Collection }
- its(:current_page) { should == 1 }
- its('query.limit') { should == 25 }
- its('query.offset') { should == 0 }
- its(:total_count) { should == 300 }
- its(:num_pages) { should == 12 }
- end
-
- context 'page 2' do
- subject { Worker.page 2 }
- it { should be_a DataMapper::Collection }
- its(:current_page) { should == 2 }
- its(:limit_value) { should == 25 }
- its('query.limit') { should == 25 }
- its('query.offset') { should == 25 }
- its(:total_count) { should == 300 }
- its(:num_pages) { should == 12 }
- end
-
- context 'page "foobar"' do
- subject { Worker.page 'foobar' }
- it { should be_a DataMapper::Collection }
- its(:current_page) { should == 1 }
- its('query.limit') { should == 25 }
- its('query.offset') { should == 0 }
- its(:total_count) { should == 300 }
- its(:num_pages) { should == 12 }
- end
-
- context 'with criteria before' do
- subject { Worker.all(:age.gt => 100).page 2 }
- it { should be_a DataMapper::Collection }
- its(:current_page) { should == 2 }
- its('query.limit') { should == 25 }
- its('query.offset') { should == 25 }
- its(:total_count) { should == Worker.count(:age.gt => 100) }
- its(:num_pages) { should == 8 }
- end
-
- context 'with criteria after' do
- subject { Worker.page(2).all(:age.gt => 100) }
- it { should be_a DataMapper::Collection }
- its(:current_page) { should == 2 }
- its('query.limit') { should == 25 }
- its('query.offset') { should == 25 }
- its(:total_count) { should == Worker.count(:age.gt => 100) }
- its(:num_pages) { should == 8 }
- end
- end
-
- describe '#per' do
- context 'on simple query' do
- subject { Worker.page(2).per(10) }
- it { should be_a DataMapper::Collection }
- its(:current_page) { should == 2 }
- its('query.limit') { should == 10 }
- its(:limit_value) { should == 10 }
- its('query.offset') { should == 10 }
- its(:total_count) { should == 300 }
- its(:num_pages) { should == 30 }
- end
-
- context 'on query with condition' do
- subject { Worker.page(5).all(:age.lte => 100).per(13) }
- its(:current_page) { should == 5 }
- its('query.limit') { should == 13 }
- its('query.offset') { should == 52 }
- its(:total_count) { should == 101 }
- its(:num_pages) { should == 8 }
- end
-
- context 'on query with order' do
- subject { Worker.page(5).all(:age.lte => 100, :order => [:age.asc]).per(13) }
- it('includes worker with age 52') { should include(Worker.first(:age => 52)) }
- it('does not include worker with age 51') { should_not include(Worker.first(:age => 51)) }
- it('includes worker with age 52') { should include(Worker.first(:age => 64)) }
- it('does not include worker with age 51') { should_not include(Worker.first(:age => 65)) }
- its(:current_page) { should == 5 }
- its('query.limit') { should == 13 }
- its('query.offset') { should == 52 }
- its(:total_count) { should == 101 }
- its(:num_pages) { should == 8 }
- end
-
- context 'on chained queries' do
- subject { Worker.all(:age.gte => 50).page(3).all(:age.lte => 100).per(13) }
- its(:current_page) { should == 3 }
- its('query.limit') { should == 13 }
- its('query.offset') { should == 26 }
- its(:total_count) { should == 51 }
- its(:num_pages) { should == 4 }
- end
-
- context 'on query on association' do
- subject { Worker[0].projects.page(3).all(:name.like => 'Project%').per(5) }
- its(:current_page) { should == 3 }
- its('query.limit') { should == 5 }
- its('query.offset') { should == 10 }
- its(:total_count) { should == 50 }
- its(:num_pages) { should == 10 }
- end
-
- context 'on query with association conditions' do
- subject { Worker.page(3).all(:projects => Project.all).per(5) }
- its(:current_page) { should == 3 }
- its('query.limit') { should == 5 }
- its('query.offset') { should == 10 }
- its(:total_count) { should == 50 }
- its(:num_pages) { should == 10 }
- end
- end
-end
diff --git a/spec/models/default_per_page_spec.rb b/spec/models/default_per_page_spec.rb
deleted file mode 100644
index b116b9c..0000000
--- a/spec/models/default_per_page_spec.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-require 'spec_helper'
-
-describe 'default per_page' do
- describe 'AR::Base' do
- subject { ActiveRecord::Base }
- it { should_not respond_to :paginates_per }
- end
-
- subject { User.page 0 }
-
- context 'by default' do
- its(:limit_value) { should == 25 }
- end
-
- context 'when explicitly set via paginates_per' do
- before { User.paginates_per 1326 }
- its(:limit_value) { should == 1326 }
- after { User.paginates_per nil }
- end
-
- describe "default per_page value's independency per model" do
- context "when User's default per_page was changed" do
- before { User.paginates_per 1326 }
- subject { Book.page 0 }
- its(:limit_value) { should == 25 }
- after { User.paginates_per nil }
- end
- end
-end
diff --git a/spec/models/mongo_mapper/mongo_mapper_spec.rb b/spec/models/mongo_mapper/mongo_mapper_spec.rb
new file mode 100644
index 0000000..380827d
--- /dev/null
+++ b/spec/models/mongo_mapper/mongo_mapper_spec.rb
@@ -0,0 +1,84 @@
+require 'spec_helper'
+
+if defined? MongoMapper
+ describe Kaminari::MongoMapperExtension do
+ before(:each) do
+ User.destroy_all
+ 41.times { User.create!({:salary => 1}) }
+ end
+
+ describe '#page' do
+ context 'page 1' do
+ subject { User.page(1) }
+ it { should be_a Plucky::Query }
+ its(:current_page) { should == 1 }
+ its(:prev_page) { should be_nil }
+ its(:next_page) { should == 2 }
+ its(:limit_value) { should == 25 }
+ its(:total_pages) { should == 2 }
+ it { should skip(0) }
+ end
+
+ context 'page 2' do
+ subject { User.page 2 }
+ it { should be_a Plucky::Query }
+ its(:current_page) { should == 2 }
+ its(:prev_page) { should == 1 }
+ its(:next_page) { should be_nil }
+ its(:limit_value) { should == 25 }
+ its(:total_pages) { should == 2 }
+ it { should skip 25 }
+ end
+
+ context 'page "foobar"' do
+ subject { User.page 'foobar' }
+ it { should be_a Plucky::Query }
+ its(:current_page) { should == 1 }
+ its(:prev_page) { should be_nil }
+ its(:next_page) { should == 2 }
+ its(:limit_value) { should == 25 }
+ its(:total_pages) { should == 2 }
+ it { should skip 0 }
+ end
+
+ context 'with criteria before' do
+ it "should have the proper criteria source" do
+ User.where(:salary => 1).page(2).criteria.source.should == {:salary => 1}
+ end
+
+ subject { User.where(:salary => 1).page 2 }
+ its(:current_page) { should == 2 }
+ its(:prev_page) { should == 1 }
+ its(:next_page) { should be_nil }
+ its(:limit_value) { should == 25 }
+ its(:total_pages) { should == 2 }
+ it { should skip 25 }
+ end
+
+ context 'with criteria after' do
+ it "should have the proper criteria source" do
+ User.where(:salary => 1).page(2).criteria.source.should == {:salary => 1}
+ end
+
+ subject { User.page(2).where(:salary => 1) }
+ its(:current_page) { should == 2 }
+ its(:prev_page) { should == 1 }
+ its(:next_page) { should be_nil }
+ its(:limit_value) { should == 25 }
+ its(:total_pages) { should == 2 }
+ it { should skip 25 }
+ end
+ end
+
+ describe '#per' do
+ subject { User.page(2).per(10) }
+ it { should be_a Plucky::Query }
+ its(:current_page) { should == 2 }
+ its(:prev_page) { should == 1 }
+ its(:next_page) { should == 3 }
+ its(:limit_value) { should == 10 }
+ its(:total_pages) { should == 5 }
+ it { should skip 10 }
+ end
+ end
+end
diff --git a/spec/models/mongo_mapper_spec.rb b/spec/models/mongo_mapper_spec.rb
deleted file mode 100644
index 11244bd..0000000
--- a/spec/models/mongo_mapper_spec.rb
+++ /dev/null
@@ -1,82 +0,0 @@
-require 'spec_helper'
-require 'mongo_mapper'
-require 'kaminari/models/mongo_mapper_extension'
-
-describe Kaminari::MongoMapperExtension do
- before do
- begin
- MongoMapper.connection = Mongo::Connection.new('localhost', 27017)
- MongoMapper.database = "kaminari_test"
- class Developer
- include ::MongoMapper::Document
- key :salary, Integer
- end
-
- stub(subject).count { 300 } # in order to avoid DB access...
- rescue Mongo::ConnectionFailure
- pending 'can not connect to MongoDB'
- end
- end
-
- describe '#page' do
- context 'page 1' do
- subject { Developer.page(1) }
- it { should be_a Plucky::Query }
- its(:current_page) { should == 1 }
- its(:limit_value) { should == 25 }
- its(:num_pages) { should == 12 }
- it { should skip(0) }
- end
-
- context 'page 2' do
- subject { Developer.page 2 }
- it { should be_a Plucky::Query }
- its(:current_page) { should == 2 }
- its(:limit_value) { should == 25 }
- its(:num_pages) { should == 12 }
- it { should skip 25 }
- end
-
- context 'page "foobar"' do
- subject { Developer.page 'foobar' }
- it { should be_a Plucky::Query }
- its(:current_page) { should == 1 }
- its(:limit_value) { should == 25 }
- its(:num_pages) { should == 12 }
- it { should skip 0 }
- end
-
- context 'with criteria before' do
- it "should have the proper criteria source" do
- Developer.where(:salary => 1).page(2).criteria.source.should == {:salary => 1}
- end
-
- subject { Developer.where(:salary => 1).page 2 }
- its(:current_page) { should == 2 }
- its(:limit_value) { should == 25 }
- its(:num_pages) { should == 12 }
- it { should skip 25 }
- end
-
- context 'with criteria after' do
- it "should have the proper criteria source" do
- Developer.where(:salary => 1).page(2).criteria.source.should == {:salary => 1}
- end
-
- subject { Developer.page(2).where(:salary => 1) }
- its(:current_page) { should == 2 }
- its(:limit_value) { should == 25 }
- its(:num_pages) { should == 12 }
- it { should skip 25 }
- end
- end
-
- describe '#per' do
- subject { Developer.page(2).per(10) }
- it { should be_a Plucky::Query }
- its(:current_page) { should == 2 }
- its(:limit_value) { should == 10 }
- its(:num_pages) { should == 30 }
- it { should skip 10 }
- end
-end
diff --git a/spec/models/mongoid/mongoid_spec.rb b/spec/models/mongoid/mongoid_spec.rb
new file mode 100644
index 0000000..952c4f2
--- /dev/null
+++ b/spec/models/mongoid/mongoid_spec.rb
@@ -0,0 +1,197 @@
+require 'spec_helper'
+
+if defined? Mongoid
+ describe Kaminari::MongoidExtension do
+ before(:each) do
+ 41.times do
+ User.create!({:salary => 1})
+ end
+ end
+
+ describe 'max_scan', :if => Mongoid::VERSION >= '3' do
+ context 'less than total' do
+ context 'page 1' do
+ subject { User.max_scan(20).page 1 }
+ it { should be_a Mongoid::Criteria }
+ its(:current_page) { should == 1 }
+ its(:prev_page) { should be_nil }
+ its(:next_page) { should be_nil }
+ its(:limit_value) { should == 25 }
+ its(:total_pages) { should == 1 }
+ its(:total_count) { should == 20 }
+ it { should skip(0) }
+ end
+
+ context 'page 2' do
+ subject { User.max_scan(30).page 2 }
+ it { should be_a Mongoid::Criteria }
+ its(:current_page) { should == 2 }
+ its(:prev_page) { should == 1 }
+ its(:next_page) { should be_nil }
+ its(:limit_value) { should == 25 }
+ its(:total_pages) { should == 2 }
+ its(:total_count) { should == 30 }
+ it { should skip 25 }
+ end
+ end
+
+ context 'more than total' do
+ context 'page 1' do
+ subject { User.max_scan(60).page 1 }
+ it { should be_a Mongoid::Criteria }
+ its(:current_page) { should == 1 }
+ its(:prev_page) { should be_nil }
+ its(:next_page) { should == 2 }
+ its(:limit_value) { should == 25 }
+ its(:total_pages) { should == 2 }
+ its(:total_count) { should == 41 }
+ it { should skip(0) }
+ end
+
+ context 'page 2' do
+ subject { User.max_scan(60).page 2 }
+ it { should be_a Mongoid::Criteria }
+ its(:current_page) { should == 2 }
+ its(:prev_page) { should == 1 }
+ its(:next_page) { should be_nil }
+ its(:limit_value) { should == 25 }
+ its(:total_pages) { should == 2 }
+ its(:total_count) { should == 41 }
+ it { should skip 25 }
+ end
+ end
+ end
+
+ describe '#page' do
+
+ context 'page 1' do
+ subject { User.page 1 }
+ it { should be_a Mongoid::Criteria }
+ its(:current_page) { should == 1 }
+ its(:prev_page) { should be_nil }
+ its(:next_page) { should == 2 }
+ its(:limit_value) { should == 25 }
+ its(:total_pages) { should == 2 }
+ it { should skip(0) }
+ end
+
+ context 'page 2' do
+ subject { User.page 2 }
+ it { should be_a Mongoid::Criteria }
+ its(:current_page) { should == 2 }
+ its(:prev_page) { should == 1 }
+ its(:next_page) { should be_nil }
+ its(:limit_value) { should == 25 }
+ its(:total_pages) { should == 2 }
+ it { should skip 25 }
+ end
+
+ context 'page "foobar"' do
+ subject { User.page 'foobar' }
+ it { should be_a Mongoid::Criteria }
+ its(:current_page) { should == 1 }
+ its(:prev_page) { should be_nil }
+ its(:next_page) { should == 2 }
+ its(:limit_value) { should == 25 }
+ its(:total_pages) { should == 2 }
+ it { should skip 0 }
+ end
+
+ shared_examples 'complete valid pagination' do
+ if Mongoid::VERSION > '3.0.0'
+ its(:selector) { should == {'salary' => 1} }
+ else
+ its(:selector) { should == {:salary => 1} }
+ end
+ its(:current_page) { should == 2 }
+ its(:prev_page) { should == 1 }
+ its(:next_page) { should be_nil }
+ its(:limit_value) { should == 25 }
+ its(:total_pages) { should == 2 }
+ it { should skip 25 }
+ end
+
+ context 'with criteria before' do
+ subject { User.where(:salary => 1).page 2 }
+ it_should_behave_like 'complete valid pagination'
+ end
+
+ context 'with criteria after' do
+ subject { User.page(2).where(:salary => 1) }
+ it_should_behave_like 'complete valid pagination'
+ end
+
+ context "with database:", :if => Mongoid::VERSION >= '3' do
+ before :all do
+ 15.times { User.with(:database => "default_db").create!(:salary => 1) }
+ 10.times { User.with(:database => "other_db").create!(:salary => 1) }
+ end
+
+ context "default_db" do
+ subject { User.with(:database => "default_db").order_by(:artist.asc).page(1) }
+ its(:total_count) { should == 15 }
+ end
+
+ context "other_db" do
+ subject { User.with(:database => "other_db").order_by(:artist.asc).page(1) }
+ its(:total_count) { should == 10 }
+ end
+ end
+ end
+
+ describe '#per' do
+ subject { User.page(2).per(10) }
+ it { should be_a Mongoid::Criteria }
+ its(:current_page) { should == 2 }
+ its(:prev_page) { should == 1 }
+ its(:next_page) { should == 3 }
+ its(:limit_value) { should == 10 }
+ its(:total_pages) { should == 5 }
+ it { should skip 10 }
+ end
+
+ describe '#page in embedded documents' do
+ before do
+ @mongo_developer = MongoMongoidExtensionDeveloper.new
+ @mongo_developer.frameworks.new(:name => "rails", :language => "ruby")
+ @mongo_developer.frameworks.new(:name => "merb", :language => "ruby")
+ @mongo_developer.frameworks.new(:name => "sinatra", :language => "ruby")
+ @mongo_developer.frameworks.new(:name => "cakephp", :language => "php")
+ @mongo_developer.frameworks.new(:name => "tornado", :language => "python")
+ end
+
+ context 'page 1' do
+ subject { @mongo_developer.frameworks.page(1).per(1) }
+ it { should be_a Mongoid::Criteria }
+ its(:total_count) { should == 5 }
+ its(:limit_value) { should == 1 }
+ its(:current_page) { should == 1 }
+ its(:prev_page) { should be_nil }
+ its(:next_page) { should == 2 }
+ its(:total_pages) { should == 5 }
+ end
+
+ context 'with criteria after' do
+ subject { @mongo_developer.frameworks.page(1).per(2).where(:language => "ruby") }
+ it { should be_a Mongoid::Criteria }
+ its(:total_count) { should == 3 }
+ its(:limit_value) { should == 2 }
+ its(:current_page) { should == 1 }
+ its(:prev_page) { should be_nil }
+ its(:next_page) { should == 2 }
+ its(:total_pages) { should == 2 }
+ end
+
+ context 'with criteria before' do
+ subject { @mongo_developer.frameworks.where(:language => "ruby").page(1).per(2) }
+ it { should be_a Mongoid::Criteria }
+ its(:total_count) { should == 3 }
+ its(:limit_value) { should == 2 }
+ its(:current_page) { should == 1 }
+ its(:prev_page) { should be_nil }
+ its(:next_page) { should == 2 }
+ its(:total_pages) { should == 2 }
+ end
+ end
+ end
+end
diff --git a/spec/models/mongoid_spec.rb b/spec/models/mongoid_spec.rb
deleted file mode 100644
index 1a8d9a8..0000000
--- a/spec/models/mongoid_spec.rb
+++ /dev/null
@@ -1,129 +0,0 @@
-require 'spec_helper'
-require 'mongoid'
-require 'kaminari/models/mongoid_extension'
-
-describe Kaminari::MongoidExtension do
- before :all do
- class Developer
- include ::Mongoid::Document
- field :salary, :type => Integer
- end
- end
-
- describe '#page' do
- before do
- stub(subject).count { 300 } # in order to avoid DB access...
- end
-
- context 'page 1' do
- subject { Developer.page 1 }
- it { should be_a Mongoid::Criteria }
- its(:current_page) { should == 1 }
- its(:limit_value) { should == 25 }
- its(:num_pages) { should == 12 }
- it { should skip(0) }
- end
-
- context 'page 2' do
- subject { Developer.page 2 }
- it { should be_a Mongoid::Criteria }
- its(:current_page) { should == 2 }
- its(:limit_value) { should == 25 }
- its(:num_pages) { should == 12 }
- it { should skip 25 }
- end
-
- context 'page "foobar"' do
- subject { Developer.page 'foobar' }
- it { should be_a Mongoid::Criteria }
- its(:current_page) { should == 1 }
- its(:limit_value) { should == 25 }
- its(:num_pages) { should == 12 }
- it { should skip 0 }
- end
-
- context 'with criteria before' do
- subject { Developer.where(:salary => 1).page 2 }
- its(:selector) { should == {:salary => 1} }
- its(:current_page) { should == 2 }
- its(:limit_value) { should == 25 }
- its(:num_pages) { should == 12 }
- it { should skip 25 }
- end
-
- context 'with criteria after' do
- subject { Developer.page(2).where(:salary => 1) }
- its(:selector) { should == {:salary => 1} }
- its(:current_page) { should == 2 }
- its(:limit_value) { should == 25 }
- its(:num_pages) { should == 12 }
- it { should skip 25 }
- end
- end
-
- describe '#per' do
- before do
- stub(subject).count { 300 } # in order to avoid DB access...
- end
-
- subject { Developer.page(2).per(10) }
- it { should be_a Mongoid::Criteria }
- its(:current_page) { should == 2 }
- its(:limit_value) { should == 10 }
- its(:num_pages) { should == 30 }
- it { should skip 10 }
- end
-
- describe '#page in embedded documents' do
- before :all do
- class MongoDeveloper
- include ::Mongoid::Document
- field :salary, :type => Integer
- embeds_many :frameworks
- end
-
- class Framework
- include ::Mongoid::Document
- field :name, :type => String
- field :language, :type => String
- embedded_in :mongo_developer
- end
- end
-
- before :all do
- @mongo_developer = MongoDeveloper.new
- @mongo_developer.frameworks.new(:name => "rails", :language => "ruby")
- @mongo_developer.frameworks.new(:name => "merb", :language => "ruby")
- @mongo_developer.frameworks.new(:name => "sinatra", :language => "ruby")
- @mongo_developer.frameworks.new(:name => "cakephp", :language => "php")
- @mongo_developer.frameworks.new(:name => "tornado", :language => "python")
- end
-
- context 'page 1' do
- subject { @mongo_developer.frameworks.page(1).per(1) }
- it { should be_a Mongoid::Criteria }
- its(:total_count) { should == 5 }
- its(:limit_value) { should == 1 }
- its(:current_page) { should == 1 }
- its(:num_pages) { should == 5 }
- end
-
- context 'with criteria after' do
- subject { @mongo_developer.frameworks.page(1).per(2).where(:language => "ruby") }
- it { should be_a Mongoid::Criteria }
- its(:total_count) { should == 3 }
- its(:limit_value) { should == 2 }
- its(:current_page) { should == 1 }
- its(:num_pages) { should == 2 }
- end
-
- context 'with criteria before' do
- subject { @mongo_developer.frameworks.where(:language => "ruby").page(1).per(2) }
- it { should be_a Mongoid::Criteria }
- its(:total_count) { should == 3 }
- its(:limit_value) { should == 2 }
- its(:current_page) { should == 1 }
- its(:num_pages) { should == 2 }
- end
- end
-end
diff --git a/spec/models/scopes_spec.rb b/spec/models/scopes_spec.rb
deleted file mode 100644
index a21df29..0000000
--- a/spec/models/scopes_spec.rb
+++ /dev/null
@@ -1,163 +0,0 @@
-require 'spec_helper'
-
-shared_examples_for 'the first page' do
- it { should have(25).users }
- its('first.name') { should == 'user001' }
-end
-
-shared_examples_for 'blank page' do
- it { should have(0).users }
-end
-
-describe Kaminari::ActiveRecordExtension do
- before :all do
- 1.upto(100) {|i| User.create! :name => "user#{'%03d' % i}", :age => (i / 10)}
- 1.upto(100) {|i| GemDefinedModel.create! :name => "user#{'%03d' % i}", :age => (i / 10)}
- end
-
- [User, Admin, GemDefinedModel].each do |model_class|
- context "for #{model_class}" do
- describe '#page' do
- context 'page 1' do
- subject { model_class.page 1 }
- it_should_behave_like 'the first page'
- end
-
- context 'page 2' do
- subject { model_class.page 2 }
- it { should have(25).users }
- its('first.name') { should == 'user026' }
- end
-
- context 'page without an argument' do
- subject { model_class.page }
- it_should_behave_like 'the first page'
- end
-
- context 'page < 1' do
- subject { model_class.page 0 }
- it_should_behave_like 'the first page'
- end
-
- context 'page > max page' do
- subject { model_class.page 5 }
- it_should_behave_like 'blank page'
- end
-
- describe 'ensure #order_values is preserved' do
- subject { model_class.order('id').page 1 }
- its('order_values.uniq') { should == ['id'] }
- end
- end
-
- describe '#per' do
- context 'page 1 per 5' do
- subject { model_class.page(1).per(5) }
- it { should have(5).users }
- its('first.name') { should == 'user001' }
- end
- end
-
- describe '#padding' do
- context 'page 1 per 5 padding 1' do
- subject { model_class.page(1).per(5).padding(1) }
- it { should have(5).users }
- its('first.name') { should == 'user002' }
- end
- end
-
- describe '#num_pages' do
- context 'per 25 (default)' do
- subject { model_class.page }
- its(:num_pages) { should == 4 }
- end
-
- context 'per 7' do
- subject { model_class.page(2).per(7) }
- its(:num_pages) { should == 15 }
- end
-
- context 'per 65536' do
- subject { model_class.page(50).per(65536) }
- its(:num_pages) { should == 1 }
- end
-
- context 'per 0 (using default)' do
- subject { model_class.page(50).per(0) }
- its(:num_pages) { should == 4 }
- end
-
- context 'per -1 (using default)' do
- subject { model_class.page(5).per(-1) }
- its(:num_pages) { should == 4 }
- end
-
- context 'per "String value that can not be converted into Number" (using default)' do
- subject { model_class.page(5).per('aho') }
- its(:num_pages) { should == 4 }
- end
- end
-
-
- describe '#current_page' do
- context 'page 1' do
- subject { model_class.page }
- its(:current_page) { should == 1 }
- end
-
- context 'page 2' do
- subject { model_class.page(2).per 3 }
- its(:current_page) { should == 2 }
- end
- end
-
- describe '#first_page?' do
- context 'on first page' do
- subject { model_class.page(1).per(10) }
- its(:first_page?) { should == true }
- end
-
- context 'not on first page' do
- subject { model_class.page(5).per(10) }
- its(:first_page?) { should == false }
- end
- end
-
- describe '#last_page?' do
- context 'on last page' do
- subject { model_class.page(10).per(10) }
- its(:last_page?) { should == true }
- end
-
- context 'not on last page' do
- subject { model_class.page(1).per(10) }
- its(:last_page?) { should == false }
- end
- end
-
- describe '#count' do
- context 'page 1' do
- subject { model_class.page }
- its(:count) { should == 25 }
- end
-
- context 'page 2' do
- subject { model_class.page 2 }
- its(:count) { should == 25 }
- end
- end
-
- context 'chained with .group' do
- subject { model_class.group('age').page(2).per 5 }
- # 0..10
- its(:total_count) { should == 11 }
- its(:num_pages) { should == 3 }
- end
-
- context 'activerecord descendants' do
- subject { ActiveRecord::Base.descendants }
- its(:length) { should_not == 0 }
- end
- end
- end
-end
diff --git a/spec/requests/users_spec.rb b/spec/requests/users_spec.rb
index 7480e6f..d80f71f 100644
--- a/spec/requests/users_spec.rb
+++ b/spec/requests/users_spec.rb
@@ -3,7 +3,6 @@ require 'spec_helper'
feature 'Users' do
background do
- User.delete_all
1.upto(100) {|i| User.create! :name => "user#{'%03d' % i}" }
end
scenario 'navigating by pagination links' do
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index a4c86b0..700b458 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -1,30 +1,34 @@
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
$LOAD_PATH.unshift(File.dirname(__FILE__))
-require 'rails'
-require 'mongoid'
-require 'dm-core'
-require 'kaminari'
+
+begin
+ require 'rails'
+rescue LoadError
+end
+
+require 'bundler/setup'
+Bundler.require
+
+require 'capybara/rspec'
require 'database_cleaner'
-# Ensure we use 'syck' instead of 'psych' in 1.9.2
-# RubyGems >= 1.5.0 uses 'psych' on 1.9.2, but
-# Psych does not yet support YAML 1.1 merge keys.
-# Merge keys is often used in mongoid.yml
-# See: http://redmine.ruby-lang.org/issues/show/4300
-if RUBY_VERSION >= '1.9.2'
- YAML::ENGINE.yamler = 'syck'
+
+# Simulate a gem providing a subclass of ActiveRecord::Base before the Railtie is loaded.
+require 'fake_gem' if defined? ActiveRecord
+
+if defined? Rails
+ require 'fake_app/rails_app'
+
+ require 'rspec/rails'
+end
+if defined? Sinatra
+ require 'spec_helper_for_sinatra'
end
-require 'fake_gem'
-require 'fake_app'
-require 'rspec/rails'
# Requires supporting files with custom matchers and macros, etc,
# in ./support/ and its subdirectories.
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
RSpec.configure do |config|
config.mock_with :rr
- config.before :all do
-# ActiveRecord::Base.connection.execute 'CREATE TABLE "users" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar(255))' unless ActiveRecord::Base.connection.table_exists? 'users'
- CreateAllTables.up unless ActiveRecord::Base.connection.table_exists? 'users'
- end
+ config.filter_run_excluding :generator_spec => true if !ENV['GENERATOR_SPEC']
end
diff --git a/spec/spec_helper_for_sinatra.rb b/spec/spec_helper_for_sinatra.rb
index 4a6ca92..9e44252 100644
--- a/spec/spec_helper_for_sinatra.rb
+++ b/spec/spec_helper_for_sinatra.rb
@@ -1,10 +1,31 @@
require 'kaminari/sinatra'
+require 'kaminari/helpers/action_view_extension'
require 'rack/test'
require 'sinatra/test_helpers'
+require 'capybara/rspec'
+
+require 'fake_app/sinatra_app'
+
+Capybara.app = SinatraApp
+
+module HelperMethodForHelperSpec
+ module FakeEnv
+ def env
+ {'PATH_INFO' => '/'}
+ end
+ end
+
+ def helper
+ # OMG terrible object...
+ ::Kaminari::Helpers::SinatraHelpers::ActionViewTemplateProxy.new(:current_params => {}, :current_path => '/', :param_name => Kaminari.config.param_name).extend(Padrino::Helpers, Kaminari::ActionViewExtension, Kaminari::Helpers::SinatraHelpers::HelperMethods, FakeEnv)
+ end
+end
RSpec.configure do |config|
config.include Rack::Test::Methods
config.include Sinatra::TestHelpers
+ config.include HelperMethodForHelperSpec
+# config.include HelperMethodForHelperSpec, :type => :helper
end
require 'nokogiri'
diff --git a/spec/support/database_cleaner.rb b/spec/support/database_cleaner.rb
index 9008744..05a5c13 100644
--- a/spec/support/database_cleaner.rb
+++ b/spec/support/database_cleaner.rb
@@ -1,8 +1,14 @@
-DatabaseCleaner.strategy = :transaction
+DatabaseCleaner[:active_record].strategy = :transaction if defined? ActiveRecord
+DatabaseCleaner[:data_mapper].strategy = :truncation if defined? DataMapper
+DatabaseCleaner[:mongoid].strategy = :truncation if defined? Mongoid
+DatabaseCleaner[:mongo_mapper].strategy = :truncation if defined? MongoMapper
RSpec.configure do |config|
config.before :suite do
- DatabaseCleaner.clean_with :truncation
+ DatabaseCleaner.clean_with :truncation if defined? ActiveRecord
+ DatabaseCleaner.clean_with :truncation if defined? DataMapper
+ DatabaseCleaner.clean_with :truncation if defined? Mongoid
+ DatabaseCleaner.clean_with :truncation if defined? MongoMapper
end
config.before :each do
DatabaseCleaner.start
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment