actionpack 1.13.6 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

Files changed (317) hide show
  1. data/CHANGELOG +1400 -20
  2. data/MIT-LICENSE +1 -1
  3. data/README +5 -5
  4. data/RUNNING_UNIT_TESTS +4 -5
  5. data/Rakefile +5 -6
  6. data/install.rb +2 -2
  7. data/lib/action_controller.rb +11 -15
  8. data/lib/action_controller/assertions.rb +12 -25
  9. data/lib/action_controller/assertions/dom_assertions.rb +18 -4
  10. data/lib/action_controller/assertions/model_assertions.rb +8 -1
  11. data/lib/action_controller/assertions/response_assertions.rb +35 -12
  12. data/lib/action_controller/assertions/routing_assertions.rb +56 -12
  13. data/lib/action_controller/assertions/selector_assertions.rb +105 -38
  14. data/lib/action_controller/assertions/tag_assertions.rb +28 -15
  15. data/lib/action_controller/base.rb +318 -250
  16. data/lib/action_controller/benchmarking.rb +33 -29
  17. data/lib/action_controller/caching.rb +130 -64
  18. data/lib/action_controller/cgi_ext.rb +16 -0
  19. data/lib/action_controller/cgi_ext/{cookie_performance_fix.rb → cookie.rb} +25 -40
  20. data/lib/action_controller/cgi_ext/query_extension.rb +22 -0
  21. data/lib/action_controller/cgi_ext/session.rb +73 -0
  22. data/lib/action_controller/cgi_ext/stdinput.rb +23 -0
  23. data/lib/action_controller/cgi_process.rb +34 -57
  24. data/lib/action_controller/components.rb +19 -36
  25. data/lib/action_controller/cookies.rb +10 -9
  26. data/lib/action_controller/dispatcher.rb +195 -0
  27. data/lib/action_controller/filters.rb +35 -34
  28. data/lib/action_controller/flash.rb +30 -35
  29. data/lib/action_controller/helpers.rb +121 -47
  30. data/lib/action_controller/http_authentication.rb +126 -0
  31. data/lib/action_controller/integration.rb +105 -101
  32. data/lib/action_controller/layout.rb +59 -47
  33. data/lib/action_controller/mime_responds.rb +57 -68
  34. data/lib/action_controller/mime_type.rb +43 -80
  35. data/lib/action_controller/mime_types.rb +20 -0
  36. data/lib/action_controller/polymorphic_routes.rb +88 -0
  37. data/lib/action_controller/record_identifier.rb +91 -0
  38. data/lib/action_controller/request.rb +553 -88
  39. data/lib/action_controller/request_forgery_protection.rb +126 -0
  40. data/lib/action_controller/request_profiler.rb +138 -0
  41. data/lib/action_controller/rescue.rb +185 -69
  42. data/lib/action_controller/resources.rb +211 -172
  43. data/lib/action_controller/response.rb +49 -8
  44. data/lib/action_controller/routing.rb +359 -236
  45. data/lib/action_controller/routing_optimisation.rb +119 -0
  46. data/lib/action_controller/session/active_record_store.rb +3 -2
  47. data/lib/action_controller/session/cookie_store.rb +161 -0
  48. data/lib/action_controller/session/mem_cache_store.rb +9 -16
  49. data/lib/action_controller/session_management.rb +17 -8
  50. data/lib/action_controller/streaming.rb +6 -3
  51. data/lib/action_controller/templates/rescues/_request_and_response.erb +24 -0
  52. data/lib/action_controller/templates/rescues/{_trace.rhtml → _trace.erb} +0 -0
  53. data/lib/action_controller/templates/rescues/{diagnostics.rhtml → diagnostics.erb} +2 -2
  54. data/lib/action_controller/templates/rescues/{layout.rhtml → layout.erb} +0 -0
  55. data/lib/action_controller/templates/rescues/{missing_template.rhtml → missing_template.erb} +0 -0
  56. data/lib/action_controller/templates/rescues/{routing_error.rhtml → routing_error.erb} +0 -0
  57. data/lib/action_controller/templates/rescues/{template_error.rhtml → template_error.erb} +2 -2
  58. data/lib/action_controller/templates/rescues/{unknown_action.rhtml → unknown_action.erb} +0 -0
  59. data/lib/action_controller/test_case.rb +53 -0
  60. data/lib/action_controller/test_process.rb +59 -46
  61. data/lib/action_controller/url_rewriter.rb +48 -24
  62. data/lib/action_controller/vendor/html-scanner/html/document.rb +7 -4
  63. data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +173 -0
  64. data/lib/action_controller/vendor/html-scanner/html/selector.rb +11 -6
  65. data/lib/action_controller/verification.rb +27 -21
  66. data/lib/action_pack.rb +1 -1
  67. data/lib/action_pack/version.rb +4 -4
  68. data/lib/action_view.rb +2 -3
  69. data/lib/action_view/base.rb +218 -63
  70. data/lib/action_view/compiled_templates.rb +1 -2
  71. data/lib/action_view/helpers/active_record_helper.rb +35 -17
  72. data/lib/action_view/helpers/asset_tag_helper.rb +395 -87
  73. data/lib/action_view/helpers/atom_feed_helper.rb +111 -0
  74. data/lib/action_view/helpers/benchmark_helper.rb +12 -5
  75. data/lib/action_view/helpers/cache_helper.rb +29 -0
  76. data/lib/action_view/helpers/capture_helper.rb +97 -63
  77. data/lib/action_view/helpers/date_helper.rb +295 -35
  78. data/lib/action_view/helpers/debug_helper.rb +6 -2
  79. data/lib/action_view/helpers/form_helper.rb +354 -111
  80. data/lib/action_view/helpers/form_options_helper.rb +171 -109
  81. data/lib/action_view/helpers/form_tag_helper.rb +332 -76
  82. data/lib/action_view/helpers/javascript_helper.rb +35 -11
  83. data/lib/action_view/helpers/javascripts/controls.js +484 -354
  84. data/lib/action_view/helpers/javascripts/dragdrop.js +88 -58
  85. data/lib/action_view/helpers/javascripts/effects.js +396 -364
  86. data/lib/action_view/helpers/javascripts/prototype.js +2817 -1107
  87. data/lib/action_view/helpers/number_helper.rb +84 -60
  88. data/lib/action_view/helpers/prototype_helper.rb +419 -43
  89. data/lib/action_view/helpers/record_identification_helper.rb +20 -0
  90. data/lib/action_view/helpers/record_tag_helper.rb +59 -0
  91. data/lib/action_view/helpers/sanitize_helper.rb +223 -0
  92. data/lib/action_view/helpers/scriptaculous_helper.rb +63 -4
  93. data/lib/action_view/helpers/tag_helper.rb +69 -39
  94. data/lib/action_view/helpers/text_helper.rb +221 -148
  95. data/lib/action_view/helpers/url_helper.rb +283 -165
  96. data/lib/action_view/partials.rb +134 -62
  97. data/lib/action_view/template_error.rb +4 -12
  98. data/lib/actionpack.rb +1 -0
  99. data/test/abstract_unit.rb +21 -1
  100. data/test/action_view_test.rb +26 -0
  101. data/test/active_record_unit.rb +12 -20
  102. data/test/activerecord/active_record_store_test.rb +2 -2
  103. data/test/activerecord/render_partial_with_record_identification_test.rb +74 -0
  104. data/test/controller/action_pack_assertions_test.rb +21 -152
  105. data/test/controller/addresses_render_test.rb +2 -7
  106. data/test/controller/assert_select_test.rb +120 -14
  107. data/test/controller/base_test.rb +11 -13
  108. data/test/controller/caching_test.rb +125 -5
  109. data/test/controller/capture_test.rb +23 -16
  110. data/test/controller/cgi_test.rb +66 -391
  111. data/test/controller/components_test.rb +31 -42
  112. data/test/controller/content_type_test.rb +1 -1
  113. data/test/controller/cookie_test.rb +42 -14
  114. data/test/controller/deprecation/deprecated_base_methods_test.rb +1 -42
  115. data/test/controller/dispatcher_test.rb +123 -0
  116. data/test/controller/fake_models.rb +5 -0
  117. data/test/controller/filters_test.rb +44 -7
  118. data/test/controller/flash_test.rb +46 -2
  119. data/test/controller/fragment_store_setting_test.rb +10 -8
  120. data/test/controller/helper_test.rb +19 -2
  121. data/test/controller/html-scanner/document_test.rb +124 -0
  122. data/test/controller/html-scanner/node_test.rb +69 -0
  123. data/test/controller/html-scanner/sanitizer_test.rb +250 -0
  124. data/test/controller/html-scanner/tag_node_test.rb +239 -0
  125. data/test/controller/html-scanner/text_node_test.rb +51 -0
  126. data/test/controller/html-scanner/tokenizer_test.rb +125 -0
  127. data/test/controller/http_authentication_test.rb +54 -0
  128. data/test/controller/integration_test.rb +12 -26
  129. data/test/controller/layout_test.rb +64 -12
  130. data/test/controller/mime_responds_test.rb +193 -38
  131. data/test/controller/mime_type_test.rb +30 -8
  132. data/test/controller/new_render_test.rb +104 -22
  133. data/test/controller/polymorphic_routes_test.rb +98 -0
  134. data/test/controller/record_identifier_test.rb +103 -0
  135. data/test/controller/redirect_test.rb +120 -18
  136. data/test/controller/render_test.rb +195 -45
  137. data/test/controller/request_forgery_protection_test.rb +217 -0
  138. data/test/controller/request_test.rb +545 -27
  139. data/test/controller/rescue_test.rb +501 -0
  140. data/test/controller/resources_test.rb +258 -132
  141. data/test/controller/routing_test.rb +502 -106
  142. data/test/controller/selector_test.rb +5 -5
  143. data/test/controller/send_file_test.rb +17 -7
  144. data/test/controller/session/cookie_store_test.rb +246 -0
  145. data/test/controller/session/mem_cache_store_test.rb +182 -0
  146. data/test/controller/session_fixation_test.rb +8 -11
  147. data/test/controller/session_management_test.rb +7 -7
  148. data/test/controller/test_test.rb +150 -38
  149. data/test/controller/url_rewriter_test.rb +87 -12
  150. data/test/controller/verification_test.rb +11 -0
  151. data/test/controller/view_paths_test.rb +137 -0
  152. data/test/controller/webservice_test.rb +11 -75
  153. data/test/fixtures/addresses/{list.rhtml → list.erb} +0 -0
  154. data/test/fixtures/db_definitions/sqlite.sql +2 -1
  155. data/test/fixtures/developer.rb +2 -0
  156. data/test/fixtures/fun/games/{hello_world.rhtml → hello_world.erb} +0 -0
  157. data/test/fixtures/helpers/fun/pdf_helper.rb +1 -1
  158. data/test/fixtures/layout_tests/alt/hello.rhtml +1 -0
  159. data/test/fixtures/layout_tests/layouts/multiple_extensions.html.erb +1 -0
  160. data/test/fixtures/layouts/{builder.rxml → builder.builder} +0 -0
  161. data/test/fixtures/layouts/{standard.rhtml → standard.erb} +0 -0
  162. data/test/fixtures/layouts/{talk_from_action.rhtml → talk_from_action.erb} +0 -0
  163. data/test/fixtures/layouts/{yield.rhtml → yield.erb} +0 -0
  164. data/test/fixtures/multipart/binary_file +0 -0
  165. data/test/fixtures/multipart/bracketed_param +5 -0
  166. data/test/fixtures/override/test/hello_world.erb +1 -0
  167. data/test/fixtures/override2/layouts/test/sub.erb +1 -0
  168. data/test/fixtures/post_test/layouts/post.html.erb +1 -0
  169. data/test/fixtures/post_test/layouts/super_post.iphone.erb +1 -0
  170. data/test/fixtures/post_test/post/index.html.erb +1 -0
  171. data/test/fixtures/post_test/post/index.iphone.erb +1 -0
  172. data/test/fixtures/post_test/super_post/index.html.erb +1 -0
  173. data/test/fixtures/post_test/super_post/index.iphone.erb +1 -0
  174. data/test/fixtures/public/404.html +1 -0
  175. data/test/fixtures/public/500.html +1 -0
  176. data/test/fixtures/public/javascripts/application.js +0 -1
  177. data/test/fixtures/public/javascripts/bank.js +1 -0
  178. data/test/fixtures/public/javascripts/robber.js +1 -0
  179. data/test/fixtures/public/stylesheets/bank.css +1 -0
  180. data/test/fixtures/public/stylesheets/robber.css +1 -0
  181. data/test/fixtures/replies.yml +2 -0
  182. data/test/fixtures/reply.rb +2 -1
  183. data/test/fixtures/respond_to/{all_types_with_layout.rhtml → all_types_with_layout.html.erb} +0 -0
  184. data/test/fixtures/respond_to/{all_types_with_layout.rjs → all_types_with_layout.js.rjs} +0 -0
  185. data/test/fixtures/respond_to/custom_constant_handling_without_block.mobile.erb +1 -0
  186. data/test/fixtures/respond_to/iphone_with_html_response_type.html.erb +1 -0
  187. data/test/fixtures/respond_to/iphone_with_html_response_type.iphone.erb +1 -0
  188. data/test/fixtures/respond_to/layouts/missing.html.erb +1 -0
  189. data/test/fixtures/respond_to/layouts/standard.html.erb +1 -0
  190. data/test/fixtures/respond_to/layouts/standard.iphone.erb +1 -0
  191. data/test/fixtures/respond_to/{using_defaults.rhtml → using_defaults.html.erb} +0 -0
  192. data/test/fixtures/respond_to/{using_defaults.rjs → using_defaults.js.rjs} +0 -0
  193. data/test/fixtures/respond_to/{using_defaults.rxml → using_defaults.xml.builder} +0 -0
  194. data/test/fixtures/respond_to/{using_defaults_with_type_list.rhtml → using_defaults_with_type_list.html.erb} +0 -0
  195. data/test/fixtures/respond_to/{using_defaults_with_type_list.rjs → using_defaults_with_type_list.js.rjs} +0 -0
  196. data/test/fixtures/respond_to/{using_defaults_with_type_list.rxml → using_defaults_with_type_list.xml.builder} +0 -0
  197. data/test/fixtures/scope/test/{modgreet.rhtml → modgreet.erb} +0 -0
  198. data/test/fixtures/test/{_customer.rhtml → _customer.erb} +0 -0
  199. data/test/fixtures/test/{_customer_greeting.rhtml → _customer_greeting.erb} +0 -0
  200. data/test/fixtures/test/_hash_greeting.erb +1 -0
  201. data/test/fixtures/test/_hash_object.erb +2 -0
  202. data/test/fixtures/test/{_hello.rxml → _hello.builder} +0 -0
  203. data/test/fixtures/test/_layout_for_partial.html.erb +3 -0
  204. data/test/fixtures/test/_partial.erb +1 -0
  205. data/test/fixtures/test/_partial.html.erb +1 -0
  206. data/test/fixtures/test/_partial.js.erb +1 -0
  207. data/test/fixtures/test/_partial_for_use_in_layout.html.erb +1 -0
  208. data/test/fixtures/test/{_partial_only.rhtml → _partial_only.erb} +0 -0
  209. data/test/fixtures/test/{_person.rhtml → _person.erb} +0 -0
  210. data/test/fixtures/test/{action_talk_to_layout.rhtml → action_talk_to_layout.erb} +0 -0
  211. data/test/fixtures/test/{block_content_for.rhtml → block_content_for.erb} +0 -0
  212. data/test/fixtures/test/calling_partial_with_layout.html.erb +1 -0
  213. data/test/fixtures/test/{capturing.rhtml → capturing.erb} +0 -0
  214. data/test/fixtures/test/{content_for.rhtml → content_for.erb} +0 -0
  215. data/test/fixtures/test/content_for_concatenated.erb +3 -0
  216. data/test/fixtures/test/content_for_with_parameter.erb +2 -0
  217. data/test/fixtures/test/dot.directory/{render_file_with_ivar.rhtml → render_file_with_ivar.erb} +0 -0
  218. data/test/fixtures/test/{erb_content_for.rhtml → erb_content_for.erb} +0 -0
  219. data/test/fixtures/test/formatted_html_erb.html.erb +1 -0
  220. data/test/fixtures/test/formatted_xml_erb.builder +1 -0
  221. data/test/fixtures/test/formatted_xml_erb.html.erb +1 -0
  222. data/test/fixtures/test/formatted_xml_erb.xml.erb +1 -0
  223. data/test/fixtures/test/{greeting.rhtml → greeting.erb} +0 -0
  224. data/test/fixtures/test/{hello.rxml → hello.builder} +0 -0
  225. data/test/fixtures/test/{hello_world.rxml → hello_world.builder} +0 -0
  226. data/test/fixtures/test/{hello_world.rhtml → hello_world.erb} +0 -0
  227. data/test/fixtures/test/{hello_world_container.rxml → hello_world_container.builder} +0 -0
  228. data/test/fixtures/test/{hello_world_with_layout_false.rhtml → hello_world_with_layout_false.erb} +0 -0
  229. data/test/fixtures/test/{hello_xml_world.rxml → hello_xml_world.builder} +0 -0
  230. data/test/fixtures/test/list.erb +1 -0
  231. data/test/fixtures/test/{non_erb_block_content_for.rxml → non_erb_block_content_for.builder} +0 -0
  232. data/test/fixtures/test/{potential_conflicts.rhtml → potential_conflicts.erb} +0 -0
  233. data/test/fixtures/test/{render_file_with_ivar.rhtml → render_file_with_ivar.erb} +0 -0
  234. data/test/fixtures/test/{render_file_with_locals.rhtml → render_file_with_locals.erb} +0 -0
  235. data/test/fixtures/test/{render_to_string_test.rhtml → render_to_string_test.erb} +0 -0
  236. data/test/fixtures/test/{update_element_with_capture.rhtml → update_element_with_capture.erb} +0 -0
  237. data/test/fixtures/test/using_layout_around_block.html.erb +1 -0
  238. data/test/fixtures/topic.rb +1 -1
  239. data/test/template/active_record_helper_test.rb +67 -20
  240. data/test/template/asset_tag_helper_test.rb +222 -54
  241. data/test/template/atom_feed_helper_test.rb +101 -0
  242. data/test/template/benchmark_helper_test.rb +2 -2
  243. data/test/template/compiled_templates_test.rb +76 -32
  244. data/test/template/date_helper_test.rb +125 -9
  245. data/test/template/form_helper_test.rb +326 -33
  246. data/test/template/form_options_helper_test.rb +822 -15
  247. data/test/template/form_tag_helper_test.rb +96 -30
  248. data/test/template/javascript_helper_test.rb +61 -13
  249. data/test/template/number_helper_test.rb +12 -11
  250. data/test/template/prototype_helper_test.rb +185 -24
  251. data/test/template/sanitize_helper_test.rb +49 -0
  252. data/test/template/scriptaculous_helper_test.rb +9 -3
  253. data/test/template/tag_helper_test.rb +13 -2
  254. data/test/template/text_helper_test.rb +38 -52
  255. data/test/template/url_helper_test.rb +216 -46
  256. metadata +144 -116
  257. data/examples/.htaccess +0 -24
  258. data/examples/address_book/index.rhtml +0 -33
  259. data/examples/address_book/layout.rhtml +0 -8
  260. data/examples/address_book_controller.cgi +0 -9
  261. data/examples/address_book_controller.fcgi +0 -6
  262. data/examples/address_book_controller.rb +0 -52
  263. data/examples/address_book_controller.rbx +0 -4
  264. data/examples/benchmark.rb +0 -52
  265. data/examples/benchmark_with_ar.fcgi +0 -89
  266. data/examples/blog_controller.cgi +0 -53
  267. data/examples/debate/index.rhtml +0 -14
  268. data/examples/debate/new_topic.rhtml +0 -22
  269. data/examples/debate/topic.rhtml +0 -32
  270. data/examples/debate_controller.cgi +0 -57
  271. data/lib/action_controller/assertions/deprecated_assertions.rb +0 -228
  272. data/lib/action_controller/cgi_ext/cgi_ext.rb +0 -36
  273. data/lib/action_controller/cgi_ext/cgi_methods.rb +0 -211
  274. data/lib/action_controller/cgi_ext/pstore_performance_fix.rb +0 -30
  275. data/lib/action_controller/cgi_ext/raw_post_data_fix.rb +0 -95
  276. data/lib/action_controller/cgi_ext/session_performance_fix.rb +0 -30
  277. data/lib/action_controller/deprecated_dependencies.rb +0 -65
  278. data/lib/action_controller/deprecated_redirects.rb +0 -17
  279. data/lib/action_controller/deprecated_request_methods.rb +0 -34
  280. data/lib/action_controller/macros/auto_complete.rb +0 -53
  281. data/lib/action_controller/macros/in_place_editing.rb +0 -33
  282. data/lib/action_controller/pagination.rb +0 -408
  283. data/lib/action_controller/scaffolding.rb +0 -189
  284. data/lib/action_controller/templates/rescues/_request_and_response.rhtml +0 -44
  285. data/lib/action_controller/templates/scaffolds/edit.rhtml +0 -7
  286. data/lib/action_controller/templates/scaffolds/layout.rhtml +0 -69
  287. data/lib/action_controller/templates/scaffolds/list.rhtml +0 -27
  288. data/lib/action_controller/templates/scaffolds/new.rhtml +0 -6
  289. data/lib/action_controller/templates/scaffolds/show.rhtml +0 -9
  290. data/lib/action_controller/vendor/xml_node.rb +0 -97
  291. data/lib/action_view/helpers/deprecated_helper.rb +0 -37
  292. data/lib/action_view/helpers/java_script_macros_helper.rb +0 -233
  293. data/lib/action_view/helpers/pagination_helper.rb +0 -86
  294. data/test/activerecord/active_record_assertions_test.rb +0 -92
  295. data/test/activerecord/pagination_test.rb +0 -165
  296. data/test/controller/deprecated_instance_variables_test.rb +0 -48
  297. data/test/controller/raw_post_test.rb +0 -68
  298. data/test/fixtures/deprecated_instance_variables/_cookies_ivar.rhtml +0 -1
  299. data/test/fixtures/deprecated_instance_variables/_cookies_method.rhtml +0 -1
  300. data/test/fixtures/deprecated_instance_variables/_flash_ivar.rhtml +0 -1
  301. data/test/fixtures/deprecated_instance_variables/_flash_method.rhtml +0 -1
  302. data/test/fixtures/deprecated_instance_variables/_headers_ivar.rhtml +0 -1
  303. data/test/fixtures/deprecated_instance_variables/_headers_method.rhtml +0 -1
  304. data/test/fixtures/deprecated_instance_variables/_params_ivar.rhtml +0 -1
  305. data/test/fixtures/deprecated_instance_variables/_params_method.rhtml +0 -1
  306. data/test/fixtures/deprecated_instance_variables/_request_ivar.rhtml +0 -1
  307. data/test/fixtures/deprecated_instance_variables/_request_method.rhtml +0 -1
  308. data/test/fixtures/deprecated_instance_variables/_response_ivar.rhtml +0 -1
  309. data/test/fixtures/deprecated_instance_variables/_response_method.rhtml +0 -1
  310. data/test/fixtures/deprecated_instance_variables/_session_ivar.rhtml +0 -1
  311. data/test/fixtures/deprecated_instance_variables/_session_method.rhtml +0 -1
  312. data/test/fixtures/respond_to/layouts/standard.rhtml +0 -1
  313. data/test/fixtures/test/_hash_object.rhtml +0 -1
  314. data/test/fixtures/test/list.rhtml +0 -1
  315. data/test/template/deprecated_helper_test.rb +0 -36
  316. data/test/template/deprecated_instance_variables_test.rb +0 -43
  317. data/test/template/java_script_macros_helper_test.rb +0 -109
@@ -1,30 +0,0 @@
1
- # CGI::Session::PStore.initialize requires 'digest/md5' on every call.
2
- # This makes sense when spawning processes per request, but is
3
- # unnecessarily expensive when serving requests from a long-lived
4
- # process.
5
- require 'cgi/session'
6
- require 'cgi/session/pstore'
7
- require 'digest/md5'
8
-
9
- class CGI::Session::PStore #:nodoc:
10
- def initialize(session, option={})
11
- dir = option['tmpdir'] || Dir::tmpdir
12
- prefix = option['prefix'] || ''
13
- id = session.session_id
14
- md5 = Digest::MD5.hexdigest(id)[0,16]
15
- path = dir+"/"+prefix+md5
16
- path.untaint
17
- if File::exist?(path)
18
- @hash = nil
19
- else
20
- unless session.new_session
21
- raise CGI::Session::NoSession, "uninitialized session"
22
- end
23
- @hash = {}
24
- end
25
- @p = ::PStore.new(path)
26
- @p.transaction do |p|
27
- File.chmod(0600, p.path)
28
- end
29
- end
30
- end
@@ -1,95 +0,0 @@
1
- class CGI #:nodoc:
2
- module QueryExtension
3
- # Initialize the data from the query.
4
- #
5
- # Handles multipart forms (in particular, forms that involve file uploads).
6
- # Reads query parameters in the @params field, and cookies into @cookies.
7
- def initialize_query
8
- @cookies = CGI::Cookie::parse(env_table['HTTP_COOKIE'] || env_table['COOKIE'])
9
-
10
- # Fix some strange request environments.
11
- if method = env_table['REQUEST_METHOD']
12
- method = method.to_s.downcase.intern
13
- else
14
- method = :get
15
- end
16
-
17
- # POST assumes missing Content-Type is application/x-www-form-urlencoded.
18
- content_type = env_table['CONTENT_TYPE']
19
- if content_type.blank? && method == :post
20
- content_type = 'application/x-www-form-urlencoded'
21
- end
22
-
23
- # Force content length to zero if missing.
24
- content_length = env_table['CONTENT_LENGTH'].to_i
25
-
26
- # Set multipart to false by default.
27
- @multipart = false
28
-
29
- # POST and PUT may have params in entity body. If content type is
30
- # missing for POST, assume urlencoded. If content type is missing
31
- # for PUT, don't assume anything and don't parse the parameters:
32
- # it's likely binary data.
33
- #
34
- # The other HTTP methods have their params in the query string.
35
- if method == :post || method == :put
36
- if boundary = extract_multipart_form_boundary(content_type)
37
- @multipart = true
38
- @params = read_multipart(boundary, content_length)
39
- elsif content_type.blank? || content_type !~ %r{application/x-www-form-urlencoded}i
40
- read_params(method, content_length)
41
- @params = {}
42
- end
43
- end
44
-
45
- @params ||= CGI.parse(read_params(method, content_length))
46
- end
47
-
48
- private
49
- unless defined?(MULTIPART_FORM_BOUNDARY_RE)
50
- MULTIPART_FORM_BOUNDARY_RE = %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|n #"
51
- end
52
-
53
- def extract_multipart_form_boundary(content_type)
54
- MULTIPART_FORM_BOUNDARY_RE.match(content_type).to_a.pop
55
- end
56
-
57
- if defined? MOD_RUBY
58
- def read_query
59
- Apache::request.args || ''
60
- end
61
- else
62
- def read_query
63
- # fixes CGI querystring parsing for lighttpd
64
- env_qs = env_table['QUERY_STRING']
65
- if env_qs.blank? && !(uri = env_table['REQUEST_URI']).blank?
66
- uri.split('?', 2)[1] || ''
67
- else
68
- env_qs || ''
69
- end
70
- end
71
- end
72
-
73
- def read_body(content_length)
74
- stdinput.binmode if stdinput.respond_to?(:binmode)
75
- content = stdinput.read(content_length) || ''
76
- # Fix for Safari Ajax postings that always append \000
77
- content.chop! if content[-1] == 0
78
- content.gsub!(/&_=$/, '')
79
- env_table['RAW_POST_DATA'] = content.freeze
80
- end
81
-
82
- def read_params(method, content_length)
83
- case method
84
- when :get
85
- read_query
86
- when :post, :put
87
- read_body(content_length)
88
- when :cmd
89
- read_from_cmdline
90
- else # :head, :delete, :options, :trace, :connect
91
- read_query
92
- end
93
- end
94
- end # module QueryExtension
95
- end
@@ -1,30 +0,0 @@
1
- # CGI::Session#create_new_id requires 'digest/md5' on every call. This makes
2
- # sense when spawning processes per request, but is unnecessarily expensive
3
- # when serving requests from a long-lived process.
4
- #
5
- # http://railsexpress.de/blog/articles/2005/11/22/speeding-up-the-creation-of-new-sessions
6
- require 'cgi/session'
7
- require 'digest/md5'
8
-
9
- class CGI
10
- class Session #:nodoc:
11
- private
12
- # Create a new session id.
13
- #
14
- # The session id is an MD5 hash based upon the time,
15
- # a random number, and a constant string. This routine
16
- # is used internally for automatically generated
17
- # session ids.
18
- def create_new_id
19
- md5 = Digest::MD5::new
20
- now = Time::now
21
- md5.update(now.to_s)
22
- md5.update(String(now.usec))
23
- md5.update(String(rand(0)))
24
- md5.update(String($$))
25
- md5.update('foobar')
26
- @new_session = true
27
- md5.hexdigest
28
- end
29
- end
30
- end
@@ -1,65 +0,0 @@
1
- module ActionController #:nodoc:
2
- module Dependencies #:nodoc:
3
- def self.included(base)
4
- base.extend(ClassMethods)
5
- end
6
-
7
- # Deprecated module. The responsibility of loading dependencies belong with Active Support now.
8
- module ClassMethods #:nodoc:
9
- # Specifies a variable number of models that this controller depends on. Models are normally Active Record classes or a similar
10
- # backend for modelling entity classes.
11
- def model(*models)
12
- require_dependencies(:model, models)
13
- depend_on(:model, models)
14
- end
15
- deprecate :model
16
-
17
- # Specifies a variable number of services that this controller depends on. Services are normally singletons or factories, like
18
- # Action Mailer service or a Payment Gateway service.
19
- def service(*services)
20
- require_dependencies(:service, services)
21
- depend_on(:service, services)
22
- end
23
- deprecate :service
24
-
25
- # Specifies a variable number of observers that are to govern when this controller is handling actions. The observers will
26
- # automatically have .instance called on them to make them active on assignment.
27
- def observer(*observers)
28
- require_dependencies(:observer, observers)
29
- depend_on(:observer, observers)
30
- instantiate_observers(observers)
31
- end
32
- deprecate :observer
33
-
34
- # Returns an array of symbols that specify the dependencies on a given layer. For the example at the top, calling
35
- # <tt>ApplicationController.dependencies_on(:model)</tt> would return <tt>[:account, :company, :person, :project, :category]</tt>
36
- def dependencies_on(layer)
37
- read_inheritable_attribute("#{layer}_dependencies")
38
- end
39
- deprecate :dependencies_on
40
-
41
- def depend_on(layer, dependencies) #:nodoc:
42
- write_inheritable_array("#{layer}_dependencies", dependencies)
43
- end
44
- deprecate :depend_on
45
-
46
- private
47
- def instantiate_observers(observers)
48
- observers.flatten.each { |observer| Object.const_get(Inflector.classify(observer.to_s)).instance }
49
- end
50
-
51
- def require_dependencies(layer, dependencies)
52
- dependencies.flatten.each do |dependency|
53
- begin
54
- require_dependency(dependency.to_s)
55
- rescue LoadError => e
56
- raise LoadError.new("Missing #{layer} #{dependency}.rb").copy_blame!(e)
57
- rescue Exception => exception # error from loaded file
58
- exception.blame_file! "=> #{layer} #{dependency}.rb"
59
- raise
60
- end
61
- end
62
- end
63
- end
64
- end
65
- end
@@ -1,17 +0,0 @@
1
- module ActionController
2
- class Base
3
- protected
4
- # Deprecated in favor of calling redirect_to directly with the path.
5
- def redirect_to_path(path) #:nodoc:
6
- redirect_to(path)
7
- end
8
-
9
- # Deprecated in favor of calling redirect_to directly with the url. If the resource has moved permanently, it's possible to pass
10
- # true as the second parameter and the browser will get "301 Moved Permanently" instead of "302 Found". This can also be done through
11
- # just setting the headers["Status"] to "301 Moved Permanently" before using the redirect_to.
12
- def redirect_to_url(url, permanently = false) #:nodoc:
13
- headers["Status"] = "301 Moved Permanently" if permanently
14
- redirect_to(url)
15
- end
16
- end
17
- end
@@ -1,34 +0,0 @@
1
- module ActionController
2
- class AbstractRequest
3
- # Determine whether the body of a HTTP call is URL-encoded (default)
4
- # or matches one of the registered param_parsers.
5
- #
6
- # For backward compatibility, the post format is extracted from the
7
- # X-Post-Data-Format HTTP header if present.
8
- def post_format
9
- case content_type.to_s
10
- when 'application/xml'
11
- :xml
12
- when 'application/x-yaml'
13
- :yaml
14
- else
15
- :url_encoded
16
- end
17
- end
18
-
19
- # Is this a POST request formatted as XML or YAML?
20
- def formatted_post?
21
- post? && (post_format == :yaml || post_format == :xml)
22
- end
23
-
24
- # Is this a POST request formatted as XML?
25
- def xml_post?
26
- post? && post_format == :xml
27
- end
28
-
29
- # Is this a POST request formatted as YAML?
30
- def yaml_post?
31
- post? && post_format == :yaml
32
- end
33
- end
34
- end
@@ -1,53 +0,0 @@
1
- module ActionController
2
- # Macros are class-level calls that add pre-defined actions to the controller based on the parameters passed in.
3
- # Currently, they're used to bridge the JavaScript macros, like autocompletion and in-place editing, with the controller
4
- # backing.
5
- module Macros
6
- module AutoComplete #:nodoc:
7
- def self.included(base) #:nodoc:
8
- base.extend(ClassMethods)
9
- end
10
-
11
- # DEPRECATION WARNING: This method will become a separate plugin when Rails 2.0 ships.
12
- #
13
- # Example:
14
- #
15
- # # Controller
16
- # class BlogController < ApplicationController
17
- # auto_complete_for :post, :title
18
- # end
19
- #
20
- # # View
21
- # <%= text_field_with_auto_complete :post, title %>
22
- #
23
- # By default, auto_complete_for limits the results to 10 entries,
24
- # and sorts by the given field.
25
- #
26
- # auto_complete_for takes a third parameter, an options hash to
27
- # the find method used to search for the records:
28
- #
29
- # auto_complete_for :post, :title, :limit => 15, :order => 'created_at DESC'
30
- #
31
- # For help on defining text input fields with autocompletion,
32
- # see ActionView::Helpers::JavaScriptHelper.
33
- #
34
- # For more examples, see script.aculo.us:
35
- # * http://script.aculo.us/demos/ajax/autocompleter
36
- # * http://script.aculo.us/demos/ajax/autocompleter_customized
37
- module ClassMethods
38
- def auto_complete_for(object, method, options = {})
39
- define_method("auto_complete_for_#{object}_#{method}") do
40
- find_options = {
41
- :conditions => [ "LOWER(#{method}) LIKE ?", '%' + params[object][method].downcase + '%' ],
42
- :order => "#{method} ASC",
43
- :limit => 10 }.merge!(options)
44
-
45
- @items = object.to_s.camelize.constantize.find(:all, find_options)
46
-
47
- render :inline => "<%= auto_complete_result @items, '#{method}' %>"
48
- end
49
- end
50
- end
51
- end
52
- end
53
- end
@@ -1,33 +0,0 @@
1
- module ActionController
2
- module Macros
3
- module InPlaceEditing #:nodoc:
4
- def self.included(base) #:nodoc:
5
- base.extend(ClassMethods)
6
- end
7
-
8
- # DEPRECATION WARNING: This method will become a separate plugin when Rails 2.0 ships.
9
- #
10
- # Example:
11
- #
12
- # # Controller
13
- # class BlogController < ApplicationController
14
- # in_place_edit_for :post, :title
15
- # end
16
- #
17
- # # View
18
- # <%= in_place_editor_field :post, 'title' %>
19
- #
20
- # For help on defining an in place editor in the browser,
21
- # see ActionView::Helpers::JavaScriptHelper.
22
- module ClassMethods
23
- def in_place_edit_for(object, attribute, options = {})
24
- define_method("set_#{object}_#{attribute}") do
25
- @item = object.to_s.camelize.constantize.find(params[:id])
26
- @item.update_attribute(attribute, params[:value])
27
- render :text => @item.send(attribute).to_s
28
- end
29
- end
30
- end
31
- end
32
- end
33
- end
@@ -1,408 +0,0 @@
1
- module ActionController
2
- # === Action Pack pagination for Active Record collections
3
- #
4
- # DEPRECATION WARNING: Pagination will be moved to a plugin in Rails 2.0.
5
- # Install the classic_pagination plugin for forward compatibility:
6
- # script/plugin install svn://errtheblog.com/svn/plugins/classic_pagination
7
- #
8
- # The Pagination module aids in the process of paging large collections of
9
- # Active Record objects. It offers macro-style automatic fetching of your
10
- # model for multiple views, or explicit fetching for single actions. And if
11
- # the magic isn't flexible enough for your needs, you can create your own
12
- # paginators with a minimal amount of code.
13
- #
14
- # The Pagination module can handle as much or as little as you wish. In the
15
- # controller, have it automatically query your model for pagination; or,
16
- # if you prefer, create Paginator objects yourself.
17
- #
18
- # Pagination is included automatically for all controllers.
19
- #
20
- # For help rendering pagination links, see
21
- # ActionView::Helpers::PaginationHelper.
22
- #
23
- # ==== Automatic pagination for every action in a controller
24
- #
25
- # class PersonController < ApplicationController
26
- # model :person
27
- #
28
- # paginate :people, :order => 'last_name, first_name',
29
- # :per_page => 20
30
- #
31
- # # ...
32
- # end
33
- #
34
- # Each action in this controller now has access to a <tt>@people</tt>
35
- # instance variable, which is an ordered collection of model objects for the
36
- # current page (at most 20, sorted by last name and first name), and a
37
- # <tt>@person_pages</tt> Paginator instance. The current page is determined
38
- # by the <tt>params[:page]</tt> variable.
39
- #
40
- # ==== Pagination for a single action
41
- #
42
- # def list
43
- # @person_pages, @people =
44
- # paginate :people, :order => 'last_name, first_name'
45
- # end
46
- #
47
- # Like the previous example, but explicitly creates <tt>@person_pages</tt>
48
- # and <tt>@people</tt> for a single action, and uses the default of 10 items
49
- # per page.
50
- #
51
- # ==== Custom/"classic" pagination
52
- #
53
- # def list
54
- # @person_pages = Paginator.new self, Person.count, 10, params[:page]
55
- # @people = Person.find :all, :order => 'last_name, first_name',
56
- # :limit => @person_pages.items_per_page,
57
- # :offset => @person_pages.current.offset
58
- # end
59
- #
60
- # Explicitly creates the paginator from the previous example and uses
61
- # Paginator#to_sql to retrieve <tt>@people</tt> from the model.
62
- #
63
- module Pagination
64
- unless const_defined?(:OPTIONS)
65
- # A hash holding options for controllers using macro-style pagination
66
- OPTIONS = Hash.new
67
-
68
- # The default options for pagination
69
- DEFAULT_OPTIONS = {
70
- :class_name => nil,
71
- :singular_name => nil,
72
- :per_page => 10,
73
- :conditions => nil,
74
- :order_by => nil,
75
- :order => nil,
76
- :join => nil,
77
- :joins => nil,
78
- :count => nil,
79
- :include => nil,
80
- :select => nil,
81
- :parameter => 'page'
82
- }
83
- end
84
-
85
- def self.included(base) #:nodoc:
86
- super
87
- base.extend(ClassMethods)
88
- end
89
-
90
- def self.validate_options!(collection_id, options, in_action) #:nodoc:
91
- options.merge!(DEFAULT_OPTIONS) {|key, old, new| old}
92
-
93
- valid_options = DEFAULT_OPTIONS.keys
94
- valid_options << :actions unless in_action
95
-
96
- unknown_option_keys = options.keys - valid_options
97
- raise ActionController::ActionControllerError,
98
- "Unknown options: #{unknown_option_keys.join(', ')}" unless
99
- unknown_option_keys.empty?
100
-
101
- options[:singular_name] ||= Inflector.singularize(collection_id.to_s)
102
- options[:class_name] ||= Inflector.camelize(options[:singular_name])
103
- end
104
-
105
- # Returns a paginator and a collection of Active Record model instances
106
- # for the paginator's current page. This is designed to be used in a
107
- # single action; to automatically paginate multiple actions, consider
108
- # ClassMethods#paginate.
109
- #
110
- # +options+ are:
111
- # <tt>:singular_name</tt>:: the singular name to use, if it can't be inferred by singularizing the collection name
112
- # <tt>:class_name</tt>:: the class name to use, if it can't be inferred by
113
- # camelizing the singular name
114
- # <tt>:per_page</tt>:: the maximum number of items to include in a
115
- # single page. Defaults to 10
116
- # <tt>:conditions</tt>:: optional conditions passed to Model.find(:all, *params) and
117
- # Model.count
118
- # <tt>:order</tt>:: optional order parameter passed to Model.find(:all, *params)
119
- # <tt>:order_by</tt>:: (deprecated, used :order) optional order parameter passed to Model.find(:all, *params)
120
- # <tt>:joins</tt>:: optional joins parameter passed to Model.find(:all, *params)
121
- # and Model.count
122
- # <tt>:join</tt>:: (deprecated, used :joins or :include) optional join parameter passed to Model.find(:all, *params)
123
- # and Model.count
124
- # <tt>:include</tt>:: optional eager loading parameter passed to Model.find(:all, *params)
125
- # and Model.count
126
- # <tt>:select</tt>:: :select parameter passed to Model.find(:all, *params)
127
- #
128
- # <tt>:count</tt>:: parameter passed as :select option to Model.count(*params)
129
- #
130
- def paginate(collection_id, options={})
131
- Pagination.validate_options!(collection_id, options, true)
132
- paginator_and_collection_for(collection_id, options)
133
- end
134
-
135
- deprecate :paginate => 'Pagination is moving to a plugin in Rails 2.0: script/plugin install svn://errtheblog.com/svn/plugins/classic_pagination'
136
-
137
- # These methods become class methods on any controller
138
- module ClassMethods
139
- # Creates a +before_filter+ which automatically paginates an Active
140
- # Record model for all actions in a controller (or certain actions if
141
- # specified with the <tt>:actions</tt> option).
142
- #
143
- # +options+ are the same as PaginationHelper#paginate, with the addition
144
- # of:
145
- # <tt>:actions</tt>:: an array of actions for which the pagination is
146
- # active. Defaults to +nil+ (i.e., every action)
147
- def paginate(collection_id, options={})
148
- Pagination.validate_options!(collection_id, options, false)
149
- module_eval do
150
- before_filter :create_paginators_and_retrieve_collections
151
- OPTIONS[self] ||= Hash.new
152
- OPTIONS[self][collection_id] = options
153
- end
154
- end
155
-
156
- deprecate :paginate => 'Pagination is moving to a plugin in Rails 2.0: script/plugin install svn://errtheblog.com/svn/plugins/classic_pagination'
157
- end
158
-
159
- def create_paginators_and_retrieve_collections #:nodoc:
160
- Pagination::OPTIONS[self.class].each do |collection_id, options|
161
- next unless options[:actions].include? action_name if
162
- options[:actions]
163
-
164
- paginator, collection =
165
- paginator_and_collection_for(collection_id, options)
166
-
167
- paginator_name = "@#{options[:singular_name]}_pages"
168
- self.instance_variable_set(paginator_name, paginator)
169
-
170
- collection_name = "@#{collection_id.to_s}"
171
- self.instance_variable_set(collection_name, collection)
172
- end
173
- end
174
-
175
- # Returns the total number of items in the collection to be paginated for
176
- # the +model+ and given +conditions+. Override this method to implement a
177
- # custom counter.
178
- def count_collection_for_pagination(model, options)
179
- model.count(:conditions => options[:conditions],
180
- :joins => options[:join] || options[:joins],
181
- :include => options[:include],
182
- :select => options[:count])
183
- end
184
-
185
- # Returns a collection of items for the given +model+ and +options[conditions]+,
186
- # ordered by +options[order]+, for the current page in the given +paginator+.
187
- # Override this method to implement a custom finder.
188
- def find_collection_for_pagination(model, options, paginator)
189
- model.find(:all, :conditions => options[:conditions],
190
- :order => options[:order_by] || options[:order],
191
- :joins => options[:join] || options[:joins], :include => options[:include],
192
- :select => options[:select], :limit => options[:per_page],
193
- :offset => paginator.current.offset)
194
- end
195
-
196
- protected :create_paginators_and_retrieve_collections,
197
- :count_collection_for_pagination,
198
- :find_collection_for_pagination
199
-
200
- def paginator_and_collection_for(collection_id, options) #:nodoc:
201
- klass = options[:class_name].constantize
202
- page = params[options[:parameter]]
203
- count = count_collection_for_pagination(klass, options)
204
- paginator = Paginator.new(self, count, options[:per_page], page)
205
- collection = find_collection_for_pagination(klass, options, paginator)
206
-
207
- return paginator, collection
208
- end
209
-
210
- private :paginator_and_collection_for
211
-
212
- # A class representing a paginator for an Active Record collection.
213
- class Paginator
214
- include Enumerable
215
-
216
- # Creates a new Paginator on the given +controller+ for a set of items
217
- # of size +item_count+ and having +items_per_page+ items per page.
218
- # Raises ArgumentError if items_per_page is out of bounds (i.e., less
219
- # than or equal to zero). The page CGI parameter for links defaults to
220
- # "page" and can be overridden with +page_parameter+.
221
- def initialize(controller, item_count, items_per_page, current_page=1)
222
- raise ArgumentError, 'must have at least one item per page' if
223
- items_per_page <= 0
224
-
225
- @controller = controller
226
- @item_count = item_count || 0
227
- @items_per_page = items_per_page
228
- @pages = {}
229
-
230
- self.current_page = current_page
231
- end
232
- attr_reader :controller, :item_count, :items_per_page
233
-
234
- # Sets the current page number of this paginator. If +page+ is a Page
235
- # object, its +number+ attribute is used as the value; if the page does
236
- # not belong to this Paginator, an ArgumentError is raised.
237
- def current_page=(page)
238
- if page.is_a? Page
239
- raise ArgumentError, 'Page/Paginator mismatch' unless
240
- page.paginator == self
241
- end
242
- page = page.to_i
243
- @current_page_number = has_page_number?(page) ? page : 1
244
- end
245
-
246
- # Returns a Page object representing this paginator's current page.
247
- def current_page
248
- @current_page ||= self[@current_page_number]
249
- end
250
- alias current :current_page
251
-
252
- # Returns a new Page representing the first page in this paginator.
253
- def first_page
254
- @first_page ||= self[1]
255
- end
256
- alias first :first_page
257
-
258
- # Returns a new Page representing the last page in this paginator.
259
- def last_page
260
- @last_page ||= self[page_count]
261
- end
262
- alias last :last_page
263
-
264
- # Returns the number of pages in this paginator.
265
- def page_count
266
- @page_count ||= @item_count.zero? ? 1 :
267
- (q,r=@item_count.divmod(@items_per_page); r==0? q : q+1)
268
- end
269
-
270
- alias length :page_count
271
-
272
- # Returns true if this paginator contains the page of index +number+.
273
- def has_page_number?(number)
274
- number >= 1 and number <= page_count
275
- end
276
-
277
- # Returns a new Page representing the page with the given index
278
- # +number+.
279
- def [](number)
280
- @pages[number] ||= Page.new(self, number)
281
- end
282
-
283
- # Successively yields all the paginator's pages to the given block.
284
- def each(&block)
285
- page_count.times do |n|
286
- yield self[n+1]
287
- end
288
- end
289
-
290
- # A class representing a single page in a paginator.
291
- class Page
292
- include Comparable
293
-
294
- # Creates a new Page for the given +paginator+ with the index
295
- # +number+. If +number+ is not in the range of valid page numbers or
296
- # is not a number at all, it defaults to 1.
297
- def initialize(paginator, number)
298
- @paginator = paginator
299
- @number = number.to_i
300
- @number = 1 unless @paginator.has_page_number? @number
301
- end
302
- attr_reader :paginator, :number
303
- alias to_i :number
304
-
305
- # Compares two Page objects and returns true when they represent the
306
- # same page (i.e., their paginators are the same and they have the
307
- # same page number).
308
- def ==(page)
309
- return false if page.nil?
310
- @paginator == page.paginator and
311
- @number == page.number
312
- end
313
-
314
- # Compares two Page objects and returns -1 if the left-hand page comes
315
- # before the right-hand page, 0 if the pages are equal, and 1 if the
316
- # left-hand page comes after the right-hand page. Raises ArgumentError
317
- # if the pages do not belong to the same Paginator object.
318
- def <=>(page)
319
- raise ArgumentError unless @paginator == page.paginator
320
- @number <=> page.number
321
- end
322
-
323
- # Returns the item offset for the first item in this page.
324
- def offset
325
- @paginator.items_per_page * (@number - 1)
326
- end
327
-
328
- # Returns the number of the first item displayed.
329
- def first_item
330
- offset + 1
331
- end
332
-
333
- # Returns the number of the last item displayed.
334
- def last_item
335
- [@paginator.items_per_page * @number, @paginator.item_count].min
336
- end
337
-
338
- # Returns true if this page is the first page in the paginator.
339
- def first?
340
- self == @paginator.first
341
- end
342
-
343
- # Returns true if this page is the last page in the paginator.
344
- def last?
345
- self == @paginator.last
346
- end
347
-
348
- # Returns a new Page object representing the page just before this
349
- # page, or nil if this is the first page.
350
- def previous
351
- if first? then nil else @paginator[@number - 1] end
352
- end
353
-
354
- # Returns a new Page object representing the page just after this
355
- # page, or nil if this is the last page.
356
- def next
357
- if last? then nil else @paginator[@number + 1] end
358
- end
359
-
360
- # Returns a new Window object for this page with the specified
361
- # +padding+.
362
- def window(padding=2)
363
- Window.new(self, padding)
364
- end
365
-
366
- # Returns the limit/offset array for this page.
367
- def to_sql
368
- [@paginator.items_per_page, offset]
369
- end
370
-
371
- def to_param #:nodoc:
372
- @number.to_s
373
- end
374
- end
375
-
376
- # A class for representing ranges around a given page.
377
- class Window
378
- # Creates a new Window object for the given +page+ with the specified
379
- # +padding+.
380
- def initialize(page, padding=2)
381
- @paginator = page.paginator
382
- @page = page
383
- self.padding = padding
384
- end
385
- attr_reader :paginator, :page
386
-
387
- # Sets the window's padding (the number of pages on either side of the
388
- # window page).
389
- def padding=(padding)
390
- @padding = padding < 0 ? 0 : padding
391
- # Find the beginning and end pages of the window
392
- @first = @paginator.has_page_number?(@page.number - @padding) ?
393
- @paginator[@page.number - @padding] : @paginator.first
394
- @last = @paginator.has_page_number?(@page.number + @padding) ?
395
- @paginator[@page.number + @padding] : @paginator.last
396
- end
397
- attr_reader :padding, :first, :last
398
-
399
- # Returns an array of Page objects in the current window.
400
- def pages
401
- (@first.number..@last.number).to_a.collect! {|n| @paginator[n]}
402
- end
403
- alias to_a :pages
404
- end
405
- end
406
-
407
- end
408
- end