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.
- data/CHANGELOG +1400 -20
- data/MIT-LICENSE +1 -1
- data/README +5 -5
- data/RUNNING_UNIT_TESTS +4 -5
- data/Rakefile +5 -6
- data/install.rb +2 -2
- data/lib/action_controller.rb +11 -15
- data/lib/action_controller/assertions.rb +12 -25
- data/lib/action_controller/assertions/dom_assertions.rb +18 -4
- data/lib/action_controller/assertions/model_assertions.rb +8 -1
- data/lib/action_controller/assertions/response_assertions.rb +35 -12
- data/lib/action_controller/assertions/routing_assertions.rb +56 -12
- data/lib/action_controller/assertions/selector_assertions.rb +105 -38
- data/lib/action_controller/assertions/tag_assertions.rb +28 -15
- data/lib/action_controller/base.rb +318 -250
- data/lib/action_controller/benchmarking.rb +33 -29
- data/lib/action_controller/caching.rb +130 -64
- data/lib/action_controller/cgi_ext.rb +16 -0
- data/lib/action_controller/cgi_ext/{cookie_performance_fix.rb → cookie.rb} +25 -40
- data/lib/action_controller/cgi_ext/query_extension.rb +22 -0
- data/lib/action_controller/cgi_ext/session.rb +73 -0
- data/lib/action_controller/cgi_ext/stdinput.rb +23 -0
- data/lib/action_controller/cgi_process.rb +34 -57
- data/lib/action_controller/components.rb +19 -36
- data/lib/action_controller/cookies.rb +10 -9
- data/lib/action_controller/dispatcher.rb +195 -0
- data/lib/action_controller/filters.rb +35 -34
- data/lib/action_controller/flash.rb +30 -35
- data/lib/action_controller/helpers.rb +121 -47
- data/lib/action_controller/http_authentication.rb +126 -0
- data/lib/action_controller/integration.rb +105 -101
- data/lib/action_controller/layout.rb +59 -47
- data/lib/action_controller/mime_responds.rb +57 -68
- data/lib/action_controller/mime_type.rb +43 -80
- data/lib/action_controller/mime_types.rb +20 -0
- data/lib/action_controller/polymorphic_routes.rb +88 -0
- data/lib/action_controller/record_identifier.rb +91 -0
- data/lib/action_controller/request.rb +553 -88
- data/lib/action_controller/request_forgery_protection.rb +126 -0
- data/lib/action_controller/request_profiler.rb +138 -0
- data/lib/action_controller/rescue.rb +185 -69
- data/lib/action_controller/resources.rb +211 -172
- data/lib/action_controller/response.rb +49 -8
- data/lib/action_controller/routing.rb +359 -236
- data/lib/action_controller/routing_optimisation.rb +119 -0
- data/lib/action_controller/session/active_record_store.rb +3 -2
- data/lib/action_controller/session/cookie_store.rb +161 -0
- data/lib/action_controller/session/mem_cache_store.rb +9 -16
- data/lib/action_controller/session_management.rb +17 -8
- data/lib/action_controller/streaming.rb +6 -3
- data/lib/action_controller/templates/rescues/_request_and_response.erb +24 -0
- data/lib/action_controller/templates/rescues/{_trace.rhtml → _trace.erb} +0 -0
- data/lib/action_controller/templates/rescues/{diagnostics.rhtml → diagnostics.erb} +2 -2
- data/lib/action_controller/templates/rescues/{layout.rhtml → layout.erb} +0 -0
- data/lib/action_controller/templates/rescues/{missing_template.rhtml → missing_template.erb} +0 -0
- data/lib/action_controller/templates/rescues/{routing_error.rhtml → routing_error.erb} +0 -0
- data/lib/action_controller/templates/rescues/{template_error.rhtml → template_error.erb} +2 -2
- data/lib/action_controller/templates/rescues/{unknown_action.rhtml → unknown_action.erb} +0 -0
- data/lib/action_controller/test_case.rb +53 -0
- data/lib/action_controller/test_process.rb +59 -46
- data/lib/action_controller/url_rewriter.rb +48 -24
- data/lib/action_controller/vendor/html-scanner/html/document.rb +7 -4
- data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +173 -0
- data/lib/action_controller/vendor/html-scanner/html/selector.rb +11 -6
- data/lib/action_controller/verification.rb +27 -21
- data/lib/action_pack.rb +1 -1
- data/lib/action_pack/version.rb +4 -4
- data/lib/action_view.rb +2 -3
- data/lib/action_view/base.rb +218 -63
- data/lib/action_view/compiled_templates.rb +1 -2
- data/lib/action_view/helpers/active_record_helper.rb +35 -17
- data/lib/action_view/helpers/asset_tag_helper.rb +395 -87
- data/lib/action_view/helpers/atom_feed_helper.rb +111 -0
- data/lib/action_view/helpers/benchmark_helper.rb +12 -5
- data/lib/action_view/helpers/cache_helper.rb +29 -0
- data/lib/action_view/helpers/capture_helper.rb +97 -63
- data/lib/action_view/helpers/date_helper.rb +295 -35
- data/lib/action_view/helpers/debug_helper.rb +6 -2
- data/lib/action_view/helpers/form_helper.rb +354 -111
- data/lib/action_view/helpers/form_options_helper.rb +171 -109
- data/lib/action_view/helpers/form_tag_helper.rb +332 -76
- data/lib/action_view/helpers/javascript_helper.rb +35 -11
- data/lib/action_view/helpers/javascripts/controls.js +484 -354
- data/lib/action_view/helpers/javascripts/dragdrop.js +88 -58
- data/lib/action_view/helpers/javascripts/effects.js +396 -364
- data/lib/action_view/helpers/javascripts/prototype.js +2817 -1107
- data/lib/action_view/helpers/number_helper.rb +84 -60
- data/lib/action_view/helpers/prototype_helper.rb +419 -43
- data/lib/action_view/helpers/record_identification_helper.rb +20 -0
- data/lib/action_view/helpers/record_tag_helper.rb +59 -0
- data/lib/action_view/helpers/sanitize_helper.rb +223 -0
- data/lib/action_view/helpers/scriptaculous_helper.rb +63 -4
- data/lib/action_view/helpers/tag_helper.rb +69 -39
- data/lib/action_view/helpers/text_helper.rb +221 -148
- data/lib/action_view/helpers/url_helper.rb +283 -165
- data/lib/action_view/partials.rb +134 -62
- data/lib/action_view/template_error.rb +4 -12
- data/lib/actionpack.rb +1 -0
- data/test/abstract_unit.rb +21 -1
- data/test/action_view_test.rb +26 -0
- data/test/active_record_unit.rb +12 -20
- data/test/activerecord/active_record_store_test.rb +2 -2
- data/test/activerecord/render_partial_with_record_identification_test.rb +74 -0
- data/test/controller/action_pack_assertions_test.rb +21 -152
- data/test/controller/addresses_render_test.rb +2 -7
- data/test/controller/assert_select_test.rb +120 -14
- data/test/controller/base_test.rb +11 -13
- data/test/controller/caching_test.rb +125 -5
- data/test/controller/capture_test.rb +23 -16
- data/test/controller/cgi_test.rb +66 -391
- data/test/controller/components_test.rb +31 -42
- data/test/controller/content_type_test.rb +1 -1
- data/test/controller/cookie_test.rb +42 -14
- data/test/controller/deprecation/deprecated_base_methods_test.rb +1 -42
- data/test/controller/dispatcher_test.rb +123 -0
- data/test/controller/fake_models.rb +5 -0
- data/test/controller/filters_test.rb +44 -7
- data/test/controller/flash_test.rb +46 -2
- data/test/controller/fragment_store_setting_test.rb +10 -8
- data/test/controller/helper_test.rb +19 -2
- data/test/controller/html-scanner/document_test.rb +124 -0
- data/test/controller/html-scanner/node_test.rb +69 -0
- data/test/controller/html-scanner/sanitizer_test.rb +250 -0
- data/test/controller/html-scanner/tag_node_test.rb +239 -0
- data/test/controller/html-scanner/text_node_test.rb +51 -0
- data/test/controller/html-scanner/tokenizer_test.rb +125 -0
- data/test/controller/http_authentication_test.rb +54 -0
- data/test/controller/integration_test.rb +12 -26
- data/test/controller/layout_test.rb +64 -12
- data/test/controller/mime_responds_test.rb +193 -38
- data/test/controller/mime_type_test.rb +30 -8
- data/test/controller/new_render_test.rb +104 -22
- data/test/controller/polymorphic_routes_test.rb +98 -0
- data/test/controller/record_identifier_test.rb +103 -0
- data/test/controller/redirect_test.rb +120 -18
- data/test/controller/render_test.rb +195 -45
- data/test/controller/request_forgery_protection_test.rb +217 -0
- data/test/controller/request_test.rb +545 -27
- data/test/controller/rescue_test.rb +501 -0
- data/test/controller/resources_test.rb +258 -132
- data/test/controller/routing_test.rb +502 -106
- data/test/controller/selector_test.rb +5 -5
- data/test/controller/send_file_test.rb +17 -7
- data/test/controller/session/cookie_store_test.rb +246 -0
- data/test/controller/session/mem_cache_store_test.rb +182 -0
- data/test/controller/session_fixation_test.rb +8 -11
- data/test/controller/session_management_test.rb +7 -7
- data/test/controller/test_test.rb +150 -38
- data/test/controller/url_rewriter_test.rb +87 -12
- data/test/controller/verification_test.rb +11 -0
- data/test/controller/view_paths_test.rb +137 -0
- data/test/controller/webservice_test.rb +11 -75
- data/test/fixtures/addresses/{list.rhtml → list.erb} +0 -0
- data/test/fixtures/db_definitions/sqlite.sql +2 -1
- data/test/fixtures/developer.rb +2 -0
- data/test/fixtures/fun/games/{hello_world.rhtml → hello_world.erb} +0 -0
- data/test/fixtures/helpers/fun/pdf_helper.rb +1 -1
- data/test/fixtures/layout_tests/alt/hello.rhtml +1 -0
- data/test/fixtures/layout_tests/layouts/multiple_extensions.html.erb +1 -0
- data/test/fixtures/layouts/{builder.rxml → builder.builder} +0 -0
- data/test/fixtures/layouts/{standard.rhtml → standard.erb} +0 -0
- data/test/fixtures/layouts/{talk_from_action.rhtml → talk_from_action.erb} +0 -0
- data/test/fixtures/layouts/{yield.rhtml → yield.erb} +0 -0
- data/test/fixtures/multipart/binary_file +0 -0
- data/test/fixtures/multipart/bracketed_param +5 -0
- data/test/fixtures/override/test/hello_world.erb +1 -0
- data/test/fixtures/override2/layouts/test/sub.erb +1 -0
- data/test/fixtures/post_test/layouts/post.html.erb +1 -0
- data/test/fixtures/post_test/layouts/super_post.iphone.erb +1 -0
- data/test/fixtures/post_test/post/index.html.erb +1 -0
- data/test/fixtures/post_test/post/index.iphone.erb +1 -0
- data/test/fixtures/post_test/super_post/index.html.erb +1 -0
- data/test/fixtures/post_test/super_post/index.iphone.erb +1 -0
- data/test/fixtures/public/404.html +1 -0
- data/test/fixtures/public/500.html +1 -0
- data/test/fixtures/public/javascripts/application.js +0 -1
- data/test/fixtures/public/javascripts/bank.js +1 -0
- data/test/fixtures/public/javascripts/robber.js +1 -0
- data/test/fixtures/public/stylesheets/bank.css +1 -0
- data/test/fixtures/public/stylesheets/robber.css +1 -0
- data/test/fixtures/replies.yml +2 -0
- data/test/fixtures/reply.rb +2 -1
- data/test/fixtures/respond_to/{all_types_with_layout.rhtml → all_types_with_layout.html.erb} +0 -0
- data/test/fixtures/respond_to/{all_types_with_layout.rjs → all_types_with_layout.js.rjs} +0 -0
- data/test/fixtures/respond_to/custom_constant_handling_without_block.mobile.erb +1 -0
- data/test/fixtures/respond_to/iphone_with_html_response_type.html.erb +1 -0
- data/test/fixtures/respond_to/iphone_with_html_response_type.iphone.erb +1 -0
- data/test/fixtures/respond_to/layouts/missing.html.erb +1 -0
- data/test/fixtures/respond_to/layouts/standard.html.erb +1 -0
- data/test/fixtures/respond_to/layouts/standard.iphone.erb +1 -0
- data/test/fixtures/respond_to/{using_defaults.rhtml → using_defaults.html.erb} +0 -0
- data/test/fixtures/respond_to/{using_defaults.rjs → using_defaults.js.rjs} +0 -0
- data/test/fixtures/respond_to/{using_defaults.rxml → using_defaults.xml.builder} +0 -0
- data/test/fixtures/respond_to/{using_defaults_with_type_list.rhtml → using_defaults_with_type_list.html.erb} +0 -0
- data/test/fixtures/respond_to/{using_defaults_with_type_list.rjs → using_defaults_with_type_list.js.rjs} +0 -0
- data/test/fixtures/respond_to/{using_defaults_with_type_list.rxml → using_defaults_with_type_list.xml.builder} +0 -0
- data/test/fixtures/scope/test/{modgreet.rhtml → modgreet.erb} +0 -0
- data/test/fixtures/test/{_customer.rhtml → _customer.erb} +0 -0
- data/test/fixtures/test/{_customer_greeting.rhtml → _customer_greeting.erb} +0 -0
- data/test/fixtures/test/_hash_greeting.erb +1 -0
- data/test/fixtures/test/_hash_object.erb +2 -0
- data/test/fixtures/test/{_hello.rxml → _hello.builder} +0 -0
- data/test/fixtures/test/_layout_for_partial.html.erb +3 -0
- data/test/fixtures/test/_partial.erb +1 -0
- data/test/fixtures/test/_partial.html.erb +1 -0
- data/test/fixtures/test/_partial.js.erb +1 -0
- data/test/fixtures/test/_partial_for_use_in_layout.html.erb +1 -0
- data/test/fixtures/test/{_partial_only.rhtml → _partial_only.erb} +0 -0
- data/test/fixtures/test/{_person.rhtml → _person.erb} +0 -0
- data/test/fixtures/test/{action_talk_to_layout.rhtml → action_talk_to_layout.erb} +0 -0
- data/test/fixtures/test/{block_content_for.rhtml → block_content_for.erb} +0 -0
- data/test/fixtures/test/calling_partial_with_layout.html.erb +1 -0
- data/test/fixtures/test/{capturing.rhtml → capturing.erb} +0 -0
- data/test/fixtures/test/{content_for.rhtml → content_for.erb} +0 -0
- data/test/fixtures/test/content_for_concatenated.erb +3 -0
- data/test/fixtures/test/content_for_with_parameter.erb +2 -0
- data/test/fixtures/test/dot.directory/{render_file_with_ivar.rhtml → render_file_with_ivar.erb} +0 -0
- data/test/fixtures/test/{erb_content_for.rhtml → erb_content_for.erb} +0 -0
- data/test/fixtures/test/formatted_html_erb.html.erb +1 -0
- data/test/fixtures/test/formatted_xml_erb.builder +1 -0
- data/test/fixtures/test/formatted_xml_erb.html.erb +1 -0
- data/test/fixtures/test/formatted_xml_erb.xml.erb +1 -0
- data/test/fixtures/test/{greeting.rhtml → greeting.erb} +0 -0
- data/test/fixtures/test/{hello.rxml → hello.builder} +0 -0
- data/test/fixtures/test/{hello_world.rxml → hello_world.builder} +0 -0
- data/test/fixtures/test/{hello_world.rhtml → hello_world.erb} +0 -0
- data/test/fixtures/test/{hello_world_container.rxml → hello_world_container.builder} +0 -0
- data/test/fixtures/test/{hello_world_with_layout_false.rhtml → hello_world_with_layout_false.erb} +0 -0
- data/test/fixtures/test/{hello_xml_world.rxml → hello_xml_world.builder} +0 -0
- data/test/fixtures/test/list.erb +1 -0
- data/test/fixtures/test/{non_erb_block_content_for.rxml → non_erb_block_content_for.builder} +0 -0
- data/test/fixtures/test/{potential_conflicts.rhtml → potential_conflicts.erb} +0 -0
- data/test/fixtures/test/{render_file_with_ivar.rhtml → render_file_with_ivar.erb} +0 -0
- data/test/fixtures/test/{render_file_with_locals.rhtml → render_file_with_locals.erb} +0 -0
- data/test/fixtures/test/{render_to_string_test.rhtml → render_to_string_test.erb} +0 -0
- data/test/fixtures/test/{update_element_with_capture.rhtml → update_element_with_capture.erb} +0 -0
- data/test/fixtures/test/using_layout_around_block.html.erb +1 -0
- data/test/fixtures/topic.rb +1 -1
- data/test/template/active_record_helper_test.rb +67 -20
- data/test/template/asset_tag_helper_test.rb +222 -54
- data/test/template/atom_feed_helper_test.rb +101 -0
- data/test/template/benchmark_helper_test.rb +2 -2
- data/test/template/compiled_templates_test.rb +76 -32
- data/test/template/date_helper_test.rb +125 -9
- data/test/template/form_helper_test.rb +326 -33
- data/test/template/form_options_helper_test.rb +822 -15
- data/test/template/form_tag_helper_test.rb +96 -30
- data/test/template/javascript_helper_test.rb +61 -13
- data/test/template/number_helper_test.rb +12 -11
- data/test/template/prototype_helper_test.rb +185 -24
- data/test/template/sanitize_helper_test.rb +49 -0
- data/test/template/scriptaculous_helper_test.rb +9 -3
- data/test/template/tag_helper_test.rb +13 -2
- data/test/template/text_helper_test.rb +38 -52
- data/test/template/url_helper_test.rb +216 -46
- metadata +144 -116
- data/examples/.htaccess +0 -24
- data/examples/address_book/index.rhtml +0 -33
- data/examples/address_book/layout.rhtml +0 -8
- data/examples/address_book_controller.cgi +0 -9
- data/examples/address_book_controller.fcgi +0 -6
- data/examples/address_book_controller.rb +0 -52
- data/examples/address_book_controller.rbx +0 -4
- data/examples/benchmark.rb +0 -52
- data/examples/benchmark_with_ar.fcgi +0 -89
- data/examples/blog_controller.cgi +0 -53
- data/examples/debate/index.rhtml +0 -14
- data/examples/debate/new_topic.rhtml +0 -22
- data/examples/debate/topic.rhtml +0 -32
- data/examples/debate_controller.cgi +0 -57
- data/lib/action_controller/assertions/deprecated_assertions.rb +0 -228
- data/lib/action_controller/cgi_ext/cgi_ext.rb +0 -36
- data/lib/action_controller/cgi_ext/cgi_methods.rb +0 -211
- data/lib/action_controller/cgi_ext/pstore_performance_fix.rb +0 -30
- data/lib/action_controller/cgi_ext/raw_post_data_fix.rb +0 -95
- data/lib/action_controller/cgi_ext/session_performance_fix.rb +0 -30
- data/lib/action_controller/deprecated_dependencies.rb +0 -65
- data/lib/action_controller/deprecated_redirects.rb +0 -17
- data/lib/action_controller/deprecated_request_methods.rb +0 -34
- data/lib/action_controller/macros/auto_complete.rb +0 -53
- data/lib/action_controller/macros/in_place_editing.rb +0 -33
- data/lib/action_controller/pagination.rb +0 -408
- data/lib/action_controller/scaffolding.rb +0 -189
- data/lib/action_controller/templates/rescues/_request_and_response.rhtml +0 -44
- data/lib/action_controller/templates/scaffolds/edit.rhtml +0 -7
- data/lib/action_controller/templates/scaffolds/layout.rhtml +0 -69
- data/lib/action_controller/templates/scaffolds/list.rhtml +0 -27
- data/lib/action_controller/templates/scaffolds/new.rhtml +0 -6
- data/lib/action_controller/templates/scaffolds/show.rhtml +0 -9
- data/lib/action_controller/vendor/xml_node.rb +0 -97
- data/lib/action_view/helpers/deprecated_helper.rb +0 -37
- data/lib/action_view/helpers/java_script_macros_helper.rb +0 -233
- data/lib/action_view/helpers/pagination_helper.rb +0 -86
- data/test/activerecord/active_record_assertions_test.rb +0 -92
- data/test/activerecord/pagination_test.rb +0 -165
- data/test/controller/deprecated_instance_variables_test.rb +0 -48
- data/test/controller/raw_post_test.rb +0 -68
- data/test/fixtures/deprecated_instance_variables/_cookies_ivar.rhtml +0 -1
- data/test/fixtures/deprecated_instance_variables/_cookies_method.rhtml +0 -1
- data/test/fixtures/deprecated_instance_variables/_flash_ivar.rhtml +0 -1
- data/test/fixtures/deprecated_instance_variables/_flash_method.rhtml +0 -1
- data/test/fixtures/deprecated_instance_variables/_headers_ivar.rhtml +0 -1
- data/test/fixtures/deprecated_instance_variables/_headers_method.rhtml +0 -1
- data/test/fixtures/deprecated_instance_variables/_params_ivar.rhtml +0 -1
- data/test/fixtures/deprecated_instance_variables/_params_method.rhtml +0 -1
- data/test/fixtures/deprecated_instance_variables/_request_ivar.rhtml +0 -1
- data/test/fixtures/deprecated_instance_variables/_request_method.rhtml +0 -1
- data/test/fixtures/deprecated_instance_variables/_response_ivar.rhtml +0 -1
- data/test/fixtures/deprecated_instance_variables/_response_method.rhtml +0 -1
- data/test/fixtures/deprecated_instance_variables/_session_ivar.rhtml +0 -1
- data/test/fixtures/deprecated_instance_variables/_session_method.rhtml +0 -1
- data/test/fixtures/respond_to/layouts/standard.rhtml +0 -1
- data/test/fixtures/test/_hash_object.rhtml +0 -1
- data/test/fixtures/test/list.rhtml +0 -1
- data/test/template/deprecated_helper_test.rb +0 -36
- data/test/template/deprecated_instance_variables_test.rb +0 -43
- 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
|