actionpack-rack-upgrade-2 2.3.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +5250 -0
- data/MIT-LICENSE +21 -0
- data/README +409 -0
- data/RUNNING_UNIT_TESTS +24 -0
- data/Rakefile +158 -0
- data/install.rb +30 -0
- data/lib/action_controller.rb +113 -0
- data/lib/action_controller/assertions/dom_assertions.rb +55 -0
- data/lib/action_controller/assertions/model_assertions.rb +21 -0
- data/lib/action_controller/assertions/response_assertions.rb +169 -0
- data/lib/action_controller/assertions/routing_assertions.rb +146 -0
- data/lib/action_controller/assertions/selector_assertions.rb +638 -0
- data/lib/action_controller/assertions/tag_assertions.rb +127 -0
- data/lib/action_controller/base.rb +1425 -0
- data/lib/action_controller/benchmarking.rb +107 -0
- data/lib/action_controller/caching.rb +71 -0
- data/lib/action_controller/caching/actions.rb +177 -0
- data/lib/action_controller/caching/fragments.rb +120 -0
- data/lib/action_controller/caching/pages.rb +152 -0
- data/lib/action_controller/caching/sweeper.rb +45 -0
- data/lib/action_controller/caching/sweeping.rb +55 -0
- data/lib/action_controller/cgi_ext.rb +15 -0
- data/lib/action_controller/cgi_ext/cookie.rb +112 -0
- data/lib/action_controller/cgi_ext/query_extension.rb +22 -0
- data/lib/action_controller/cgi_ext/stdinput.rb +24 -0
- data/lib/action_controller/cgi_process.rb +77 -0
- data/lib/action_controller/cookies.rb +197 -0
- data/lib/action_controller/dispatcher.rb +133 -0
- data/lib/action_controller/failsafe.rb +87 -0
- data/lib/action_controller/filters.rb +680 -0
- data/lib/action_controller/flash.rb +213 -0
- data/lib/action_controller/headers.rb +33 -0
- data/lib/action_controller/helpers.rb +225 -0
- data/lib/action_controller/http_authentication.rb +309 -0
- data/lib/action_controller/integration.rb +708 -0
- data/lib/action_controller/layout.rb +286 -0
- data/lib/action_controller/middleware_stack.rb +119 -0
- data/lib/action_controller/middlewares.rb +14 -0
- data/lib/action_controller/mime_responds.rb +193 -0
- data/lib/action_controller/mime_type.rb +212 -0
- data/lib/action_controller/mime_types.rb +21 -0
- data/lib/action_controller/params_parser.rb +77 -0
- data/lib/action_controller/performance_test.rb +15 -0
- data/lib/action_controller/polymorphic_routes.rb +189 -0
- data/lib/action_controller/rack_lint_patch.rb +36 -0
- data/lib/action_controller/record_identifier.rb +104 -0
- data/lib/action_controller/reloader.rb +54 -0
- data/lib/action_controller/request.rb +495 -0
- data/lib/action_controller/request_forgery_protection.rb +116 -0
- data/lib/action_controller/rescue.rb +183 -0
- data/lib/action_controller/resources.rb +682 -0
- data/lib/action_controller/response.rb +237 -0
- data/lib/action_controller/routing.rb +388 -0
- data/lib/action_controller/routing/builder.rb +197 -0
- data/lib/action_controller/routing/optimisations.rb +130 -0
- data/lib/action_controller/routing/recognition_optimisation.rb +167 -0
- data/lib/action_controller/routing/route.rb +265 -0
- data/lib/action_controller/routing/route_set.rb +503 -0
- data/lib/action_controller/routing/routing_ext.rb +49 -0
- data/lib/action_controller/routing/segments.rb +343 -0
- data/lib/action_controller/session/abstract_store.rb +276 -0
- data/lib/action_controller/session/cookie_store.rb +240 -0
- data/lib/action_controller/session/mem_cache_store.rb +60 -0
- data/lib/action_controller/session_management.rb +54 -0
- data/lib/action_controller/status_codes.rb +88 -0
- data/lib/action_controller/streaming.rb +181 -0
- data/lib/action_controller/string_coercion.rb +29 -0
- data/lib/action_controller/templates/rescues/_request_and_response.erb +24 -0
- data/lib/action_controller/templates/rescues/_trace.erb +26 -0
- data/lib/action_controller/templates/rescues/diagnostics.erb +11 -0
- data/lib/action_controller/templates/rescues/layout.erb +29 -0
- data/lib/action_controller/templates/rescues/missing_template.erb +2 -0
- data/lib/action_controller/templates/rescues/routing_error.erb +10 -0
- data/lib/action_controller/templates/rescues/template_error.erb +21 -0
- data/lib/action_controller/templates/rescues/unknown_action.erb +2 -0
- data/lib/action_controller/test_case.rb +209 -0
- data/lib/action_controller/test_process.rb +580 -0
- data/lib/action_controller/translation.rb +13 -0
- data/lib/action_controller/uploaded_file.rb +44 -0
- data/lib/action_controller/url_rewriter.rb +229 -0
- data/lib/action_controller/vendor/html-scanner.rb +16 -0
- data/lib/action_controller/vendor/html-scanner/html/document.rb +68 -0
- data/lib/action_controller/vendor/html-scanner/html/node.rb +537 -0
- data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +173 -0
- data/lib/action_controller/vendor/html-scanner/html/selector.rb +828 -0
- data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +105 -0
- data/lib/action_controller/vendor/html-scanner/html/version.rb +11 -0
- data/lib/action_controller/verification.rb +130 -0
- data/lib/action_pack.rb +24 -0
- data/lib/action_pack/version.rb +9 -0
- data/lib/action_view.rb +58 -0
- data/lib/action_view/base.rb +362 -0
- data/lib/action_view/helpers.rb +61 -0
- data/lib/action_view/helpers/active_record_helper.rb +305 -0
- data/lib/action_view/helpers/asset_tag_helper.rb +695 -0
- data/lib/action_view/helpers/atom_feed_helper.rb +198 -0
- data/lib/action_view/helpers/benchmark_helper.rb +54 -0
- data/lib/action_view/helpers/cache_helper.rb +39 -0
- data/lib/action_view/helpers/capture_helper.rb +136 -0
- data/lib/action_view/helpers/csrf_helper.rb +14 -0
- data/lib/action_view/helpers/date_helper.rb +989 -0
- data/lib/action_view/helpers/debug_helper.rb +38 -0
- data/lib/action_view/helpers/form_helper.rb +1118 -0
- data/lib/action_view/helpers/form_options_helper.rb +599 -0
- data/lib/action_view/helpers/form_tag_helper.rb +490 -0
- data/lib/action_view/helpers/javascript_helper.rb +208 -0
- data/lib/action_view/helpers/number_helper.rb +308 -0
- data/lib/action_view/helpers/prototype_helper.rb +1305 -0
- data/lib/action_view/helpers/raw_output_helper.rb +9 -0
- data/lib/action_view/helpers/record_identification_helper.rb +20 -0
- data/lib/action_view/helpers/record_tag_helper.rb +58 -0
- data/lib/action_view/helpers/sanitize_helper.rb +251 -0
- data/lib/action_view/helpers/scriptaculous_helper.rb +226 -0
- data/lib/action_view/helpers/tag_helper.rb +151 -0
- data/lib/action_view/helpers/text_helper.rb +597 -0
- data/lib/action_view/helpers/translation_helper.rb +67 -0
- data/lib/action_view/helpers/url_helper.rb +637 -0
- data/lib/action_view/inline_template.rb +19 -0
- data/lib/action_view/locale/en.yml +117 -0
- data/lib/action_view/partials.rb +241 -0
- data/lib/action_view/paths.rb +77 -0
- data/lib/action_view/reloadable_template.rb +117 -0
- data/lib/action_view/renderable.rb +109 -0
- data/lib/action_view/renderable_partial.rb +53 -0
- data/lib/action_view/template.rb +252 -0
- data/lib/action_view/template_error.rb +99 -0
- data/lib/action_view/template_handler.rb +34 -0
- data/lib/action_view/template_handlers.rb +48 -0
- data/lib/action_view/template_handlers/builder.rb +17 -0
- data/lib/action_view/template_handlers/erb.rb +25 -0
- data/lib/action_view/template_handlers/rjs.rb +13 -0
- data/lib/action_view/test_case.rb +162 -0
- data/lib/actionpack.rb +2 -0
- data/test/abstract_unit.rb +78 -0
- data/test/active_record_unit.rb +104 -0
- data/test/activerecord/active_record_store_test.rb +221 -0
- data/test/activerecord/render_partial_with_record_identification_test.rb +188 -0
- data/test/adv_attr_test.rb +20 -0
- data/test/controller/action_pack_assertions_test.rb +545 -0
- data/test/controller/addresses_render_test.rb +37 -0
- data/test/controller/assert_select_test.rb +735 -0
- data/test/controller/base_test.rb +217 -0
- data/test/controller/benchmark_test.rb +32 -0
- data/test/controller/caching_test.rb +743 -0
- data/test/controller/capture_test.rb +66 -0
- data/test/controller/content_type_test.rb +178 -0
- data/test/controller/controller_fixtures/app/controllers/admin/user_controller.rb +0 -0
- data/test/controller/controller_fixtures/app/controllers/user_controller.rb +0 -0
- data/test/controller/controller_fixtures/vendor/plugins/bad_plugin/lib/plugin_controller.rb +0 -0
- data/test/controller/cookie_test.rb +208 -0
- data/test/controller/deprecation/deprecated_base_methods_test.rb +32 -0
- data/test/controller/dispatcher_test.rb +144 -0
- data/test/controller/dom_assertions_test.rb +53 -0
- data/test/controller/failsafe_test.rb +60 -0
- data/test/controller/fake_controllers.rb +33 -0
- data/test/controller/fake_models.rb +19 -0
- data/test/controller/filter_params_test.rb +52 -0
- data/test/controller/filters_test.rb +885 -0
- data/test/controller/flash_test.rb +174 -0
- data/test/controller/header_test.rb +14 -0
- data/test/controller/helper_test.rb +224 -0
- data/test/controller/html-scanner/cdata_node_test.rb +15 -0
- data/test/controller/html-scanner/document_test.rb +148 -0
- data/test/controller/html-scanner/node_test.rb +89 -0
- data/test/controller/html-scanner/sanitizer_test.rb +281 -0
- data/test/controller/html-scanner/tag_node_test.rb +238 -0
- data/test/controller/html-scanner/text_node_test.rb +50 -0
- data/test/controller/html-scanner/tokenizer_test.rb +131 -0
- data/test/controller/http_basic_authentication_test.rb +113 -0
- data/test/controller/http_digest_authentication_test.rb +254 -0
- data/test/controller/integration_test.rb +526 -0
- data/test/controller/layout_test.rb +215 -0
- data/test/controller/localized_templates_test.rb +24 -0
- data/test/controller/logging_test.rb +46 -0
- data/test/controller/middleware_stack_test.rb +90 -0
- data/test/controller/mime_responds_test.rb +536 -0
- data/test/controller/mime_type_test.rb +93 -0
- data/test/controller/output_escaping_test.rb +19 -0
- data/test/controller/polymorphic_routes_test.rb +297 -0
- data/test/controller/rack_test.rb +308 -0
- data/test/controller/record_identifier_test.rb +139 -0
- data/test/controller/redirect_test.rb +285 -0
- data/test/controller/reloader_test.rb +125 -0
- data/test/controller/render_test.rb +1783 -0
- data/test/controller/request/json_params_parsing_test.rb +65 -0
- data/test/controller/request/multipart_params_parsing_test.rb +177 -0
- data/test/controller/request/query_string_parsing_test.rb +120 -0
- data/test/controller/request/test_request_test.rb +35 -0
- data/test/controller/request/url_encoded_params_parsing_test.rb +146 -0
- data/test/controller/request/xml_params_parsing_test.rb +103 -0
- data/test/controller/request_forgery_protection_test.rb +233 -0
- data/test/controller/request_test.rb +398 -0
- data/test/controller/rescue_test.rb +541 -0
- data/test/controller/resources_test.rb +1393 -0
- data/test/controller/routing_test.rb +2592 -0
- data/test/controller/selector_test.rb +628 -0
- data/test/controller/send_file_test.rb +171 -0
- data/test/controller/session/abstract_store_test.rb +64 -0
- data/test/controller/session/cookie_store_test.rb +354 -0
- data/test/controller/session/mem_cache_store_test.rb +187 -0
- data/test/controller/session/test_session_test.rb +58 -0
- data/test/controller/test_test.rb +700 -0
- data/test/controller/translation_test.rb +26 -0
- data/test/controller/url_rewriter_test.rb +395 -0
- data/test/controller/verification_test.rb +270 -0
- data/test/controller/view_paths_test.rb +141 -0
- data/test/controller/webservice_test.rb +273 -0
- data/test/fixtures/_top_level_partial.html.erb +1 -0
- data/test/fixtures/_top_level_partial_only.erb +1 -0
- data/test/fixtures/addresses/list.erb +1 -0
- data/test/fixtures/alternate_helpers/foo_helper.rb +3 -0
- data/test/fixtures/bad_customers/_bad_customer.html.erb +1 -0
- data/test/fixtures/companies.yml +24 -0
- data/test/fixtures/company.rb +10 -0
- data/test/fixtures/content_type/render_default_content_types_for_respond_to.rhtml +1 -0
- data/test/fixtures/content_type/render_default_for_rhtml.rhtml +1 -0
- data/test/fixtures/content_type/render_default_for_rjs.rjs +1 -0
- data/test/fixtures/content_type/render_default_for_rxml.rxml +1 -0
- data/test/fixtures/customers/_customer.html.erb +1 -0
- data/test/fixtures/db_definitions/sqlite.sql +49 -0
- data/test/fixtures/developer.rb +9 -0
- data/test/fixtures/developers.yml +21 -0
- data/test/fixtures/developers/_developer.erb +1 -0
- data/test/fixtures/developers_projects.yml +13 -0
- data/test/fixtures/failsafe/500.html +1 -0
- data/test/fixtures/fun/games/_game.erb +1 -0
- data/test/fixtures/fun/games/hello_world.erb +1 -0
- data/test/fixtures/fun/serious/games/_game.erb +1 -0
- data/test/fixtures/functional_caching/_partial.erb +3 -0
- data/test/fixtures/functional_caching/formatted_fragment_cached.html.erb +3 -0
- data/test/fixtures/functional_caching/formatted_fragment_cached.js.rjs +6 -0
- data/test/fixtures/functional_caching/formatted_fragment_cached.xml.builder +5 -0
- data/test/fixtures/functional_caching/fragment_cached.html.erb +2 -0
- data/test/fixtures/functional_caching/html_fragment_cached_with_partial.html.erb +1 -0
- data/test/fixtures/functional_caching/inline_fragment_cached.html.erb +2 -0
- data/test/fixtures/functional_caching/js_fragment_cached_with_partial.js.rjs +1 -0
- data/test/fixtures/good_customers/_good_customer.html.erb +1 -0
- data/test/fixtures/helpers/abc_helper.rb +5 -0
- data/test/fixtures/helpers/fun/games_helper.rb +3 -0
- data/test/fixtures/helpers/fun/pdf_helper.rb +3 -0
- data/test/fixtures/layout_tests/abs_path_layout.rhtml +1 -0
- data/test/fixtures/layout_tests/alt/hello.rhtml +1 -0
- data/test/fixtures/layout_tests/alt/layouts/alt.rhtml +0 -0
- data/test/fixtures/layout_tests/layouts/controller_name_space/nested.rhtml +1 -0
- data/test/fixtures/layout_tests/layouts/item.rhtml +1 -0
- data/test/fixtures/layout_tests/layouts/layout_test.rhtml +1 -0
- data/test/fixtures/layout_tests/layouts/multiple_extensions.html.erb +1 -0
- data/test/fixtures/layout_tests/layouts/third_party_template_library.mab +1 -0
- data/test/fixtures/layout_tests/views/hello.rhtml +1 -0
- data/test/fixtures/layouts/_column.html.erb +2 -0
- data/test/fixtures/layouts/block_with_layout.erb +3 -0
- data/test/fixtures/layouts/builder.builder +3 -0
- data/test/fixtures/layouts/default_html.html.erb +1 -0
- data/test/fixtures/layouts/partial_with_layout.erb +3 -0
- data/test/fixtures/layouts/standard.erb +1 -0
- data/test/fixtures/layouts/talk_from_action.erb +2 -0
- data/test/fixtures/layouts/xhr.html.erb +2 -0
- data/test/fixtures/layouts/yield.erb +2 -0
- data/test/fixtures/localized/hello_world.de.html +1 -0
- data/test/fixtures/localized/hello_world.en.html +1 -0
- data/test/fixtures/mascot.rb +3 -0
- data/test/fixtures/mascots.yml +4 -0
- data/test/fixtures/mascots/_mascot.html.erb +1 -0
- data/test/fixtures/multipart/binary_file +0 -0
- data/test/fixtures/multipart/boundary_problem_file +10 -0
- data/test/fixtures/multipart/bracketed_param +5 -0
- data/test/fixtures/multipart/empty +10 -0
- data/test/fixtures/multipart/hello.txt +1 -0
- data/test/fixtures/multipart/large_text_file +10 -0
- data/test/fixtures/multipart/mixed_files +0 -0
- data/test/fixtures/multipart/mona_lisa.jpg +0 -0
- data/test/fixtures/multipart/none +9 -0
- data/test/fixtures/multipart/single_parameter +5 -0
- data/test/fixtures/multipart/text_file +10 -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/project.rb +3 -0
- data/test/fixtures/projects.yml +7 -0
- data/test/fixtures/projects/_project.erb +1 -0
- data/test/fixtures/public/404.html +1 -0
- data/test/fixtures/public/500.da.html +1 -0
- data/test/fixtures/public/500.html +1 -0
- data/test/fixtures/public/absolute/test.css +23 -0
- data/test/fixtures/public/absolute/test.js +63 -0
- data/test/fixtures/public/images/rails.png +0 -0
- data/test/fixtures/public/javascripts/application.js +1 -0
- data/test/fixtures/public/javascripts/bank.js +1 -0
- data/test/fixtures/public/javascripts/controls.js +1 -0
- data/test/fixtures/public/javascripts/dragdrop.js +1 -0
- data/test/fixtures/public/javascripts/effects.js +1 -0
- data/test/fixtures/public/javascripts/prototype.js +1 -0
- data/test/fixtures/public/javascripts/robber.js +1 -0
- data/test/fixtures/public/javascripts/subdir/subdir.js +1 -0
- data/test/fixtures/public/javascripts/version.1.0.js +1 -0
- data/test/fixtures/public/stylesheets/bank.css +1 -0
- data/test/fixtures/public/stylesheets/robber.css +1 -0
- data/test/fixtures/public/stylesheets/subdir/subdir.css +1 -0
- data/test/fixtures/public/stylesheets/version.1.0.css +1 -0
- data/test/fixtures/quiz/questions/_question.html.erb +1 -0
- data/test/fixtures/replies.yml +15 -0
- data/test/fixtures/replies/_reply.erb +1 -0
- data/test/fixtures/reply.rb +7 -0
- data/test/fixtures/respond_to/all_types_with_layout.html.erb +1 -0
- data/test/fixtures/respond_to/all_types_with_layout.js.rjs +1 -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.html.erb +1 -0
- data/test/fixtures/respond_to/using_defaults.js.rjs +1 -0
- data/test/fixtures/respond_to/using_defaults.xml.builder +1 -0
- data/test/fixtures/respond_to/using_defaults_with_type_list.html.erb +1 -0
- data/test/fixtures/respond_to/using_defaults_with_type_list.js.rjs +1 -0
- data/test/fixtures/respond_to/using_defaults_with_type_list.xml.builder +1 -0
- data/test/fixtures/scope/test/modgreet.erb +1 -0
- data/test/fixtures/session_autoload_test/session_autoload_test/foo.rb +10 -0
- data/test/fixtures/shared.html.erb +1 -0
- data/test/fixtures/symlink_parent/symlinked_layout.erb +5 -0
- data/test/fixtures/test/_counter.html.erb +1 -0
- data/test/fixtures/test/_customer.erb +1 -0
- data/test/fixtures/test/_customer_counter.erb +1 -0
- data/test/fixtures/test/_customer_counter_with_as.erb +1 -0
- data/test/fixtures/test/_customer_greeting.erb +1 -0
- data/test/fixtures/test/_customer_with_var.erb +1 -0
- data/test/fixtures/test/_form.erb +1 -0
- data/test/fixtures/test/_from_helper.erb +1 -0
- data/test/fixtures/test/_hash_greeting.erb +1 -0
- data/test/fixtures/test/_hash_object.erb +2 -0
- data/test/fixtures/test/_hello.builder +1 -0
- data/test/fixtures/test/_labelling_form.erb +1 -0
- data/test/fixtures/test/_layout_for_block_with_args.html.erb +3 -0
- data/test/fixtures/test/_layout_for_partial.html.erb +3 -0
- data/test/fixtures/test/_local_inspector.html.erb +1 -0
- data/test/fixtures/test/_one.html.erb +1 -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.erb +1 -0
- data/test/fixtures/test/_partial_with_only_html_version.html.erb +1 -0
- data/test/fixtures/test/_person.erb +2 -0
- data/test/fixtures/test/_raise.html.erb +1 -0
- data/test/fixtures/test/_two.html.erb +1 -0
- data/test/fixtures/test/_utf8_partial.html.erb +1 -0
- data/test/fixtures/test/_utf8_partial_magic.html.erb +2 -0
- data/test/fixtures/test/action_talk_to_layout.erb +2 -0
- data/test/fixtures/test/array_translation.erb +1 -0
- data/test/fixtures/test/calling_partial_with_layout.html.erb +1 -0
- data/test/fixtures/test/capturing.erb +4 -0
- data/test/fixtures/test/content_for.erb +2 -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/delete_with_js.rjs +2 -0
- data/test/fixtures/test/dont_pick_me +1 -0
- data/test/fixtures/test/dot.directory/render_file_with_ivar.erb +1 -0
- data/test/fixtures/test/enum_rjs_test.rjs +6 -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.erb +1 -0
- data/test/fixtures/test/greeting.js.rjs +1 -0
- data/test/fixtures/test/hello.builder +4 -0
- data/test/fixtures/test/hello_world.da.html.erb +1 -0
- data/test/fixtures/test/hello_world.erb +1 -0
- data/test/fixtures/test/hello_world.erb~ +1 -0
- data/test/fixtures/test/hello_world.pt-BR.html.erb +1 -0
- data/test/fixtures/test/hello_world_container.builder +3 -0
- data/test/fixtures/test/hello_world_from_rxml.builder +4 -0
- data/test/fixtures/test/hello_world_with_layout_false.erb +1 -0
- data/test/fixtures/test/hello_xml_world.builder +11 -0
- data/test/fixtures/test/hyphen-ated.erb +1 -0
- data/test/fixtures/test/implicit_content_type.atom.builder +2 -0
- data/test/fixtures/test/list.erb +1 -0
- data/test/fixtures/test/malformed/malformed.en.html.erb~ +1 -0
- data/test/fixtures/test/malformed/malformed.erb~ +1 -0
- data/test/fixtures/test/malformed/malformed.html.erb~ +1 -0
- data/test/fixtures/test/nested_layout.erb +3 -0
- data/test/fixtures/test/non_erb_block_content_for.builder +4 -0
- data/test/fixtures/test/potential_conflicts.erb +4 -0
- data/test/fixtures/test/render_explicit_html_template.js.rjs +1 -0
- data/test/fixtures/test/render_file_from_template.html.erb +1 -0
- data/test/fixtures/test/render_file_with_ivar.erb +1 -0
- data/test/fixtures/test/render_file_with_locals.erb +1 -0
- data/test/fixtures/test/render_implicit_html_template.js.rjs +1 -0
- data/test/fixtures/test/render_implicit_html_template_from_xhr_request.da.html.erb +1 -0
- data/test/fixtures/test/render_implicit_html_template_from_xhr_request.html.erb +1 -0
- data/test/fixtures/test/render_implicit_js_template_without_layout.js.erb +1 -0
- data/test/fixtures/test/render_to_string_test.erb +1 -0
- data/test/fixtures/test/scoped_array_translation.erb +1 -0
- data/test/fixtures/test/sub_template_raise.html.erb +1 -0
- data/test/fixtures/test/template.erb +1 -0
- data/test/fixtures/test/translation.erb +1 -0
- data/test/fixtures/test/update_element_with_capture.erb +9 -0
- data/test/fixtures/test/using_layout_around_block.html.erb +1 -0
- data/test/fixtures/test/using_layout_around_block_with_args.html.erb +1 -0
- data/test/fixtures/test/utf8.html.erb +4 -0
- data/test/fixtures/test/utf8_magic.html.erb +5 -0
- data/test/fixtures/test/utf8_magic_with_bare_partial.html.erb +5 -0
- data/test/fixtures/topic.rb +3 -0
- data/test/fixtures/topics.yml +22 -0
- data/test/fixtures/topics/_topic.html.erb +1 -0
- data/test/template/active_record_helper_i18n_test.rb +51 -0
- data/test/template/active_record_helper_test.rb +302 -0
- data/test/template/asset_tag_helper_test.rb +770 -0
- data/test/template/atom_feed_helper_test.rb +315 -0
- data/test/template/benchmark_helper_test.rb +86 -0
- data/test/template/compiled_templates_test.rb +204 -0
- data/test/template/date_helper_i18n_test.rb +121 -0
- data/test/template/date_helper_test.rb +2603 -0
- data/test/template/erb_util_test.rb +36 -0
- data/test/template/form_helper_test.rb +1447 -0
- data/test/template/form_options_helper_i18n_test.rb +27 -0
- data/test/template/form_options_helper_test.rb +811 -0
- data/test/template/form_tag_helper_test.rb +356 -0
- data/test/template/javascript_helper_test.rb +106 -0
- data/test/template/number_helper_i18n_test.rb +69 -0
- data/test/template/number_helper_test.rb +132 -0
- data/test/template/prototype_helper_test.rb +639 -0
- data/test/template/raw_output_helper_test.rb +21 -0
- data/test/template/record_tag_helper_test.rb +58 -0
- data/test/template/render_test.rb +329 -0
- data/test/template/sanitize_helper_test.rb +57 -0
- data/test/template/scriptaculous_helper_test.rb +90 -0
- data/test/template/tag_helper_test.rb +98 -0
- data/test/template/template_test.rb +32 -0
- data/test/template/test_test.rb +54 -0
- data/test/template/text_helper_test.rb +597 -0
- data/test/template/translation_helper_test.rb +95 -0
- data/test/template/url_helper_test.rb +641 -0
- data/test/testing_sandbox.rb +15 -0
- data/test/view/test_case_test.rb +176 -0
- metadata +519 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
class Object
|
|
2
|
+
def to_param
|
|
3
|
+
to_s
|
|
4
|
+
end
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
class TrueClass
|
|
8
|
+
def to_param
|
|
9
|
+
self
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
class FalseClass
|
|
14
|
+
def to_param
|
|
15
|
+
self
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
class NilClass
|
|
20
|
+
def to_param
|
|
21
|
+
self
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
class Regexp #:nodoc:
|
|
26
|
+
def number_of_captures
|
|
27
|
+
Regexp.new("|#{source}").match('').captures.length
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def multiline?
|
|
31
|
+
options & MULTILINE == MULTILINE
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
class << self
|
|
35
|
+
def optionalize(pattern)
|
|
36
|
+
case unoptionalize(pattern)
|
|
37
|
+
when /\A(.|\(.*\))\Z/ then "#{pattern}?"
|
|
38
|
+
else "(?:#{pattern})?"
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def unoptionalize(pattern)
|
|
43
|
+
[/\A\(\?:(.*)\)\?\Z/, /\A(.|\(.*\))\?\Z/].each do |regexp|
|
|
44
|
+
return $1 if regexp =~ pattern
|
|
45
|
+
end
|
|
46
|
+
return pattern
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
module ActionController
|
|
2
|
+
module Routing
|
|
3
|
+
class Segment #:nodoc:
|
|
4
|
+
RESERVED_PCHAR = ':@&=+$,;'
|
|
5
|
+
SAFE_PCHAR = "#{URI::REGEXP::PATTERN::UNRESERVED}#{RESERVED_PCHAR}"
|
|
6
|
+
if RUBY_VERSION >= '1.9'
|
|
7
|
+
UNSAFE_PCHAR = Regexp.new("[^#{SAFE_PCHAR}]", false).freeze
|
|
8
|
+
else
|
|
9
|
+
UNSAFE_PCHAR = Regexp.new("[^#{SAFE_PCHAR}]", false, 'N').freeze
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# TODO: Convert :is_optional accessor to read only
|
|
13
|
+
attr_accessor :is_optional
|
|
14
|
+
alias_method :optional?, :is_optional
|
|
15
|
+
|
|
16
|
+
def initialize
|
|
17
|
+
@is_optional = false
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def number_of_captures
|
|
21
|
+
Regexp.new(regexp_chunk).number_of_captures
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def extraction_code
|
|
25
|
+
nil
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Continue generating string for the prior segments.
|
|
29
|
+
def continue_string_structure(prior_segments)
|
|
30
|
+
if prior_segments.empty?
|
|
31
|
+
interpolation_statement(prior_segments)
|
|
32
|
+
else
|
|
33
|
+
new_priors = prior_segments[0..-2]
|
|
34
|
+
prior_segments.last.string_structure(new_priors)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def interpolation_chunk
|
|
39
|
+
URI.escape(value, UNSAFE_PCHAR)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Return a string interpolation statement for this segment and those before it.
|
|
43
|
+
def interpolation_statement(prior_segments)
|
|
44
|
+
chunks = prior_segments.collect { |s| s.interpolation_chunk }
|
|
45
|
+
chunks << interpolation_chunk
|
|
46
|
+
"\"#{chunks * ''}\"#{all_optionals_available_condition(prior_segments)}"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def string_structure(prior_segments)
|
|
50
|
+
optional? ? continue_string_structure(prior_segments) : interpolation_statement(prior_segments)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Return an if condition that is true if all the prior segments can be generated.
|
|
54
|
+
# If there are no optional segments before this one, then nil is returned.
|
|
55
|
+
def all_optionals_available_condition(prior_segments)
|
|
56
|
+
optional_locals = prior_segments.collect { |s| s.local_name if s.optional? && s.respond_to?(:local_name) }.compact
|
|
57
|
+
optional_locals.empty? ? nil : " if #{optional_locals * ' && '}"
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Recognition
|
|
61
|
+
|
|
62
|
+
def match_extraction(next_capture)
|
|
63
|
+
nil
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Warning
|
|
67
|
+
|
|
68
|
+
# Returns true if this segment is optional? because of a default. If so, then
|
|
69
|
+
# no warning will be emitted regarding this segment.
|
|
70
|
+
def optionality_implied?
|
|
71
|
+
false
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
class StaticSegment < Segment #:nodoc:
|
|
76
|
+
attr_reader :value, :raw
|
|
77
|
+
alias_method :raw?, :raw
|
|
78
|
+
|
|
79
|
+
def initialize(value = nil, options = {})
|
|
80
|
+
super()
|
|
81
|
+
@value = value
|
|
82
|
+
@raw = options[:raw] if options.key?(:raw)
|
|
83
|
+
@is_optional = options[:optional] if options.key?(:optional)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def interpolation_chunk
|
|
87
|
+
raw? ? value : super
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def regexp_chunk
|
|
91
|
+
chunk = Regexp.escape(value)
|
|
92
|
+
optional? ? Regexp.optionalize(chunk) : chunk
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def number_of_captures
|
|
96
|
+
0
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def build_pattern(pattern)
|
|
100
|
+
escaped = Regexp.escape(value)
|
|
101
|
+
if optional? && ! pattern.empty?
|
|
102
|
+
"(?:#{Regexp.optionalize escaped}\\Z|#{escaped}#{Regexp.unoptionalize pattern})"
|
|
103
|
+
elsif optional?
|
|
104
|
+
Regexp.optionalize escaped
|
|
105
|
+
else
|
|
106
|
+
escaped + pattern
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def to_s
|
|
111
|
+
value
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
class DividerSegment < StaticSegment #:nodoc:
|
|
116
|
+
def initialize(value = nil, options = {})
|
|
117
|
+
super(value, {:raw => true, :optional => true}.merge(options))
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def optionality_implied?
|
|
121
|
+
true
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
class DynamicSegment < Segment #:nodoc:
|
|
126
|
+
attr_reader :key
|
|
127
|
+
|
|
128
|
+
# TODO: Convert these accessors to read only
|
|
129
|
+
attr_accessor :default, :regexp
|
|
130
|
+
|
|
131
|
+
def initialize(key = nil, options = {})
|
|
132
|
+
super()
|
|
133
|
+
@key = key
|
|
134
|
+
@default = options[:default] if options.key?(:default)
|
|
135
|
+
@regexp = options[:regexp] if options.key?(:regexp)
|
|
136
|
+
@is_optional = true if options[:optional] || options.key?(:default)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def to_s
|
|
140
|
+
":#{key}"
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# The local variable name that the value of this segment will be extracted to.
|
|
144
|
+
def local_name
|
|
145
|
+
"#{key}_value"
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def extract_value
|
|
149
|
+
"#{local_name} = hash[:#{key}] && hash[:#{key}].to_param #{"|| #{default.inspect}" if default}"
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def value_check
|
|
153
|
+
if default # Then we know it won't be nil
|
|
154
|
+
"#{value_regexp.inspect} =~ #{local_name}" if regexp
|
|
155
|
+
elsif optional?
|
|
156
|
+
# If we have a regexp check that the value is not given, or that it matches.
|
|
157
|
+
# If we have no regexp, return nil since we do not require a condition.
|
|
158
|
+
"#{local_name}.nil? || #{value_regexp.inspect} =~ #{local_name}" if regexp
|
|
159
|
+
else # Then it must be present, and if we have a regexp, it must match too.
|
|
160
|
+
"#{local_name} #{"&& #{value_regexp.inspect} =~ #{local_name}" if regexp}"
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def expiry_statement
|
|
165
|
+
"expired, hash = true, options if !expired && expire_on[:#{key}]"
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def extraction_code
|
|
169
|
+
s = extract_value
|
|
170
|
+
vc = value_check
|
|
171
|
+
s << "\nreturn [nil,nil] unless #{vc}" if vc
|
|
172
|
+
s << "\n#{expiry_statement}"
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def interpolation_chunk(value_code = local_name)
|
|
176
|
+
"\#{URI.escape(#{value_code}.to_s, ActionController::Routing::Segment::UNSAFE_PCHAR)}"
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def string_structure(prior_segments)
|
|
180
|
+
if optional? # We have a conditional to do...
|
|
181
|
+
# If we should not appear in the url, just write the code for the prior
|
|
182
|
+
# segments. This occurs if our value is the default value, or, if we are
|
|
183
|
+
# optional, if we have nil as our value.
|
|
184
|
+
"if #{local_name} == #{default.inspect}\n" +
|
|
185
|
+
continue_string_structure(prior_segments) +
|
|
186
|
+
"\nelse\n" + # Otherwise, write the code up to here
|
|
187
|
+
"#{interpolation_statement(prior_segments)}\nend"
|
|
188
|
+
else
|
|
189
|
+
interpolation_statement(prior_segments)
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def value_regexp
|
|
194
|
+
Regexp.new "\\A#{regexp.to_s}\\Z" if regexp
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def regexp_chunk
|
|
198
|
+
regexp ? regexp_string : default_regexp_chunk
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def regexp_string
|
|
202
|
+
regexp_has_modifiers? ? "(#{regexp.to_s})" : "(#{regexp.source})"
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def default_regexp_chunk
|
|
206
|
+
"([^#{Routing::SEPARATORS.join}]+)"
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def number_of_captures
|
|
210
|
+
regexp ? regexp.number_of_captures + 1 : 1
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def build_pattern(pattern)
|
|
214
|
+
pattern = "#{regexp_chunk}#{pattern}"
|
|
215
|
+
optional? ? Regexp.optionalize(pattern) : pattern
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def match_extraction(next_capture)
|
|
219
|
+
# All non code-related keys (such as :id, :slug) are URI-unescaped as
|
|
220
|
+
# path parameters.
|
|
221
|
+
default_value = default ? default.inspect : nil
|
|
222
|
+
%[
|
|
223
|
+
value = if (m = match[#{next_capture}])
|
|
224
|
+
URI.unescape(m)
|
|
225
|
+
else
|
|
226
|
+
#{default_value}
|
|
227
|
+
end
|
|
228
|
+
params[:#{key}] = value if value
|
|
229
|
+
]
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
def optionality_implied?
|
|
233
|
+
[:action, :id].include? key
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def regexp_has_modifiers?
|
|
237
|
+
regexp.options & (Regexp::IGNORECASE | Regexp::EXTENDED) != 0
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
class ControllerSegment < DynamicSegment #:nodoc:
|
|
242
|
+
def regexp_chunk
|
|
243
|
+
possible_names = Routing.possible_controllers.collect { |name| Regexp.escape name }
|
|
244
|
+
"(?i-:(#{(regexp || Regexp.union(*possible_names)).source}))"
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
# Don't URI.escape the controller name since it may contain slashes.
|
|
248
|
+
def interpolation_chunk(value_code = local_name)
|
|
249
|
+
"\#{#{value_code}.to_s}"
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
# Make sure controller names like Admin/Content are correctly normalized to
|
|
253
|
+
# admin/content
|
|
254
|
+
def extract_value
|
|
255
|
+
"#{local_name} = (hash[:#{key}] #{"|| #{default.inspect}" if default}).downcase"
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def match_extraction(next_capture)
|
|
259
|
+
if default
|
|
260
|
+
"params[:#{key}] = match[#{next_capture}] ? match[#{next_capture}].downcase : '#{default}'"
|
|
261
|
+
else
|
|
262
|
+
"params[:#{key}] = match[#{next_capture}].downcase if match[#{next_capture}]"
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
class PathSegment < DynamicSegment #:nodoc:
|
|
268
|
+
def interpolation_chunk(value_code = local_name)
|
|
269
|
+
"\#{#{value_code}}"
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
def extract_value
|
|
273
|
+
"#{local_name} = hash[:#{key}] && Array(hash[:#{key}]).collect { |path_component| URI.escape(path_component.to_param, ActionController::Routing::Segment::UNSAFE_PCHAR) }.to_param #{"|| #{default.inspect}" if default}"
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
def default
|
|
277
|
+
''
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
def default=(path)
|
|
281
|
+
raise RoutingError, "paths cannot have non-empty default values" unless path.blank?
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
def match_extraction(next_capture)
|
|
285
|
+
"params[:#{key}] = PathSegment::Result.new_escaped((match[#{next_capture}]#{" || " + default.inspect if default}).split('/'))#{" if match[" + next_capture + "]" if !default}"
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
def default_regexp_chunk
|
|
289
|
+
"(.*)"
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
def number_of_captures
|
|
293
|
+
regexp ? regexp.number_of_captures : 1
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
def optionality_implied?
|
|
297
|
+
true
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
class Result < ::Array #:nodoc:
|
|
301
|
+
def to_s() join '/' end
|
|
302
|
+
def self.new_escaped(strings)
|
|
303
|
+
new strings.collect {|str| URI.unescape str}
|
|
304
|
+
end
|
|
305
|
+
end
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
# The OptionalFormatSegment allows for any resource route to have an optional
|
|
309
|
+
# :format, which decreases the amount of routes created by 50%.
|
|
310
|
+
class OptionalFormatSegment < DynamicSegment
|
|
311
|
+
|
|
312
|
+
def initialize(key = nil, options = {})
|
|
313
|
+
super(:format, {:optional => true}.merge(options))
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
def interpolation_chunk
|
|
317
|
+
"." + super
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
def regexp_chunk
|
|
321
|
+
'/|(\.[^/?\.]+)?'
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
def to_s
|
|
325
|
+
'(.:format)?'
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
def extract_value
|
|
329
|
+
"#{local_name} = options[:#{key}] && options[:#{key}].to_s.downcase"
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
#the value should not include the period (.)
|
|
333
|
+
def match_extraction(next_capture)
|
|
334
|
+
%[
|
|
335
|
+
if (m = match[#{next_capture}])
|
|
336
|
+
params[:#{key}] = URI.unescape(m.from(1))
|
|
337
|
+
end
|
|
338
|
+
]
|
|
339
|
+
end
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
end
|
|
343
|
+
end
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
require 'rack/utils'
|
|
2
|
+
|
|
3
|
+
module ActionController
|
|
4
|
+
module Session
|
|
5
|
+
class AbstractStore
|
|
6
|
+
ENV_SESSION_KEY = 'rack.session'.freeze
|
|
7
|
+
ENV_SESSION_OPTIONS_KEY = 'rack.session.options'.freeze
|
|
8
|
+
|
|
9
|
+
HTTP_COOKIE = 'HTTP_COOKIE'.freeze
|
|
10
|
+
SET_COOKIE = 'Set-Cookie'.freeze
|
|
11
|
+
|
|
12
|
+
# thin wrapper around Hash that allows us to lazily
|
|
13
|
+
# load session id into session_options
|
|
14
|
+
class OptionsHash < Hash
|
|
15
|
+
def initialize(by, env, default_options)
|
|
16
|
+
@by = by
|
|
17
|
+
@env = env
|
|
18
|
+
@session_id_loaded = false
|
|
19
|
+
merge!(default_options)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def [](key)
|
|
23
|
+
if key == :id
|
|
24
|
+
load_session_id! unless super(:id) || has_session_id?
|
|
25
|
+
end
|
|
26
|
+
super(key)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def has_session_id?
|
|
32
|
+
@session_id_loaded
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def load_session_id!
|
|
36
|
+
self[:id] = @by.send(:extract_session_id, @env)
|
|
37
|
+
@session_id_loaded = true
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
class SessionHash < Hash
|
|
42
|
+
def initialize(by, env)
|
|
43
|
+
super()
|
|
44
|
+
@by = by
|
|
45
|
+
@env = env
|
|
46
|
+
@loaded = false
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def session_id
|
|
50
|
+
ActiveSupport::Deprecation.warn(
|
|
51
|
+
"ActionController::Session::AbstractStore::SessionHash#session_id " +
|
|
52
|
+
"has been deprecated. Please use request.session_options[:id] instead.", caller)
|
|
53
|
+
@env[ENV_SESSION_OPTIONS_KEY][:id]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def [](key)
|
|
57
|
+
load_for_read!
|
|
58
|
+
super
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def has_key?(key)
|
|
62
|
+
load_for_read!
|
|
63
|
+
super
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def []=(key, value)
|
|
67
|
+
load_for_write!
|
|
68
|
+
super
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def clear
|
|
72
|
+
load_for_write!
|
|
73
|
+
super
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def to_hash
|
|
77
|
+
load_for_read!
|
|
78
|
+
h = {}.replace(self)
|
|
79
|
+
h.delete_if { |k,v| v.nil? }
|
|
80
|
+
h
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def update(hash)
|
|
84
|
+
load_for_write!
|
|
85
|
+
super
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def delete(key)
|
|
89
|
+
load_for_write!
|
|
90
|
+
super
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def data
|
|
94
|
+
ActiveSupport::Deprecation.warn(
|
|
95
|
+
"ActionController::Session::AbstractStore::SessionHash#data " +
|
|
96
|
+
"has been deprecated. Please use #to_hash instead.", caller)
|
|
97
|
+
to_hash
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def inspect
|
|
101
|
+
load_for_read!
|
|
102
|
+
super
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def exists?
|
|
106
|
+
return @exists if instance_variable_defined?(:@exists)
|
|
107
|
+
@exists = @by.send(:exists?, @env)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def loaded?
|
|
111
|
+
@loaded
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def destroy
|
|
115
|
+
clear
|
|
116
|
+
@by.send(:destroy, @env) if @by
|
|
117
|
+
@env[ENV_SESSION_OPTIONS_KEY][:id] = nil if @env && @env[ENV_SESSION_OPTIONS_KEY]
|
|
118
|
+
@loaded = false
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
private
|
|
122
|
+
|
|
123
|
+
def load_for_read!
|
|
124
|
+
load! if !loaded? && exists?
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def load_for_write!
|
|
128
|
+
load! unless loaded?
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def load!
|
|
132
|
+
id, session = @by.send(:load_session, @env)
|
|
133
|
+
@env[ENV_SESSION_OPTIONS_KEY][:id] = id
|
|
134
|
+
replace(session)
|
|
135
|
+
@loaded = true
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
DEFAULT_OPTIONS = {
|
|
141
|
+
:key => '_session_id',
|
|
142
|
+
:path => '/',
|
|
143
|
+
:domain => nil,
|
|
144
|
+
:expire_after => nil,
|
|
145
|
+
:secure => false,
|
|
146
|
+
:httponly => true,
|
|
147
|
+
:cookie_only => true
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
def initialize(app, options = {})
|
|
151
|
+
# Process legacy CGI options
|
|
152
|
+
options = options.symbolize_keys
|
|
153
|
+
if options.has_key?(:session_path)
|
|
154
|
+
ActiveSupport::Deprecation.warn "Giving :session_path to SessionStore is deprecated, " <<
|
|
155
|
+
"please use :path instead", caller
|
|
156
|
+
options[:path] = options.delete(:session_path)
|
|
157
|
+
end
|
|
158
|
+
if options.has_key?(:session_key)
|
|
159
|
+
ActiveSupport::Deprecation.warn "Giving :session_key to SessionStore is deprecated, " <<
|
|
160
|
+
"please use :key instead", caller
|
|
161
|
+
options[:key] = options.delete(:session_key)
|
|
162
|
+
end
|
|
163
|
+
if options.has_key?(:session_http_only)
|
|
164
|
+
ActiveSupport::Deprecation.warn "Giving :session_http_only to SessionStore is deprecated, " <<
|
|
165
|
+
"please use :httponly instead", caller
|
|
166
|
+
options[:httponly] = options.delete(:session_http_only)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
@app = app
|
|
170
|
+
@default_options = DEFAULT_OPTIONS.merge(options)
|
|
171
|
+
@key = @default_options[:key]
|
|
172
|
+
@cookie_only = @default_options[:cookie_only]
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def call(env)
|
|
176
|
+
prepare!(env)
|
|
177
|
+
response = @app.call(env)
|
|
178
|
+
|
|
179
|
+
session_data = env[ENV_SESSION_KEY]
|
|
180
|
+
options = env[ENV_SESSION_OPTIONS_KEY]
|
|
181
|
+
|
|
182
|
+
if !session_data.is_a?(AbstractStore::SessionHash) || session_data.loaded? || options[:expire_after]
|
|
183
|
+
request = ActionController::Request.new(env)
|
|
184
|
+
|
|
185
|
+
return response if (options[:secure] && !request.ssl?)
|
|
186
|
+
|
|
187
|
+
session_data.send(:load!) if session_data.is_a?(AbstractStore::SessionHash) && !session_data.loaded?
|
|
188
|
+
|
|
189
|
+
sid = options[:id] || generate_sid
|
|
190
|
+
|
|
191
|
+
unless set_session(env, sid, session_data.to_hash)
|
|
192
|
+
return response
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
request_cookies = env["rack.request.cookie_hash"]
|
|
196
|
+
|
|
197
|
+
if (request_cookies.nil? || request_cookies[@key] != sid) || options[:expire_after]
|
|
198
|
+
cookie = {:value => sid}
|
|
199
|
+
cookie[:expires] = Time.now + options[:expire_after] if options[:expire_after]
|
|
200
|
+
Rack::Utils.set_cookie_header!(response[1], @key, cookie.merge(options))
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
response
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
private
|
|
208
|
+
|
|
209
|
+
def prepare!(env)
|
|
210
|
+
env[ENV_SESSION_KEY] = SessionHash.new(self, env)
|
|
211
|
+
env[ENV_SESSION_OPTIONS_KEY] = OptionsHash.new(self, env, @default_options)
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def generate_sid
|
|
215
|
+
ActiveSupport::SecureRandom.hex(16)
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def load_session(env)
|
|
219
|
+
stale_session_check! do
|
|
220
|
+
sid = current_session_id(env)
|
|
221
|
+
sid, session = get_session(env, sid)
|
|
222
|
+
[sid, session]
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
def extract_session_id(env)
|
|
227
|
+
stale_session_check! do
|
|
228
|
+
request = Rack::Request.new(env)
|
|
229
|
+
sid = request.cookies[@key]
|
|
230
|
+
sid ||= request.params[@key] unless @cookie_only
|
|
231
|
+
sid
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def current_session_id(env)
|
|
236
|
+
env[ENV_SESSION_OPTIONS_KEY][:id]
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
def exists?(env)
|
|
240
|
+
current_session_id(env).present?
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
def get_session(env, sid)
|
|
244
|
+
raise '#get_session needs to be implemented.'
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def set_session(env, sid, session_data)
|
|
248
|
+
raise '#set_session needs to be implemented.'
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
def destroy(env)
|
|
252
|
+
raise '#destroy needs to be implemented.'
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
module SessionUtils
|
|
256
|
+
private
|
|
257
|
+
def stale_session_check!
|
|
258
|
+
yield
|
|
259
|
+
rescue ArgumentError => argument_error
|
|
260
|
+
if argument_error.message =~ %r{undefined class/module ([\w:]*\w)}
|
|
261
|
+
begin
|
|
262
|
+
# Note that the regexp does not allow $1 to end with a ':'
|
|
263
|
+
$1.constantize
|
|
264
|
+
rescue LoadError, NameError => const_error
|
|
265
|
+
raise ActionController::SessionRestoreError, "Session contains objects whose class definition isn\\'t available.\nRemember to require the classes for all objects kept in the session.\n(Original exception: \#{const_error.message} [\#{const_error.class}])\n"
|
|
266
|
+
end
|
|
267
|
+
retry
|
|
268
|
+
else
|
|
269
|
+
raise
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
include SessionUtils
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
end
|