Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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)