parlement 0.14 → 0.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (205) hide show
  1. data/CHANGES +41 -1
  2. data/MEMORY +66 -5
  3. data/README +10 -5
  4. data/Rakefile +15 -23
  5. data/app/controllers/account_controller.rb +48 -43
  6. data/app/controllers/{application.rb → application_controller.rb} +15 -12
  7. data/app/controllers/elt_controller.rb +77 -32
  8. data/app/controllers/subscriber_controller.rb +11 -10
  9. data/app/helpers/application_helper.rb +14 -1
  10. data/app/helpers/elt_helper.rb +9 -7
  11. data/app/models/elt.rb +25 -24
  12. data/app/models/mail.rb +44 -47
  13. data/app/models/person_notify.rb +2 -2
  14. data/app/models/user.rb +128 -2
  15. data/app/models/user_notify.rb +15 -15
  16. data/app/views/account/_login.rhtml +39 -39
  17. data/app/views/account/_show.rhtml +22 -30
  18. data/app/views/account/signup.rhtml +2 -2
  19. data/app/views/elt/_choice.rhtml +6 -6
  20. data/app/views/elt/_elt.rhtml +27 -32
  21. data/app/views/elt/choices.rhtml +16 -18
  22. data/app/views/elt/list/_byDate.rhtml +14 -14
  23. data/app/views/elt/list/_byVote.rhtml +15 -15
  24. data/app/views/elt/list/_children.rhtml +48 -40
  25. data/app/views/elt/list/_subscribers.rhtml +1 -1
  26. data/app/views/elt/new.rhtml +22 -21
  27. data/app/views/elt/rss.rxml +4 -11
  28. data/app/views/elt/show.rhtml +65 -61
  29. data/app/views/elt/vote_rss.rxml +4 -11
  30. data/app/views/layouts/top.rhtml +39 -50
  31. data/app/views/person/_listElts.rhtml +1 -1
  32. data/app/views/person/show.rhtml +1 -1
  33. data/{vendor/plugins/login_engine/app → app}/views/user_notify/change_password.rhtml +0 -0
  34. data/{vendor/plugins/login_engine/app → app}/views/user_notify/delete.rhtml +0 -0
  35. data/{vendor/plugins/login_engine/app → app}/views/user_notify/forgot_password.rhtml +0 -0
  36. data/{vendor/plugins/login_engine/app → app}/views/user_notify/pending_delete.rhtml +0 -0
  37. data/{vendor/plugins/login_engine/app → app}/views/user_notify/signup.rhtml +0 -0
  38. data/config/boot.rb +97 -32
  39. data/config/environment.rb +37 -35
  40. data/config/environments/development.rb +2 -3
  41. data/config/environments/production.rb +3 -0
  42. data/config/initializers/string_ruby_1.8.rb +10 -0
  43. data/config/routes.rb +17 -22
  44. data/db/schema.rb +102 -74
  45. data/lib/tasks/rspec.rake +167 -0
  46. data/public/404.html +25 -7
  47. data/public/500.html +26 -7
  48. data/public/dispatch.cgi +0 -0
  49. data/public/dispatch.fcgi +0 -0
  50. data/public/dispatch.rb +0 -0
  51. data/public/images/live_tree_branch_collapsed_icon.gif +0 -0
  52. data/public/images/live_tree_branch_expanded_icon.gif +0 -0
  53. data/public/images/live_tree_leaf_icon.gif +0 -0
  54. data/public/javascripts/application.js +258 -0
  55. data/public/javascripts/controls.js +544 -414
  56. data/public/javascripts/dragdrop.js +229 -198
  57. data/public/javascripts/effects.js +499 -459
  58. data/public/javascripts/prototype.js +2926 -1121
  59. data/public/javascripts/shadedborder.js +68 -50
  60. data/public/stylesheets/default.css +34 -34
  61. data/public/stylesheets/live_tree.css +0 -0
  62. data/public/stylesheets/scaffold.css +6 -6
  63. data/script/about +0 -0
  64. data/script/autospec +6 -0
  65. data/script/benchmarker +0 -0
  66. data/script/breakpointer +0 -0
  67. data/script/console +0 -0
  68. data/script/dbconsole +3 -0
  69. data/script/destroy +0 -0
  70. data/script/generate +0 -0
  71. data/script/plugin +0 -0
  72. data/script/profiler +0 -0
  73. data/script/runner +0 -0
  74. data/script/server +0 -0
  75. data/script/spec +10 -0
  76. data/script/spec_server +9 -0
  77. data/test/unit/attachment_test.rb +4 -4
  78. data/test/unit/choice_test.rb +1 -1
  79. data/test/unit/elt_test.rb +9 -9
  80. data/test/unit/mail_notify_test.rb +2 -2
  81. data/test/unit/mail_test.rb +18 -11
  82. data/test/unit/person_notify_test.rb +1 -1
  83. data/test/unit/person_test.rb +1 -1
  84. data/test/unit/subscriber_test.rb +1 -1
  85. data/test/unit/user_test.rb +81 -0
  86. data/test/unit/visit_test.rb +6 -6
  87. data/vendor/plugins/activerecord_foreign_key_extensions/init.rb +2 -0
  88. data/vendor/plugins/activerecord_foreign_key_extensions/lib/active_record_extensions.rb +182 -0
  89. data/vendor/plugins/activerecord_text_id_extensions/init.rb +2 -0
  90. data/vendor/plugins/activerecord_text_id_extensions/lib/active_record_extensions.rb +24 -0
  91. data/vendor/plugins/acts_as_nested_set/README +15 -0
  92. data/vendor/plugins/acts_as_nested_set/init.rb +1 -0
  93. data/vendor/plugins/acts_as_nested_set/lib/active_record/acts/nested_set.rb +210 -0
  94. data/vendor/plugins/acts_as_nested_set/test/nested_set_test.rb +269 -0
  95. data/vendor/plugins/acts_as_tree/README +26 -0
  96. data/vendor/plugins/acts_as_tree/Rakefile +22 -0
  97. data/vendor/plugins/acts_as_tree/init.rb +1 -0
  98. data/vendor/plugins/acts_as_tree/lib/active_record/acts/tree.rb +96 -0
  99. data/vendor/plugins/{output_compression/CHANGELOG → acts_as_tree/test/abstract_unit.rb} +0 -0
  100. data/vendor/plugins/acts_as_tree/test/acts_as_tree_test.rb +219 -0
  101. data/vendor/plugins/acts_as_tree/test/database.yml +0 -0
  102. data/vendor/plugins/acts_as_tree/test/fixtures/mixin.rb +0 -0
  103. data/vendor/plugins/acts_as_tree/test/fixtures/mixins.yml +0 -0
  104. data/vendor/plugins/acts_as_tree/test/schema.rb +0 -0
  105. data/vendor/plugins/classic_pagination/CHANGELOG +152 -0
  106. data/vendor/plugins/classic_pagination/README +18 -0
  107. data/vendor/plugins/{output_compression/rakefile → classic_pagination/Rakefile} +22 -22
  108. data/vendor/plugins/classic_pagination/init.rb +33 -0
  109. data/vendor/plugins/classic_pagination/install.rb +1 -0
  110. data/vendor/plugins/classic_pagination/lib/pagination.rb +405 -0
  111. data/vendor/plugins/classic_pagination/lib/pagination_helper.rb +135 -0
  112. data/vendor/plugins/classic_pagination/test/fixtures/companies.yml +24 -0
  113. data/vendor/plugins/classic_pagination/test/fixtures/company.rb +9 -0
  114. data/vendor/plugins/classic_pagination/test/fixtures/developer.rb +7 -0
  115. data/vendor/plugins/classic_pagination/test/fixtures/developers.yml +21 -0
  116. data/vendor/plugins/classic_pagination/test/fixtures/developers_projects.yml +13 -0
  117. data/vendor/plugins/classic_pagination/test/fixtures/project.rb +3 -0
  118. data/vendor/plugins/classic_pagination/test/fixtures/projects.yml +7 -0
  119. data/vendor/plugins/classic_pagination/test/fixtures/replies.yml +13 -0
  120. data/vendor/plugins/classic_pagination/test/fixtures/reply.rb +5 -0
  121. data/vendor/plugins/classic_pagination/test/fixtures/schema.sql +42 -0
  122. data/vendor/plugins/classic_pagination/test/fixtures/topic.rb +3 -0
  123. data/vendor/plugins/classic_pagination/test/fixtures/topics.yml +22 -0
  124. data/vendor/plugins/classic_pagination/test/helper.rb +117 -0
  125. data/vendor/plugins/classic_pagination/test/pagination_helper_test.rb +38 -0
  126. data/vendor/plugins/classic_pagination/test/pagination_test.rb +177 -0
  127. data/vendor/plugins/file_column/lib/file_column.rb +1 -1
  128. data/vendor/plugins/file_column/test/file_column_test.rb +0 -0
  129. metadata +151 -197
  130. data/app/helpers/live_tree.rb +0 -238
  131. data/app/views/elt/_form.rhtml +0 -31
  132. data/app/views/elt/show_tree.rhtml +0 -8
  133. data/config/environments/user_environment.rb +0 -1
  134. data/db/ROOT/Titemagli.txt +0 -3
  135. data/db/ROOT/titemagli.txt +0 -9
  136. data/public/javascripts/behaviour.js +0 -254
  137. data/public/javascripts/ie7-load.htc +0 -1
  138. data/public/javascripts/ie7.js +0 -6
  139. data/public/javascripts/live_tree.js +0 -749
  140. data/public/javascripts/mybehaviour.js +0 -225
  141. data/public/javascripts/scriptaculous.js +0 -47
  142. data/public/javascripts/slider.js +0 -283
  143. data/public/stylesheets/blue.css +0 -471
  144. data/vendor/plugins/engines/CHANGELOG +0 -241
  145. data/vendor/plugins/engines/MIT-LICENSE +0 -21
  146. data/vendor/plugins/engines/README +0 -64
  147. data/vendor/plugins/engines/Rakefile +0 -32
  148. data/vendor/plugins/engines/UPGRADING +0 -93
  149. data/vendor/plugins/engines/about.yml +0 -7
  150. data/vendor/plugins/engines/generators/plugin_migration/USAGE +0 -45
  151. data/vendor/plugins/engines/generators/plugin_migration/plugin_migration_generator.rb +0 -79
  152. data/vendor/plugins/engines/generators/plugin_migration/templates/plugin_migration.erb +0 -13
  153. data/vendor/plugins/engines/init.rb +0 -40
  154. data/vendor/plugins/engines/install.rb +0 -32
  155. data/vendor/plugins/engines/lib/engines.rb +0 -323
  156. data/vendor/plugins/engines/lib/engines/deprecated_config_support.rb +0 -135
  157. data/vendor/plugins/engines/lib/engines/plugin.rb +0 -214
  158. data/vendor/plugins/engines/lib/engines/plugin_list.rb +0 -31
  159. data/vendor/plugins/engines/lib/engines/plugin_migrator.rb +0 -60
  160. data/vendor/plugins/engines/lib/engines/rails_extensions.rb +0 -6
  161. data/vendor/plugins/engines/lib/engines/rails_extensions/active_record.rb +0 -19
  162. data/vendor/plugins/engines/lib/engines/rails_extensions/dependencies.rb +0 -143
  163. data/vendor/plugins/engines/lib/engines/rails_extensions/migrations.rb +0 -155
  164. data/vendor/plugins/engines/lib/engines/rails_extensions/public_asset_helpers.rb +0 -116
  165. data/vendor/plugins/engines/lib/engines/rails_extensions/rails.rb +0 -20
  166. data/vendor/plugins/engines/lib/engines/rails_extensions/rails_initializer.rb +0 -86
  167. data/vendor/plugins/engines/lib/engines/rails_extensions/routing.rb +0 -77
  168. data/vendor/plugins/engines/lib/engines/rails_extensions/templates.rb +0 -140
  169. data/vendor/plugins/engines/lib/engines/testing.rb +0 -87
  170. data/vendor/plugins/engines/tasks/engines.rake +0 -149
  171. data/vendor/plugins/login_engine/CHANGELOG +0 -22
  172. data/vendor/plugins/login_engine/README +0 -344
  173. data/vendor/plugins/login_engine/app/controllers/user_controller.rb +0 -262
  174. data/vendor/plugins/login_engine/app/helpers/user_helper.rb +0 -88
  175. data/vendor/plugins/login_engine/app/models/user.rb +0 -7
  176. data/vendor/plugins/login_engine/app/models/user_notify.rb +0 -75
  177. data/vendor/plugins/login_engine/app/views/user/_edit.rhtml +0 -11
  178. data/vendor/plugins/login_engine/app/views/user/_password.rhtml +0 -9
  179. data/vendor/plugins/login_engine/app/views/user/change_password.rhtml +0 -17
  180. data/vendor/plugins/login_engine/app/views/user/edit.rhtml +0 -23
  181. data/vendor/plugins/login_engine/app/views/user/forgot_password.rhtml +0 -18
  182. data/vendor/plugins/login_engine/app/views/user/home.rhtml +0 -7
  183. data/vendor/plugins/login_engine/app/views/user/login.rhtml +0 -17
  184. data/vendor/plugins/login_engine/app/views/user/logout.rhtml +0 -8
  185. data/vendor/plugins/login_engine/app/views/user/signup.rhtml +0 -17
  186. data/vendor/plugins/login_engine/db/migrate/001_initial_schema.rb +0 -25
  187. data/vendor/plugins/login_engine/init_engine.rb +0 -11
  188. data/vendor/plugins/login_engine/install.rb +0 -4
  189. data/vendor/plugins/login_engine/lib/login_engine.rb +0 -62
  190. data/vendor/plugins/login_engine/lib/login_engine/authenticated_system.rb +0 -113
  191. data/vendor/plugins/login_engine/lib/login_engine/authenticated_user.rb +0 -155
  192. data/vendor/plugins/login_engine/public/stylesheets/login_engine.css +0 -81
  193. data/vendor/plugins/login_engine/test/fixtures/users.yml +0 -41
  194. data/vendor/plugins/login_engine/test/functional/user_controller_test.rb +0 -536
  195. data/vendor/plugins/login_engine/test/mocks/mail.rb +0 -14
  196. data/vendor/plugins/login_engine/test/mocks/time.rb +0 -19
  197. data/vendor/plugins/login_engine/test/test_helper.rb +0 -11
  198. data/vendor/plugins/login_engine/test/unit/user_test.rb +0 -114
  199. data/vendor/plugins/output_compression/MIT-LICENSE +0 -20
  200. data/vendor/plugins/output_compression/README +0 -4
  201. data/vendor/plugins/output_compression/init.rb +0 -1
  202. data/vendor/plugins/output_compression/lib/output_compression.rb +0 -84
  203. data/vendor/plugins/output_compression/test/output_test.rb +0 -11
  204. data/vendor/plugins/output_compression/test/test_controller.rb +0 -3
  205. data/vendor/plugins/output_compression/test/test_helper.rb +0 -14
@@ -0,0 +1,18 @@
1
+ Pagination
2
+ ==========
3
+
4
+ To install:
5
+
6
+ script/plugin install svn://errtheblog.com/svn/plugins/classic_pagination
7
+
8
+ This code was extracted from Rails trunk after the release 1.2.3.
9
+ WARNING: this code is dead. It is unmaintained, untested and full of cruft.
10
+
11
+ There is a much better pagination plugin called will_paginate.
12
+ Install it like this and glance through the README:
13
+
14
+ script/plugin install svn://errtheblog.com/svn/plugins/will_paginate
15
+
16
+ It doesn't have the same API, but is in fact much nicer. You can
17
+ have both plugins installed until you change your controller/view code that
18
+ handles pagination. Then, simply uninstall classic_pagination.
@@ -1,22 +1,22 @@
1
- require 'rake'
2
- require 'rake/testtask'
3
- require 'rake/rdoctask'
4
-
5
- desc 'Default: run unit tests.'
6
- task :default => :test
7
-
8
- desc 'Test the Output Compression plugin.'
9
- Rake::TestTask.new(:test) do |t|
10
- t.libs << 'lib'
11
- t.pattern = 'test/**/*_test.rb'
12
- t.verbose = true
13
- end
14
-
15
- desc 'Generate documentation for the Output Compression plugin.'
16
- Rake::RDocTask.new(:rdoc) do |rdoc|
17
- rdoc.rdoc_dir = 'rdoc'
18
- rdoc.title = 'Output Compression'
19
- rdoc.options << '--line-numbers --inline-source'
20
- rdoc.rdoc_files.include('README')
21
- rdoc.rdoc_files.include('lib/**/*.rb')
22
- end
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ desc 'Test the classic_pagination plugin.'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.pattern = 'test/**/*_test.rb'
12
+ t.verbose = true
13
+ end
14
+
15
+ desc 'Generate documentation for the classic_pagination plugin.'
16
+ Rake::RDocTask.new(:rdoc) do |rdoc|
17
+ rdoc.rdoc_dir = 'rdoc'
18
+ rdoc.title = 'Pagination'
19
+ rdoc.options << '--line-numbers' << '--inline-source'
20
+ rdoc.rdoc_files.include('README')
21
+ rdoc.rdoc_files.include('lib/**/*.rb')
22
+ end
@@ -0,0 +1,33 @@
1
+ #--
2
+ # Copyright (c) 2004-2006 David Heinemeier Hansson
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ require 'pagination'
25
+ require 'pagination_helper'
26
+
27
+ ActionController::Base.class_eval do
28
+ include ActionController::Pagination
29
+ end
30
+
31
+ ActionView::Base.class_eval do
32
+ include ActionView::Helpers::PaginationHelper
33
+ end
@@ -0,0 +1 @@
1
+ puts "\n\n" + File.read(File.dirname(__FILE__) + '/README')
@@ -0,0 +1,405 @@
1
+ module ActionController
2
+ # === Action Pack pagination for Active Record collections
3
+ #
4
+ # The Pagination module aids in the process of paging large collections of
5
+ # Active Record objects. It offers macro-style automatic fetching of your
6
+ # model for multiple views, or explicit fetching for single actions. And if
7
+ # the magic isn't flexible enough for your needs, you can create your own
8
+ # paginators with a minimal amount of code.
9
+ #
10
+ # The Pagination module can handle as much or as little as you wish. In the
11
+ # controller, have it automatically query your model for pagination; or,
12
+ # if you prefer, create Paginator objects yourself.
13
+ #
14
+ # Pagination is included automatically for all controllers.
15
+ #
16
+ # For help rendering pagination links, see
17
+ # ActionView::Helpers::PaginationHelper.
18
+ #
19
+ # ==== Automatic pagination for every action in a controller
20
+ #
21
+ # class PersonController < ApplicationController
22
+ # model :person
23
+ #
24
+ # paginate :people, :order => 'last_name, first_name',
25
+ # :per_page => 20
26
+ #
27
+ # # ...
28
+ # end
29
+ #
30
+ # Each action in this controller now has access to a <tt>@people</tt>
31
+ # instance variable, which is an ordered collection of model objects for the
32
+ # current page (at most 20, sorted by last name and first name), and a
33
+ # <tt>@person_pages</tt> Paginator instance. The current page is determined
34
+ # by the <tt>params[:page]</tt> variable.
35
+ #
36
+ # ==== Pagination for a single action
37
+ #
38
+ # def list
39
+ # @person_pages, @people =
40
+ # paginate :people, :order => 'last_name, first_name'
41
+ # end
42
+ #
43
+ # Like the previous example, but explicitly creates <tt>@person_pages</tt>
44
+ # and <tt>@people</tt> for a single action, and uses the default of 10 items
45
+ # per page.
46
+ #
47
+ # ==== Custom/"classic" pagination
48
+ #
49
+ # def list
50
+ # @person_pages = Paginator.new self, Person.count, 10, params[:page]
51
+ # @people = Person.find :all, :order => 'last_name, first_name',
52
+ # :limit => @person_pages.items_per_page,
53
+ # :offset => @person_pages.current.offset
54
+ # end
55
+ #
56
+ # Explicitly creates the paginator from the previous example and uses
57
+ # Paginator#to_sql to retrieve <tt>@people</tt> from the model.
58
+ #
59
+ module Pagination
60
+ unless const_defined?(:OPTIONS)
61
+ # A hash holding options for controllers using macro-style pagination
62
+ OPTIONS = Hash.new
63
+
64
+ # The default options for pagination
65
+ DEFAULT_OPTIONS = {
66
+ :class_name => nil,
67
+ :singular_name => nil,
68
+ :per_page => 10,
69
+ :conditions => nil,
70
+ :order_by => nil,
71
+ :order => nil,
72
+ :join => nil,
73
+ :joins => nil,
74
+ :count => nil,
75
+ :include => nil,
76
+ :select => nil,
77
+ :group => nil,
78
+ :parameter => 'page'
79
+ }
80
+ else
81
+ DEFAULT_OPTIONS[:group] = nil
82
+ end
83
+
84
+ def self.included(base) #:nodoc:
85
+ super
86
+ base.extend(ClassMethods)
87
+ end
88
+
89
+ def self.validate_options!(collection_id, options, in_action) #:nodoc:
90
+ options.merge!(DEFAULT_OPTIONS) {|key, old, new| old}
91
+
92
+ valid_options = DEFAULT_OPTIONS.keys
93
+ valid_options << :actions unless in_action
94
+
95
+ unknown_option_keys = options.keys - valid_options
96
+ raise ActionController::ActionControllerError,
97
+ "Unknown options: #{unknown_option_keys.join(', ')}" unless
98
+ unknown_option_keys.empty?
99
+
100
+ options[:singular_name] ||= Inflector.singularize(collection_id.to_s)
101
+ options[:class_name] ||= Inflector.camelize(options[:singular_name])
102
+ end
103
+
104
+ # Returns a paginator and a collection of Active Record model instances
105
+ # for the paginator's current page. This is designed to be used in a
106
+ # single action; to automatically paginate multiple actions, consider
107
+ # ClassMethods#paginate.
108
+ #
109
+ # +options+ are:
110
+ # <tt>:singular_name</tt>:: the singular name to use, if it can't be inferred by singularizing the collection name
111
+ # <tt>:class_name</tt>:: the class name to use, if it can't be inferred by
112
+ # camelizing the singular name
113
+ # <tt>:per_page</tt>:: the maximum number of items to include in a
114
+ # single page. Defaults to 10
115
+ # <tt>:conditions</tt>:: optional conditions passed to Model.find(:all, *params) and
116
+ # Model.count
117
+ # <tt>:order</tt>:: optional order parameter passed to Model.find(:all, *params)
118
+ # <tt>:order_by</tt>:: (deprecated, used :order) optional order parameter passed to Model.find(:all, *params)
119
+ # <tt>:joins</tt>:: optional joins parameter passed to Model.find(:all, *params)
120
+ # and Model.count
121
+ # <tt>:join</tt>:: (deprecated, used :joins or :include) optional join parameter passed to Model.find(:all, *params)
122
+ # and Model.count
123
+ # <tt>:include</tt>:: optional eager loading parameter passed to Model.find(:all, *params)
124
+ # and Model.count
125
+ # <tt>:select</tt>:: :select parameter passed to Model.find(:all, *params)
126
+ #
127
+ # <tt>:count</tt>:: parameter passed as :select option to Model.count(*params)
128
+ #
129
+ # <tt>:group</tt>:: :group parameter passed to Model.find(:all, *params). It forces the use of DISTINCT instead of plain COUNT to come up with the total number of records
130
+ #
131
+ def paginate(collection_id, options={})
132
+ Pagination.validate_options!(collection_id, options, true)
133
+ paginator_and_collection_for(collection_id, options)
134
+ end
135
+
136
+ # These methods become class methods on any controller
137
+ module ClassMethods
138
+ # Creates a +before_filter+ which automatically paginates an Active
139
+ # Record model for all actions in a controller (or certain actions if
140
+ # specified with the <tt>:actions</tt> option).
141
+ #
142
+ # +options+ are the same as PaginationHelper#paginate, with the addition
143
+ # of:
144
+ # <tt>:actions</tt>:: an array of actions for which the pagination is
145
+ # active. Defaults to +nil+ (i.e., every action)
146
+ def paginate(collection_id, options={})
147
+ Pagination.validate_options!(collection_id, options, false)
148
+ module_eval do
149
+ before_filter :create_paginators_and_retrieve_collections
150
+ OPTIONS[self] ||= Hash.new
151
+ OPTIONS[self][collection_id] = options
152
+ end
153
+ end
154
+ end
155
+
156
+ def create_paginators_and_retrieve_collections #:nodoc:
157
+ Pagination::OPTIONS[self.class].each do |collection_id, options|
158
+ next unless options[:actions].include? action_name if
159
+ options[:actions]
160
+
161
+ paginator, collection =
162
+ paginator_and_collection_for(collection_id, options)
163
+
164
+ paginator_name = "@#{options[:singular_name]}_pages"
165
+ self.instance_variable_set(paginator_name, paginator)
166
+
167
+ collection_name = "@#{collection_id.to_s}"
168
+ self.instance_variable_set(collection_name, collection)
169
+ end
170
+ end
171
+
172
+ # Returns the total number of items in the collection to be paginated for
173
+ # the +model+ and given +conditions+. Override this method to implement a
174
+ # custom counter.
175
+ def count_collection_for_pagination(model, options)
176
+ model.count(:conditions => options[:conditions],
177
+ :joins => options[:join] || options[:joins],
178
+ :include => options[:include],
179
+ :select => (options[:group] ? "DISTINCT #{options[:group]}" : options[:count]))
180
+ end
181
+
182
+ # Returns a collection of items for the given +model+ and +options[conditions]+,
183
+ # ordered by +options[order]+, for the current page in the given +paginator+.
184
+ # Override this method to implement a custom finder.
185
+ def find_collection_for_pagination(model, options, paginator)
186
+ model.find(:all, :conditions => options[:conditions],
187
+ :order => options[:order_by] || options[:order],
188
+ :joins => options[:join] || options[:joins], :include => options[:include],
189
+ :select => options[:select], :limit => options[:per_page],
190
+ :group => options[:group], :offset => paginator.current.offset)
191
+ end
192
+
193
+ protected :create_paginators_and_retrieve_collections,
194
+ :count_collection_for_pagination,
195
+ :find_collection_for_pagination
196
+
197
+ def paginator_and_collection_for(collection_id, options) #:nodoc:
198
+ klass = options[:class_name].constantize
199
+ page = params[options[:parameter]]
200
+ count = count_collection_for_pagination(klass, options)
201
+ paginator = Paginator.new(self, count, options[:per_page], page)
202
+ collection = find_collection_for_pagination(klass, options, paginator)
203
+
204
+ return paginator, collection
205
+ end
206
+
207
+ private :paginator_and_collection_for
208
+
209
+ # A class representing a paginator for an Active Record collection.
210
+ class Paginator
211
+ include Enumerable
212
+
213
+ # Creates a new Paginator on the given +controller+ for a set of items
214
+ # of size +item_count+ and having +items_per_page+ items per page.
215
+ # Raises ArgumentError if items_per_page is out of bounds (i.e., less
216
+ # than or equal to zero). The page CGI parameter for links defaults to
217
+ # "page" and can be overridden with +page_parameter+.
218
+ def initialize(controller, item_count, items_per_page, current_page=1)
219
+ raise ArgumentError, 'must have at least one item per page' if
220
+ items_per_page <= 0
221
+
222
+ @controller = controller
223
+ @item_count = item_count || 0
224
+ @items_per_page = items_per_page
225
+ @pages = {}
226
+
227
+ self.current_page = current_page
228
+ end
229
+ attr_reader :controller, :item_count, :items_per_page
230
+
231
+ # Sets the current page number of this paginator. If +page+ is a Page
232
+ # object, its +number+ attribute is used as the value; if the page does
233
+ # not belong to this Paginator, an ArgumentError is raised.
234
+ def current_page=(page)
235
+ if page.is_a? Page
236
+ raise ArgumentError, 'Page/Paginator mismatch' unless
237
+ page.paginator == self
238
+ end
239
+ page = page.to_i
240
+ @current_page_number = has_page_number?(page) ? page : 1
241
+ end
242
+
243
+ # Returns a Page object representing this paginator's current page.
244
+ def current_page
245
+ @current_page ||= self[@current_page_number]
246
+ end
247
+ alias current :current_page
248
+
249
+ # Returns a new Page representing the first page in this paginator.
250
+ def first_page
251
+ @first_page ||= self[1]
252
+ end
253
+ alias first :first_page
254
+
255
+ # Returns a new Page representing the last page in this paginator.
256
+ def last_page
257
+ @last_page ||= self[page_count]
258
+ end
259
+ alias last :last_page
260
+
261
+ # Returns the number of pages in this paginator.
262
+ def page_count
263
+ @page_count ||= @item_count.zero? ? 1 :
264
+ (q,r=@item_count.divmod(@items_per_page); r==0? q : q+1)
265
+ end
266
+
267
+ alias length :page_count
268
+
269
+ # Returns true if this paginator contains the page of index +number+.
270
+ def has_page_number?(number)
271
+ number >= 1 and number <= page_count
272
+ end
273
+
274
+ # Returns a new Page representing the page with the given index
275
+ # +number+.
276
+ def [](number)
277
+ @pages[number] ||= Page.new(self, number)
278
+ end
279
+
280
+ # Successively yields all the paginator's pages to the given block.
281
+ def each(&block)
282
+ page_count.times do |n|
283
+ yield self[n+1]
284
+ end
285
+ end
286
+
287
+ # A class representing a single page in a paginator.
288
+ class Page
289
+ include Comparable
290
+
291
+ # Creates a new Page for the given +paginator+ with the index
292
+ # +number+. If +number+ is not in the range of valid page numbers or
293
+ # is not a number at all, it defaults to 1.
294
+ def initialize(paginator, number)
295
+ @paginator = paginator
296
+ @number = number.to_i
297
+ @number = 1 unless @paginator.has_page_number? @number
298
+ end
299
+ attr_reader :paginator, :number
300
+ alias to_i :number
301
+
302
+ # Compares two Page objects and returns true when they represent the
303
+ # same page (i.e., their paginators are the same and they have the
304
+ # same page number).
305
+ def ==(page)
306
+ return false if page.nil?
307
+ @paginator == page.paginator and
308
+ @number == page.number
309
+ end
310
+
311
+ # Compares two Page objects and returns -1 if the left-hand page comes
312
+ # before the right-hand page, 0 if the pages are equal, and 1 if the
313
+ # left-hand page comes after the right-hand page. Raises ArgumentError
314
+ # if the pages do not belong to the same Paginator object.
315
+ def <=>(page)
316
+ raise ArgumentError unless @paginator == page.paginator
317
+ @number <=> page.number
318
+ end
319
+
320
+ # Returns the item offset for the first item in this page.
321
+ def offset
322
+ @paginator.items_per_page * (@number - 1)
323
+ end
324
+
325
+ # Returns the number of the first item displayed.
326
+ def first_item
327
+ offset + 1
328
+ end
329
+
330
+ # Returns the number of the last item displayed.
331
+ def last_item
332
+ [@paginator.items_per_page * @number, @paginator.item_count].min
333
+ end
334
+
335
+ # Returns true if this page is the first page in the paginator.
336
+ def first?
337
+ self == @paginator.first
338
+ end
339
+
340
+ # Returns true if this page is the last page in the paginator.
341
+ def last?
342
+ self == @paginator.last
343
+ end
344
+
345
+ # Returns a new Page object representing the page just before this
346
+ # page, or nil if this is the first page.
347
+ def previous
348
+ if first? then nil else @paginator[@number - 1] end
349
+ end
350
+
351
+ # Returns a new Page object representing the page just after this
352
+ # page, or nil if this is the last page.
353
+ def next
354
+ if last? then nil else @paginator[@number + 1] end
355
+ end
356
+
357
+ # Returns a new Window object for this page with the specified
358
+ # +padding+.
359
+ def window(padding=2)
360
+ Window.new(self, padding)
361
+ end
362
+
363
+ # Returns the limit/offset array for this page.
364
+ def to_sql
365
+ [@paginator.items_per_page, offset]
366
+ end
367
+
368
+ def to_param #:nodoc:
369
+ @number.to_s
370
+ end
371
+ end
372
+
373
+ # A class for representing ranges around a given page.
374
+ class Window
375
+ # Creates a new Window object for the given +page+ with the specified
376
+ # +padding+.
377
+ def initialize(page, padding=2)
378
+ @paginator = page.paginator
379
+ @page = page
380
+ self.padding = padding
381
+ end
382
+ attr_reader :paginator, :page
383
+
384
+ # Sets the window's padding (the number of pages on either side of the
385
+ # window page).
386
+ def padding=(padding)
387
+ @padding = padding < 0 ? 0 : padding
388
+ # Find the beginning and end pages of the window
389
+ @first = @paginator.has_page_number?(@page.number - @padding) ?
390
+ @paginator[@page.number - @padding] : @paginator.first
391
+ @last = @paginator.has_page_number?(@page.number + @padding) ?
392
+ @paginator[@page.number + @padding] : @paginator.last
393
+ end
394
+ attr_reader :padding, :first, :last
395
+
396
+ # Returns an array of Page objects in the current window.
397
+ def pages
398
+ (@first.number..@last.number).to_a.collect! {|n| @paginator[n]}
399
+ end
400
+ alias to_a :pages
401
+ end
402
+ end
403
+
404
+ end
405
+ end