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,6 +1,6 @@
|
|
1
1
|
require 'cgi'
|
2
2
|
require 'erb'
|
3
|
-
require
|
3
|
+
require 'action_view/helpers/form_helper'
|
4
4
|
|
5
5
|
module ActionView
|
6
6
|
module Helpers
|
@@ -10,7 +10,9 @@ module ActionView
|
|
10
10
|
# and <tt>time_zone_select</tt> methods take an <tt>options</tt> parameter,
|
11
11
|
# a hash.
|
12
12
|
#
|
13
|
-
# * <tt>:include_blank</tt> - set to true if the first option element of the select element is a blank. Useful if there is not a default value required for the select element.
|
13
|
+
# * <tt>:include_blank</tt> - set to true or a prompt string if the first option element of the select element is a blank. Useful if there is not a default value required for the select element.
|
14
|
+
#
|
15
|
+
# For example,
|
14
16
|
#
|
15
17
|
# select("post", "category", Post::CATEGORIES, {:include_blank => true})
|
16
18
|
#
|
@@ -22,15 +24,31 @@ module ActionView
|
|
22
24
|
# <option>poem</option>
|
23
25
|
# </select>
|
24
26
|
#
|
27
|
+
# Another common case is a select tag for an <tt>belongs_to</tt>-associated object.
|
28
|
+
#
|
29
|
+
# Example with @post.person_id => 2:
|
30
|
+
#
|
31
|
+
# select("post", "person_id", Person.find(:all).collect {|p| [ p.name, p.id ] }, {:include_blank => 'None'})
|
32
|
+
#
|
33
|
+
# could become:
|
34
|
+
#
|
35
|
+
# <select name="post[person_id]">
|
36
|
+
# <option value="">None</option>
|
37
|
+
# <option value="1">David</option>
|
38
|
+
# <option value="2" selected="selected">Sam</option>
|
39
|
+
# <option value="3">Tobias</option>
|
40
|
+
# </select>
|
41
|
+
#
|
25
42
|
# * <tt>:prompt</tt> - set to true or a prompt string. When the select element doesn't have a value yet, this prepends an option with a generic prompt -- "Please select" -- or the given prompt string.
|
26
43
|
#
|
27
|
-
#
|
44
|
+
# Example:
|
28
45
|
#
|
29
|
-
# select("post", "person_id", Person.find(:all).collect {|p| [ p.name, p.id ] })
|
46
|
+
# select("post", "person_id", Person.find(:all).collect {|p| [ p.name, p.id ] }, {:prompt => 'Select Person'})
|
30
47
|
#
|
31
48
|
# could become:
|
32
49
|
#
|
33
50
|
# <select name="post[person_id]">
|
51
|
+
# <option value="">Select Person</option>
|
34
52
|
# <option value="1">David</option>
|
35
53
|
# <option value="2">Sam</option>
|
36
54
|
# <option value="3">Tobias</option>
|
@@ -48,7 +66,7 @@ module ActionView
|
|
48
66
|
# could become:
|
49
67
|
#
|
50
68
|
# <select name="post[person_id]">
|
51
|
-
# <option></option>
|
69
|
+
# <option value=""></option>
|
52
70
|
# <option value="1" selected="selected">David</option>
|
53
71
|
# <option value="2">Sam</option>
|
54
72
|
# <option value="3">Tobias</option>
|
@@ -66,7 +84,36 @@ module ActionView
|
|
66
84
|
InstanceTag.new(object, method, self, nil, options.delete(:object)).to_select_tag(choices, options, html_options)
|
67
85
|
end
|
68
86
|
|
69
|
-
#
|
87
|
+
# Returns <tt><select></tt> and <tt><option></tt> tags for the collection of existing return values of
|
88
|
+
# +method+ for +object+'s class. The value returned from calling +method+ on the instance +object+ will
|
89
|
+
# be selected. If calling +method+ returns +nil+, no selection is made without including <tt>:prompt</tt>
|
90
|
+
# or <tt>:include_blank</tt> in the +options+ hash.
|
91
|
+
#
|
92
|
+
# The <tt>:value_method</tt> and <tt>:text_method</tt> parameters are methods to be called on each member
|
93
|
+
# of +collection+. The return values are used as the +value+ attribute and contents of each
|
94
|
+
# <tt><option></tt> tag, respectively.
|
95
|
+
#
|
96
|
+
# Example object structure for use with this method:
|
97
|
+
# class Post < ActiveRecord::Base
|
98
|
+
# belongs_to :author
|
99
|
+
# end
|
100
|
+
# class Author < ActiveRecord::Base
|
101
|
+
# has_many :posts
|
102
|
+
# def name_with_initial
|
103
|
+
# "#{first_name.first}. #{last_name}"
|
104
|
+
# end
|
105
|
+
# end
|
106
|
+
#
|
107
|
+
# Sample usage (selecting the associated +Author+ for an instance of +Post+, <tt>@post</tt>):
|
108
|
+
# collection_select(:post, :author_id, Author.find(:all), :id, :name_with_initial, {:prompt => true})
|
109
|
+
#
|
110
|
+
# If <tt>@post.author_id</tt> is already <tt>1</tt>, this would return:
|
111
|
+
# <select name="post[author_id]">
|
112
|
+
# <option value="">Please select</option>
|
113
|
+
# <option value="1" selected="selected">D. Heinemeier Hansson</option>
|
114
|
+
# <option value="2">D. Thomas</option>
|
115
|
+
# <option value="3">M. Clark</option>
|
116
|
+
# </select>
|
70
117
|
def collection_select(object, method, collection, value_method, text_method, options = {}, html_options = {})
|
71
118
|
InstanceTag.new(object, method, self, nil, options.delete(:object)).to_collection_select_tag(collection, value_method, text_method, options, html_options)
|
72
119
|
end
|
@@ -112,17 +159,9 @@ module ActionView
|
|
112
159
|
container = container.to_a if Hash === container
|
113
160
|
|
114
161
|
options_for_select = container.inject([]) do |options, element|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
options << "<option value=\"#{html_escape(element.last.to_s)}\" selected=\"selected\">#{html_escape(element.first.to_s)}</option>"
|
119
|
-
else
|
120
|
-
options << "<option value=\"#{html_escape(element.last.to_s)}\">#{html_escape(element.first.to_s)}</option>"
|
121
|
-
end
|
122
|
-
else
|
123
|
-
is_selected = ( (selected.respond_to?(:include?) && !selected.is_a?(String) ? selected.include?(element) : element == selected) )
|
124
|
-
options << ((is_selected) ? "<option value=\"#{html_escape(element.to_s)}\" selected=\"selected\">#{html_escape(element.to_s)}</option>" : "<option value=\"#{html_escape(element.to_s)}\">#{html_escape(element.to_s)}</option>")
|
125
|
-
end
|
162
|
+
text, value = option_text_and_value(element)
|
163
|
+
selected_attribute = ' selected="selected"' if option_value_selected?(value, selected)
|
164
|
+
options << %(<option value="#{html_escape(value.to_s)}"#{selected_attribute}>#{html_escape(text.to_s)}</option>)
|
126
165
|
end
|
127
166
|
|
128
167
|
options_for_select.join("\n")
|
@@ -130,55 +169,68 @@ module ActionView
|
|
130
169
|
|
131
170
|
# Returns a string of option tags that have been compiled by iterating over the +collection+ and assigning the
|
132
171
|
# the result of a call to the +value_method+ as the option value and the +text_method+ as the option text.
|
133
|
-
# If +
|
172
|
+
# If +selected+ is specified, the element returning a match on +value_method+ will get the selected option tag.
|
134
173
|
#
|
135
174
|
# Example (call, result). Imagine a loop iterating over each +person+ in <tt>@project.people</tt> to generate an input tag:
|
136
175
|
# options_from_collection_for_select(@project.people, "id", "name")
|
137
176
|
# <option value="#{person.id}">#{person.name}</option>
|
138
177
|
#
|
139
178
|
# NOTE: Only the option tags are returned, you have to wrap this call in a regular HTML select tag.
|
140
|
-
def options_from_collection_for_select(collection, value_method, text_method,
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
)
|
179
|
+
def options_from_collection_for_select(collection, value_method, text_method, selected = nil)
|
180
|
+
options = collection.map do |element|
|
181
|
+
[element.send(text_method), element.send(value_method)]
|
182
|
+
end
|
183
|
+
options_for_select(options, selected)
|
145
184
|
end
|
146
185
|
|
147
|
-
# Returns a string of option tags, like options_from_collection_for_select
|
186
|
+
# Returns a string of <tt><option></tt> tags, like <tt>#options_from_collection_for_select</tt>, but
|
187
|
+
# groups them by <tt><optgroup></tt> tags based on the object relationships of the arguments.
|
148
188
|
#
|
149
|
-
#
|
150
|
-
#
|
189
|
+
# Parameters:
|
190
|
+
# +collection+:: An array of objects representing the <tt><optgroup></tt> tags
|
191
|
+
# +group_method+:: The name of a method which, when called on a member of +collection+, returns an
|
192
|
+
# array of child objects representing the <tt><option></tt> tags
|
193
|
+
# +group_label_method+:: The name of a method which, when called on a member of +collection+, returns a
|
194
|
+
# string to be used as the +label+ attribute for its <tt><optgroup></tt> tag
|
195
|
+
# +option_key_method+:: The name of a method which, when called on a child object of a member of
|
196
|
+
# +collection+, returns a value to be used as the +value+ attribute for its
|
197
|
+
# <tt><option></tt> tag
|
198
|
+
# +option_value_method+:: The name of a method which, when called on a child object of a member of
|
199
|
+
# +collection+, returns a value to be used as the contents of its
|
200
|
+
# <tt><option></tt> tag
|
201
|
+
# +selected_key+:: A value equal to the +value+ attribute for one of the <tt><option></tt> tags,
|
202
|
+
# which will have the +selected+ attribute set. Corresponds to the return value
|
203
|
+
# of one of the calls to +option_key_method+. If +nil+, no selection is made.
|
151
204
|
#
|
152
|
-
#
|
205
|
+
# Example object structure for use with this method:
|
206
|
+
# class Continent < ActiveRecord::Base
|
207
|
+
# has_many :countries
|
208
|
+
# # attribs: id, name
|
209
|
+
# end
|
210
|
+
# class Country < ActiveRecord::Base
|
211
|
+
# belongs_to :continent
|
212
|
+
# # attribs: id, name, continent_id
|
213
|
+
# end
|
153
214
|
#
|
154
|
-
#
|
155
|
-
#
|
156
|
-
# <select>Egypt</select>
|
157
|
-
# <select>Rwanda</select>
|
158
|
-
# ...
|
159
|
-
# </optgroup>
|
160
|
-
# <optgroup label="Asia">
|
161
|
-
# <select>China</select>
|
162
|
-
# <select>India</select>
|
163
|
-
# <select>Japan</select>
|
164
|
-
# ...
|
165
|
-
# </optgroup>
|
215
|
+
# Sample usage:
|
216
|
+
# option_groups_from_collection_for_select(@continents, :countries, :name, :id, :name, 3)
|
166
217
|
#
|
167
|
-
#
|
168
|
-
#
|
169
|
-
#
|
170
|
-
#
|
171
|
-
#
|
172
|
-
#
|
173
|
-
#
|
174
|
-
#
|
175
|
-
#
|
176
|
-
#
|
177
|
-
#
|
218
|
+
# Possible output:
|
219
|
+
# <optgroup label="Africa">
|
220
|
+
# <option value="1">Egypt</option>
|
221
|
+
# <option value="4">Rwanda</option>
|
222
|
+
# ...
|
223
|
+
# </optgroup>
|
224
|
+
# <optgroup label="Asia">
|
225
|
+
# <option value="3" selected="selected">China</option>
|
226
|
+
# <option value="12">India</option>
|
227
|
+
# <option value="5">Japan</option>
|
228
|
+
# ...
|
229
|
+
# </optgroup>
|
178
230
|
#
|
179
|
-
#
|
180
|
-
|
181
|
-
|
231
|
+
# <b>Note:</b> Only the <tt><optgroup></tt> and <tt><option></tt> tags are returned, so you still have to
|
232
|
+
# wrap the output in an appropriate <tt><select></tt> tag.
|
233
|
+
def option_groups_from_collection_for_select(collection, group_method, group_label_method, option_key_method, option_value_method, selected_key = nil)
|
182
234
|
collection.inject("") do |options_for_select, group|
|
183
235
|
group_label_string = eval("group.#{group_label_method}")
|
184
236
|
options_for_select += "<optgroup label=\"#{html_escape(group_label_string)}\">"
|
@@ -197,16 +249,10 @@ module ActionView
|
|
197
249
|
|
198
250
|
if priority_countries
|
199
251
|
country_options += options_for_select(priority_countries, selected)
|
200
|
-
country_options += "<option value=\"\">-------------</option>\n"
|
201
|
-
end
|
202
|
-
|
203
|
-
if priority_countries && priority_countries.include?(selected)
|
204
|
-
country_options += options_for_select(COUNTRIES - priority_countries, selected)
|
205
|
-
else
|
206
|
-
country_options += options_for_select(COUNTRIES, selected)
|
252
|
+
country_options += "<option value=\"\" disabled=\"disabled\">-------------</option>\n"
|
207
253
|
end
|
208
254
|
|
209
|
-
return country_options
|
255
|
+
return country_options + options_for_select(COUNTRIES, selected)
|
210
256
|
end
|
211
257
|
|
212
258
|
# Returns a string of option tags for pretty much any time zone in the
|
@@ -234,7 +280,7 @@ module ActionView
|
|
234
280
|
|
235
281
|
if priority_zones
|
236
282
|
zone_options += options_for_select(convert_zones[priority_zones], selected)
|
237
|
-
zone_options += "<option value=\"\">-------------</option>\n"
|
283
|
+
zone_options += "<option value=\"\" disabled=\"disabled\">-------------</option>\n"
|
238
284
|
|
239
285
|
zones = zones.reject { |z| priority_zones.include?( z ) }
|
240
286
|
end
|
@@ -244,51 +290,61 @@ module ActionView
|
|
244
290
|
end
|
245
291
|
|
246
292
|
private
|
293
|
+
def option_text_and_value(option)
|
294
|
+
# Options are [text, value] pairs or strings used for both.
|
295
|
+
if !option.is_a?(String) and option.respond_to?(:first) and option.respond_to?(:last)
|
296
|
+
[option.first, option.last]
|
297
|
+
else
|
298
|
+
[option, option]
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
def option_value_selected?(value, selected)
|
303
|
+
if selected.respond_to?(:include?) && !selected.is_a?(String)
|
304
|
+
selected.include? value
|
305
|
+
else
|
306
|
+
value == selected
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
247
310
|
# All the countries included in the country_options output.
|
248
|
-
COUNTRIES = [
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
"Togo", "Tokelau", "Tonga", "Trinidad", "Trinidad and Tobago", "Tunisia", "Turkey",
|
286
|
-
"Turkmenistan", "Turks and Caicos Islands", "Tuvalu", "Uganda", "Ukraine",
|
287
|
-
"United Arab Emirates", "United Kingdom", "United States",
|
288
|
-
"United States Minor Outlying Islands", "Uruguay", "Uzbekistan", "Vanuatu",
|
289
|
-
"Vatican City State (Holy See)", "Venezuela", "Viet Nam", "Virgin Islands (British)",
|
290
|
-
"Virgin Islands (U.S.)", "Wales", "Wallis and Futuna Islands", "Western Sahara",
|
291
|
-
"Yemen", "Zambia", "Zimbabwe" ] unless const_defined?("COUNTRIES")
|
311
|
+
COUNTRIES = ["Afghanistan", "Aland Islands", "Albania", "Algeria", "American Samoa", "Andorra", "Angola",
|
312
|
+
"Anguilla", "Antarctica", "Antigua And Barbuda", "Argentina", "Armenia", "Aruba", "Australia", "Austria",
|
313
|
+
"Azerbaijan", "Bahamas", "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", "Belize", "Benin",
|
314
|
+
"Bermuda", "Bhutan", "Bolivia", "Bosnia and Herzegowina", "Botswana", "Bouvet Island", "Brazil",
|
315
|
+
"British Indian Ocean Territory", "Brunei Darussalam", "Bulgaria", "Burkina Faso", "Burundi", "Cambodia",
|
316
|
+
"Cameroon", "Canada", "Cape Verde", "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
|
317
|
+
"Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
|
318
|
+
"Congo, the Democratic Republic of the", "Cook Islands", "Costa Rica", "Cote d'Ivoire", "Croatia", "Cuba",
|
319
|
+
"Cyprus", "Czech Republic", "Denmark", "Djibouti", "Dominica", "Dominican Republic", "Ecuador", "Egypt",
|
320
|
+
"El Salvador", "Equatorial Guinea", "Eritrea", "Estonia", "Ethiopia", "Falkland Islands (Malvinas)",
|
321
|
+
"Faroe Islands", "Fiji", "Finland", "France", "French Guiana", "French Polynesia",
|
322
|
+
"French Southern Territories", "Gabon", "Gambia", "Georgia", "Germany", "Ghana", "Gibraltar", "Greece", "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guernsey", "Guinea",
|
323
|
+
"Guinea-Bissau", "Guyana", "Haiti", "Heard and McDonald Islands", "Holy See (Vatican City State)",
|
324
|
+
"Honduras", "Hong Kong", "Hungary", "Iceland", "India", "Indonesia", "Iran, Islamic Republic of", "Iraq",
|
325
|
+
"Ireland", "Isle of Man", "Israel", "Italy", "Jamaica", "Japan", "Jersey", "Jordan", "Kazakhstan", "Kenya",
|
326
|
+
"Kiribati", "Korea, Democratic People's Republic of", "Korea, Republic of", "Kuwait", "Kyrgyzstan",
|
327
|
+
"Lao People's Democratic Republic", "Latvia", "Lebanon", "Lesotho", "Liberia", "Libyan Arab Jamahiriya",
|
328
|
+
"Liechtenstein", "Lithuania", "Luxembourg", "Macao", "Macedonia, The Former Yugoslav Republic Of",
|
329
|
+
"Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands", "Martinique",
|
330
|
+
"Mauritania", "Mauritius", "Mayotte", "Mexico", "Micronesia, Federated States of", "Moldova, Republic of",
|
331
|
+
"Monaco", "Mongolia", "Montenegro", "Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia", "Nauru",
|
332
|
+
"Nepal", "Netherlands", "Netherlands Antilles", "New Caledonia", "New Zealand", "Nicaragua", "Niger",
|
333
|
+
"Nigeria", "Niue", "Norfolk Island", "Northern Mariana Islands", "Norway", "Oman", "Pakistan", "Palau",
|
334
|
+
"Palestinian Territory, Occupied", "Panama", "Papua New Guinea", "Paraguay", "Peru", "Philippines",
|
335
|
+
"Pitcairn", "Poland", "Portugal", "Puerto Rico", "Qatar", "Reunion", "Romania", "Russian Federation",
|
336
|
+
"Rwanda", "Saint Barthelemy", "Saint Helena", "Saint Kitts and Nevis", "Saint Lucia",
|
337
|
+
"Saint Pierre and Miquelon", "Saint Vincent and the Grenadines", "Samoa", "San Marino",
|
338
|
+
"Sao Tome and Principe", "Saudi Arabia", "Senegal", "Serbia", "Seychelles", "Sierra Leone", "Singapore",
|
339
|
+
"Slovakia", "Slovenia", "Solomon Islands", "Somalia", "South Africa",
|
340
|
+
"South Georgia and the South Sandwich Islands", "Spain", "Sri Lanka", "Sudan", "Suriname",
|
341
|
+
"Svalbard and Jan Mayen", "Swaziland", "Sweden", "Switzerland", "Syrian Arab Republic",
|
342
|
+
"Taiwan, Province of China", "Tajikistan", "Tanzania, United Republic of", "Thailand", "Timor-Leste",
|
343
|
+
"Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey", "Turkmenistan",
|
344
|
+
"Turks and Caicos Islands", "Tuvalu", "Uganda", "Ukraine", "United Arab Emirates", "United Kingdom",
|
345
|
+
"United States", "United States Minor Outlying Islands", "Uruguay", "Uzbekistan", "Vanuatu", "Venezuela",
|
346
|
+
"Viet Nam", "Virgin Islands, British", "Virgin Islands, U.S.", "Wallis and Futuna", "Western Sahara",
|
347
|
+
"Yemen", "Zambia", "Zimbabwe"] unless const_defined?("COUNTRIES")
|
292
348
|
end
|
293
349
|
|
294
350
|
class InstanceTag #:nodoc:
|
@@ -315,7 +371,12 @@ module ActionView
|
|
315
371
|
html_options = html_options.stringify_keys
|
316
372
|
add_default_name_and_id(html_options)
|
317
373
|
value = value(object)
|
318
|
-
content_tag("select",
|
374
|
+
content_tag("select",
|
375
|
+
add_options(
|
376
|
+
country_options_for_select(value, priority_countries),
|
377
|
+
options, value
|
378
|
+
), html_options
|
379
|
+
)
|
319
380
|
end
|
320
381
|
|
321
382
|
def to_time_zone_select_tag(priority_zones, options, html_options)
|
@@ -332,8 +393,9 @@ module ActionView
|
|
332
393
|
|
333
394
|
private
|
334
395
|
def add_options(option_tags, options, value = nil)
|
335
|
-
|
336
|
-
|
396
|
+
if options[:include_blank]
|
397
|
+
option_tags = "<option value=\"\">#{options[:include_blank] if options[:include_blank].kind_of?(String)}</option>\n" + option_tags
|
398
|
+
end
|
337
399
|
if value.blank? && options[:prompt]
|
338
400
|
("<option value=\"\">#{options[:prompt].kind_of?(String) ? options[:prompt] : 'Please select'}</option>\n") + option_tags
|
339
401
|
else
|
@@ -1,109 +1,142 @@
|
|
1
1
|
require 'cgi'
|
2
|
-
require
|
2
|
+
require 'action_view/helpers/tag_helper'
|
3
3
|
|
4
4
|
module ActionView
|
5
5
|
module Helpers
|
6
|
-
# Provides a number of methods for creating form tags that doesn't rely on
|
7
|
-
# FormHelper does.
|
6
|
+
# Provides a number of methods for creating form tags that doesn't rely on an ActiveRecord object assigned to the template like
|
7
|
+
# FormHelper does. Instead, you provide the names and values manually.
|
8
8
|
#
|
9
|
-
# NOTE: The
|
10
|
-
# will give <tt>disabled="disabled"</tt>.
|
9
|
+
# NOTE: The HTML options <tt>disabled</tt>, <tt>readonly</tt>, and <tt>multiple</tt> can all be treated as booleans. So specifying
|
10
|
+
# <tt>:disabled => true</tt> will give <tt>disabled="disabled"</tt>.
|
11
11
|
module FormTagHelper
|
12
12
|
# Starts a form tag that points the action to an url configured with <tt>url_for_options</tt> just like
|
13
13
|
# ActionController::Base#url_for. The method for the form defaults to POST.
|
14
14
|
#
|
15
|
-
#
|
16
|
-
# * <tt>form_tag('/posts') => <form action="/posts" method="post"></tt>
|
17
|
-
# * <tt>form_tag('/posts/1', :method => :put) => <form action="/posts/1" method="put"></tt>
|
18
|
-
# * <tt>form_tag('/upload', :multipart => true) => <form action="/upload" method="post" enctype="multipart/form-data"></tt>
|
19
|
-
#
|
20
|
-
# ERb example:
|
21
|
-
# <% form_tag '/posts' do -%>
|
22
|
-
# <div><%= submit_tag 'Save' %></div>
|
23
|
-
# <% end -%>
|
24
|
-
#
|
25
|
-
# Will output:
|
26
|
-
# <form action="/posts" method="post"><div><input type="submit" name="submit" value="Save" /></div></form>
|
27
|
-
#
|
28
|
-
# Options:
|
15
|
+
# ==== Options
|
29
16
|
# * <tt>:multipart</tt> - If set to true, the enctype is set to "multipart/form-data".
|
30
17
|
# * <tt>:method</tt> - The method to use when submitting the form, usually either "get" or "post".
|
31
18
|
# If "put", "delete", or another verb is used, a hidden input with name _method
|
32
19
|
# is added to simulate the verb over post.
|
20
|
+
# * A list of parameters to feed to the URL the form will be posted to.
|
21
|
+
#
|
22
|
+
# ==== Examples
|
23
|
+
# form_tag('/posts')
|
24
|
+
# # => <form action="/posts" method="post">
|
25
|
+
#
|
26
|
+
# form_tag('/posts/1', :method => :put)
|
27
|
+
# # => <form action="/posts/1" method="put">
|
28
|
+
#
|
29
|
+
# form_tag('/upload', :multipart => true)
|
30
|
+
# # => <form action="/upload" method="post" enctype="multipart/form-data">
|
31
|
+
#
|
32
|
+
# <% form_tag '/posts' do -%>
|
33
|
+
# <div><%= submit_tag 'Save' %></div>
|
34
|
+
# <% end -%>
|
35
|
+
# # => <form action="/posts" method="post"><div><input type="submit" name="submit" value="Save" /></div></form>
|
33
36
|
def form_tag(url_for_options = {}, options = {}, *parameters_for_url, &block)
|
34
|
-
html_options = options
|
35
|
-
html_options["enctype"] = "multipart/form-data" if html_options.delete("multipart")
|
36
|
-
html_options["action"] = url_for(url_for_options, *parameters_for_url)
|
37
|
-
|
38
|
-
method_tag = ""
|
39
|
-
|
40
|
-
case method = html_options.delete("method").to_s
|
41
|
-
when /^get$/i # must be case-insentive, but can't use downcase as might be nil
|
42
|
-
html_options["method"] = "get"
|
43
|
-
when /^post$/i, "", nil
|
44
|
-
html_options["method"] = "post"
|
45
|
-
else
|
46
|
-
html_options["method"] = "post"
|
47
|
-
method_tag = content_tag(:div, tag(:input, :type => "hidden", :name => "_method", :value => method), :style => 'margin:0;padding:0')
|
48
|
-
end
|
49
|
-
|
37
|
+
html_options = html_options_for_form(url_for_options, options, *parameters_for_url)
|
50
38
|
if block_given?
|
51
|
-
|
52
|
-
concat(tag(:form, html_options, true) + method_tag, block.binding)
|
53
|
-
concat(content, block.binding)
|
54
|
-
concat("</form>", block.binding)
|
39
|
+
form_tag_in_block(html_options, &block)
|
55
40
|
else
|
56
|
-
|
41
|
+
form_tag_html(html_options)
|
57
42
|
end
|
58
43
|
end
|
59
44
|
|
60
|
-
alias_method :start_form_tag, :form_tag
|
61
|
-
|
62
|
-
# Outputs "</form>"
|
63
|
-
def end_form_tag
|
64
|
-
"</form>"
|
65
|
-
end
|
66
|
-
|
67
|
-
deprecate :end_form_tag, :start_form_tag => :form_tag
|
68
|
-
|
69
45
|
# Creates a dropdown selection box, or if the <tt>:multiple</tt> option is set to true, a multiple
|
70
46
|
# choice selection box.
|
71
47
|
#
|
72
48
|
# Helpers::FormOptions can be used to create common select boxes such as countries, time zones, or
|
73
|
-
# associated records.
|
49
|
+
# associated records. <tt>option_tags</tt> is a string containing the option tags for the select box.
|
74
50
|
#
|
75
|
-
#
|
76
|
-
#
|
51
|
+
# ==== Options
|
52
|
+
# * <tt>:multiple</tt> - If set to true the selection will allow multiple choices.
|
53
|
+
# * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
|
54
|
+
# * Any other key creates standard HTML attributes for the tag.
|
55
|
+
#
|
56
|
+
# ==== Examples
|
77
57
|
# select_tag "people", "<option>David</option>"
|
58
|
+
# # => <select id="people" name="people"><option>David</option></select>
|
78
59
|
#
|
79
|
-
#
|
80
|
-
#
|
60
|
+
# select_tag "count", "<option>1</option><option>2</option><option>3</option><option>4</option>"
|
61
|
+
# # => <select id="count" name="count"><option>1</option><option>2</option>
|
62
|
+
# # <option>3</option><option>4</option></select>
|
63
|
+
#
|
64
|
+
# select_tag "colors", "<option>Red</option><option>Green</option><option>Blue</option>", :multiple => true
|
65
|
+
# # => <select id="colors" multiple="multiple" name="colors"><option>Red</option>
|
66
|
+
# # <option>Green</option><option>Blue</option></select>
|
67
|
+
#
|
68
|
+
# select_tag "locations", "<option>Home</option><option selected="selected">Work</option><option>Out</option>"
|
69
|
+
# # => <select id="locations" name="locations"><option>Home</option><option selected='selected'>Work</option>
|
70
|
+
# # <option>Out</option></select>
|
71
|
+
#
|
72
|
+
# select_tag "access", "<option>Read</option><option>Write</option>", :multiple => true, :class => 'form_input'
|
73
|
+
# # => <select class="form_input" id="access" multiple="multiple" name="access"><option>Read</option>
|
74
|
+
# # <option>Write</option></select>
|
75
|
+
#
|
76
|
+
# select_tag "destination", "<option>NYC</option><option>Paris</option><option>Rome</option>", :disabled => true
|
77
|
+
# # => <select disabled="disabled" id="destination" name="destination"><option>NYC</option>
|
78
|
+
# # <option>Paris</option><option>Rome</option></select>
|
81
79
|
def select_tag(name, option_tags = nil, options = {})
|
82
80
|
content_tag :select, option_tags, { "name" => name, "id" => name }.update(options.stringify_keys)
|
83
81
|
end
|
84
82
|
|
85
|
-
# Creates a standard text field
|
83
|
+
# Creates a standard text field; use these text fields to input smaller chunks of text like a username
|
84
|
+
# or a search query.
|
86
85
|
#
|
87
|
-
# Options
|
86
|
+
# ==== Options
|
88
87
|
# * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
|
89
88
|
# * <tt>:size</tt> - The number of visible characters that will fit in the input.
|
90
89
|
# * <tt>:maxlength</tt> - The maximum number of characters that the browser will allow the user to enter.
|
90
|
+
# * Any other key creates standard HTML attributes for the tag.
|
91
91
|
#
|
92
|
-
#
|
92
|
+
# ==== Examples
|
93
|
+
# text_field_tag 'name'
|
94
|
+
# # => <input id="name" name="name" type="text" />
|
95
|
+
#
|
96
|
+
# text_field_tag 'query', 'Enter your search query here'
|
97
|
+
# # => <input id="query" name="query" type="text" value="Enter your search query here" />
|
98
|
+
#
|
99
|
+
# text_field_tag 'request', nil, :class => 'special_input'
|
100
|
+
# # => <input class="special_input" id="request" name="request" type="text" />
|
101
|
+
#
|
102
|
+
# text_field_tag 'address', '', :size => 75
|
103
|
+
# # => <input id="address" name="address" size="75" type="text" value="" />
|
104
|
+
#
|
105
|
+
# text_field_tag 'zip', nil, :maxlength => 5
|
106
|
+
# # => <input id="zip" maxlength="5" name="zip" type="text" />
|
107
|
+
#
|
108
|
+
# text_field_tag 'payment_amount', '$0.00', :disabled => true
|
109
|
+
# # => <input disabled="disabled" id="payment_amount" name="payment_amount" type="text" value="$0.00" />
|
110
|
+
#
|
111
|
+
# text_field_tag 'ip', '0.0.0.0', :maxlength => 15, :size => 20, :class => "ip-input"
|
112
|
+
# # => <input class="ip-input" id="ip" maxlength="15" name="ip" size="20" type="text" value="0.0.0.0" />
|
93
113
|
def text_field_tag(name, value = nil, options = {})
|
94
114
|
tag :input, { "type" => "text", "name" => name, "id" => name, "value" => value }.update(options.stringify_keys)
|
95
115
|
end
|
96
116
|
|
97
|
-
# Creates a hidden field
|
117
|
+
# Creates a hidden form input field used to transmit data that would be lost due to HTTP's statelessness or
|
118
|
+
# data that should be hidden from the user.
|
119
|
+
#
|
120
|
+
# ==== Options
|
121
|
+
# * Creates standard HTML attributes for the tag.
|
98
122
|
#
|
99
|
-
#
|
123
|
+
# ==== Examples
|
124
|
+
# hidden_field_tag 'tags_list'
|
125
|
+
# # => <input id="tags_list" name="tags_list" type="hidden" />
|
126
|
+
#
|
127
|
+
# hidden_field_tag 'token', 'VUBJKB23UIVI1UU1VOBVI@'
|
128
|
+
# # => <input id="token" name="token" type="hidden" value="VUBJKB23UIVI1UU1VOBVI@" />
|
129
|
+
#
|
130
|
+
# hidden_field_tag 'collected_input', '', :onchange => "alert('Input collected!')"
|
131
|
+
# # => <input id="collected_input" name="collected_input" onchange="alert('Input collected!')"
|
132
|
+
# # type="hidden" value="" />
|
100
133
|
def hidden_field_tag(name, value = nil, options = {})
|
101
134
|
text_field_tag(name, value, options.stringify_keys.update("type" => "hidden"))
|
102
135
|
end
|
103
136
|
|
104
|
-
# Creates a file upload field.
|
137
|
+
# Creates a file upload field. If you are using file uploads then you will also need
|
138
|
+
# to set the multipart option for the form tag:
|
105
139
|
#
|
106
|
-
# If you are using file uploads then you will also need to set the multipart option for the form:
|
107
140
|
# <%= form_tag { :action => "post" }, { :multipart => true } %>
|
108
141
|
# <label for="file">File to Upload</label> <%= file_field_tag "file" %>
|
109
142
|
# <%= submit_tag %>
|
@@ -111,55 +144,197 @@ module ActionView
|
|
111
144
|
#
|
112
145
|
# The specified URL will then be passed a File object containing the selected file, or if the field
|
113
146
|
# was left blank, a StringIO object.
|
147
|
+
#
|
148
|
+
# ==== Options
|
149
|
+
# * Creates standard HTML attributes for the tag.
|
150
|
+
# * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
|
151
|
+
#
|
152
|
+
# ==== Examples
|
153
|
+
# file_field_tag 'attachment'
|
154
|
+
# # => <input id="attachment" name="attachment" type="file" />
|
155
|
+
#
|
156
|
+
# file_field_tag 'avatar', :class => 'profile-input'
|
157
|
+
# # => <input class="profile-input" id="avatar" name="avatar" type="file" />
|
158
|
+
#
|
159
|
+
# file_field_tag 'picture', :disabled => true
|
160
|
+
# # => <input disabled="disabled" id="picture" name="picture" type="file" />
|
161
|
+
#
|
162
|
+
# file_field_tag 'resume', :value => '~/resume.doc'
|
163
|
+
# # => <input id="resume" name="resume" type="file" value="~/resume.doc" />
|
164
|
+
#
|
165
|
+
# file_field_tag 'user_pic', :accept => 'image/png,image/gif,image/jpeg'
|
166
|
+
# # => <input accept="image/png,image/gif,image/jpeg" id="user_pic" name="user_pic" type="file" />
|
167
|
+
#
|
168
|
+
# file_field_tag 'file', :accept => 'text/html', :class => 'upload', :value => 'index.html'
|
169
|
+
# # => <input accept="text/html" class="upload" id="file" name="file" type="file" value="index.html" />
|
114
170
|
def file_field_tag(name, options = {})
|
115
171
|
text_field_tag(name, nil, options.update("type" => "file"))
|
116
172
|
end
|
117
173
|
|
118
|
-
# Creates a password field.
|
174
|
+
# Creates a password field, a masked text field that will hide the users input behind a mask character.
|
175
|
+
#
|
176
|
+
# ==== Options
|
177
|
+
# * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
|
178
|
+
# * <tt>:size</tt> - The number of visible characters that will fit in the input.
|
179
|
+
# * <tt>:maxlength</tt> - The maximum number of characters that the browser will allow the user to enter.
|
180
|
+
# * Any other key creates standard HTML attributes for the tag.
|
181
|
+
#
|
182
|
+
# ==== Examples
|
183
|
+
# password_field_tag 'pass'
|
184
|
+
# # => <input id="pass" name="pass" type="password" />
|
185
|
+
#
|
186
|
+
# password_field_tag 'secret', 'Your secret here'
|
187
|
+
# # => <input id="secret" name="secret" type="password" value="Your secret here" />
|
188
|
+
#
|
189
|
+
# password_field_tag 'masked', nil, :class => 'masked_input_field'
|
190
|
+
# # => <input class="masked_input_field" id="masked" name="masked" type="password" />
|
119
191
|
#
|
120
|
-
#
|
192
|
+
# password_field_tag 'token', '', :size => 15
|
193
|
+
# # => <input id="token" name="token" size="15" type="password" value="" />
|
194
|
+
#
|
195
|
+
# password_field_tag 'key', nil, :maxlength => 16
|
196
|
+
# # => <input id="key" maxlength="16" name="key" type="password" />
|
197
|
+
#
|
198
|
+
# password_field_tag 'confirm_pass', nil, :disabled => true
|
199
|
+
# # => <input disabled="disabled" id="confirm_pass" name="confirm_pass" type="password" />
|
200
|
+
#
|
201
|
+
# password_field_tag 'pin', '1234', :maxlength => 4, :size => 6, :class => "pin-input"
|
202
|
+
# # => <input class="pin-input" id="pin" maxlength="4" name="pin" size="6" type="password" value="1234" />
|
121
203
|
def password_field_tag(name = "password", value = nil, options = {})
|
122
204
|
text_field_tag(name, value, options.update("type" => "password"))
|
123
205
|
end
|
124
206
|
|
125
|
-
# Creates a text input area.
|
207
|
+
# Creates a text input area; use a textarea for longer text inputs such as blog posts or descriptions.
|
208
|
+
#
|
209
|
+
# ==== Options
|
210
|
+
# * <tt>:size</tt> - A string specifying the dimensions (columns by rows) of the textarea (e.g., "25x10").
|
211
|
+
# * <tt>:rows</tt> - Specify the number of rows in the textarea
|
212
|
+
# * <tt>:cols</tt> - Specify the number of columns in the textarea
|
213
|
+
# * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
|
214
|
+
# * Any other key creates standard HTML attributes for the tag.
|
215
|
+
#
|
216
|
+
# ==== Examples
|
217
|
+
# text_area_tag 'post'
|
218
|
+
# # => <textarea id="post" name="post"></textarea>
|
219
|
+
#
|
220
|
+
# text_area_tag 'bio', @user.bio
|
221
|
+
# # => <textarea id="bio" name="bio">This is my biography.</textarea>
|
126
222
|
#
|
127
|
-
#
|
128
|
-
#
|
129
|
-
#
|
130
|
-
#
|
223
|
+
# text_area_tag 'body', nil, :rows => 10, :cols => 25
|
224
|
+
# # => <textarea cols="25" id="body" name="body" rows="10"></textarea>
|
225
|
+
#
|
226
|
+
# text_area_tag 'body', nil, :size => "25x10"
|
227
|
+
# # => <textarea name="body" id="body" cols="25" rows="10"></textarea>
|
228
|
+
#
|
229
|
+
# text_area_tag 'description', "Description goes here.", :disabled => true
|
230
|
+
# # => <textarea disabled="disabled" id="description" name="description">Description goes here.</textarea>
|
231
|
+
#
|
232
|
+
# text_area_tag 'comment', nil, :class => 'comment_input'
|
233
|
+
# # => <textarea class="comment_input" id="comment" name="comment"></textarea>
|
131
234
|
def text_area_tag(name, content = nil, options = {})
|
132
235
|
options.stringify_keys!
|
133
236
|
|
134
237
|
if size = options.delete("size")
|
135
|
-
options["cols"], options["rows"] = size.split("x")
|
238
|
+
options["cols"], options["rows"] = size.split("x") if size.respond_to?(:split)
|
136
239
|
end
|
137
240
|
|
138
241
|
content_tag :textarea, content, { "name" => name, "id" => name }.update(options.stringify_keys)
|
139
242
|
end
|
140
243
|
|
141
|
-
# Creates a check box.
|
244
|
+
# Creates a check box form input tag.
|
245
|
+
#
|
246
|
+
# ==== Options
|
247
|
+
# * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
|
248
|
+
# * Any other key creates standard HTML options for the tag.
|
249
|
+
#
|
250
|
+
# ==== Examples
|
251
|
+
# check_box_tag 'accept'
|
252
|
+
# # => <input id="accept" name="accept" type="checkbox" value="1" />
|
253
|
+
#
|
254
|
+
# check_box_tag 'rock', 'rock music'
|
255
|
+
# # => <input id="rock" name="rock" type="checkbox" value="rock music" />
|
256
|
+
#
|
257
|
+
# check_box_tag 'receive_email', 'yes', true
|
258
|
+
# # => <input checked="checked" id="receive_email" name="receive_email" type="checkbox" value="yes" />
|
259
|
+
#
|
260
|
+
# check_box_tag 'tos', 'yes', false, :class => 'accept_tos'
|
261
|
+
# # => <input class="accept_tos" id="tos" name="tos" type="checkbox" value="yes" />
|
262
|
+
#
|
263
|
+
# check_box_tag 'eula', 'accepted', false, :disabled => true
|
264
|
+
# # => <input disabled="disabled" id="eula" name="eula" type="checkbox" value="accepted" />
|
142
265
|
def check_box_tag(name, value = "1", checked = false, options = {})
|
143
266
|
html_options = { "type" => "checkbox", "name" => name, "id" => name, "value" => value }.update(options.stringify_keys)
|
144
267
|
html_options["checked"] = "checked" if checked
|
145
268
|
tag :input, html_options
|
146
269
|
end
|
147
270
|
|
148
|
-
# Creates a radio button
|
271
|
+
# Creates a radio button; use groups of radio buttons named the same to allow users to
|
272
|
+
# select from a group of options.
|
273
|
+
#
|
274
|
+
# ==== Options
|
275
|
+
# * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
|
276
|
+
# * Any other key creates standard HTML options for the tag.
|
277
|
+
#
|
278
|
+
# ==== Examples
|
279
|
+
# radio_button_tag 'gender', 'male'
|
280
|
+
# # => <input id="gender_male" name="gender" type="radio" value="male" />
|
281
|
+
#
|
282
|
+
# radio_button_tag 'receive_updates', 'no', true
|
283
|
+
# # => <input checked="checked" id="receive_updates_no" name="receive_updates" type="radio" value="no" />
|
284
|
+
#
|
285
|
+
# radio_button_tag 'time_slot', "3:00 p.m.", false, :disabled => true
|
286
|
+
# # => <input disabled="disabled" id="time_slot_300_pm" name="time_slot" type="radio" value="3:00 p.m." />
|
287
|
+
#
|
288
|
+
# radio_button_tag 'color', "green", true, :class => "color_input"
|
289
|
+
# # => <input checked="checked" class="color_input" id="color_green" name="color" type="radio" value="green" />
|
149
290
|
def radio_button_tag(name, value, checked = false, options = {})
|
150
291
|
pretty_tag_value = value.to_s.gsub(/\s/, "_").gsub(/(?!-)\W/, "").downcase
|
151
|
-
|
292
|
+
pretty_name = name.to_s.gsub(/\[/, "_").gsub(/\]/, "")
|
293
|
+
html_options = { "type" => "radio", "name" => name, "id" => "#{pretty_name}_#{pretty_tag_value}", "value" => value }.update(options.stringify_keys)
|
152
294
|
html_options["checked"] = "checked" if checked
|
153
295
|
tag :input, html_options
|
154
296
|
end
|
155
297
|
|
156
|
-
# Creates a submit button with the text <tt>value</tt> as the caption.
|
157
|
-
#
|
298
|
+
# Creates a submit button with the text <tt>value</tt> as the caption.
|
299
|
+
#
|
300
|
+
# ==== Options
|
301
|
+
# * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
|
302
|
+
# * <tt>:disable_with</tt> - Value of this parameter will be used as the value for a disabled version
|
303
|
+
# of the submit button when the form is submitted.
|
304
|
+
# * Any other key creates standard HTML options for the tag.
|
305
|
+
#
|
306
|
+
# ==== Examples
|
307
|
+
# submit_tag
|
308
|
+
# # => <input name="commit" type="submit" value="Save changes" />
|
309
|
+
#
|
310
|
+
# submit_tag "Edit this article"
|
311
|
+
# # => <input name="commit" type="submit" value="Edit this article" />
|
312
|
+
#
|
313
|
+
# submit_tag "Save edits", :disabled => true
|
314
|
+
# # => <input disabled="disabled" name="commit" type="submit" value="Save edits" />
|
315
|
+
#
|
316
|
+
# submit_tag "Complete sale", :disable_with => "Please wait..."
|
317
|
+
# # => <input name="commit" onclick="this.disabled=true;this.value='Please wait...';this.form.submit();"
|
318
|
+
# # type="submit" value="Complete sale" />
|
319
|
+
#
|
320
|
+
# submit_tag nil, :class => "form_submit"
|
321
|
+
# # => <input class="form_submit" name="commit" type="submit" />
|
322
|
+
#
|
323
|
+
# submit_tag "Edit", :disable_with => "Editing...", :class => 'edit-button'
|
324
|
+
# # => <input class="edit-button" disable_with="Editing..." name="commit" type="submit" value="Edit" />
|
158
325
|
def submit_tag(value = "Save changes", options = {})
|
159
326
|
options.stringify_keys!
|
160
327
|
|
161
328
|
if disable_with = options.delete("disable_with")
|
162
|
-
options["onclick"] =
|
329
|
+
options["onclick"] = [
|
330
|
+
"this.setAttribute('originalValue', this.value)",
|
331
|
+
"this.disabled=true",
|
332
|
+
"this.value='#{disable_with}'",
|
333
|
+
"#{options["onclick"]}",
|
334
|
+
"result = (this.form.onsubmit ? (this.form.onsubmit() ? this.form.submit() : false) : this.form.submit())",
|
335
|
+
"if (result == false) { this.value = this.getAttribute('originalValue'); this.disabled = false }",
|
336
|
+
"return result",
|
337
|
+
].join(";")
|
163
338
|
end
|
164
339
|
|
165
340
|
tag :input, { "type" => "submit", "name" => "commit", "value" => value }.update(options.stringify_keys)
|
@@ -168,9 +343,90 @@ module ActionView
|
|
168
343
|
# Displays an image which when clicked will submit the form.
|
169
344
|
#
|
170
345
|
# <tt>source</tt> is passed to AssetTagHelper#image_path
|
346
|
+
#
|
347
|
+
# ==== Options
|
348
|
+
# * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
|
349
|
+
# * Any other key creates standard HTML options for the tag.
|
350
|
+
#
|
351
|
+
# ==== Examples
|
352
|
+
# image_submit_tag("login.png")
|
353
|
+
# # => <input src="/images/login.png" type="image" />
|
354
|
+
#
|
355
|
+
# image_submit_tag("purchase.png"), :disabled => true
|
356
|
+
# # => <input disabled="disabled" src="/images/purchase.png" type="image" />
|
357
|
+
#
|
358
|
+
# image_submit_tag("search.png"), :class => 'search-button'
|
359
|
+
# # => <input class="search-button" src="/images/search.png" type="image" />
|
360
|
+
#
|
361
|
+
# image_submit_tag("agree.png"), :disabled => true, :class => "agree-disagree-button"
|
362
|
+
# # => <input class="agree-disagree-button" disabled="disabled" src="/images/agree.png" type="image" />
|
171
363
|
def image_submit_tag(source, options = {})
|
172
|
-
tag :input, { "type" => "image", "src" =>
|
364
|
+
tag :input, { "type" => "image", "src" => path_to_image(source) }.update(options.stringify_keys)
|
365
|
+
end
|
366
|
+
|
367
|
+
# Creates a field set for grouping HTML form elements.
|
368
|
+
#
|
369
|
+
# <tt>legend</tt> will become the fieldset's title (optional as per W3C).
|
370
|
+
#
|
371
|
+
# === Examples
|
372
|
+
# <% field_set_tag do %>
|
373
|
+
# <p><%= text_field_tag 'name' %></p>
|
374
|
+
# <% end %>
|
375
|
+
# # => <fieldset><p><input id="name" name="name" type="text" /></p></fieldset>
|
376
|
+
#
|
377
|
+
# <% field_set_tag 'Your details' do %>
|
378
|
+
# <p><%= text_field_tag 'name' %></p>
|
379
|
+
# <% end %>
|
380
|
+
# # => <fieldset><legend>Your details</legend><p><input id="name" name="name" type="text" /></p></fieldset>
|
381
|
+
def field_set_tag(legend = nil, &block)
|
382
|
+
content = capture(&block)
|
383
|
+
concat(tag(:fieldset, {}, true), block.binding)
|
384
|
+
concat(content_tag(:legend, legend), block.binding) unless legend.blank?
|
385
|
+
concat(content, block.binding)
|
386
|
+
concat("</fieldset>", block.binding)
|
173
387
|
end
|
388
|
+
|
389
|
+
private
|
390
|
+
def html_options_for_form(url_for_options, options, *parameters_for_url)
|
391
|
+
returning options.stringify_keys do |html_options|
|
392
|
+
html_options["enctype"] = "multipart/form-data" if html_options.delete("multipart")
|
393
|
+
html_options["action"] = url_for(url_for_options, *parameters_for_url)
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
def extra_tags_for_form(html_options)
|
398
|
+
case method = html_options.delete("method").to_s
|
399
|
+
when /^get$/i # must be case-insentive, but can't use downcase as might be nil
|
400
|
+
html_options["method"] = "get"
|
401
|
+
''
|
402
|
+
when /^post$/i, "", nil
|
403
|
+
html_options["method"] = "post"
|
404
|
+
protect_against_forgery? ? content_tag(:div, token_tag, :style => 'margin:0;padding:0') : ''
|
405
|
+
else
|
406
|
+
html_options["method"] = "post"
|
407
|
+
content_tag(:div, tag(:input, :type => "hidden", :name => "_method", :value => method) + token_tag, :style => 'margin:0;padding:0')
|
408
|
+
end
|
409
|
+
end
|
410
|
+
|
411
|
+
def form_tag_html(html_options)
|
412
|
+
extra_tags = extra_tags_for_form(html_options)
|
413
|
+
tag(:form, html_options, true) + extra_tags
|
414
|
+
end
|
415
|
+
|
416
|
+
def form_tag_in_block(html_options, &block)
|
417
|
+
content = capture(&block)
|
418
|
+
concat(form_tag_html(html_options), block.binding)
|
419
|
+
concat(content, block.binding)
|
420
|
+
concat("</form>", block.binding)
|
421
|
+
end
|
422
|
+
|
423
|
+
def token_tag
|
424
|
+
unless protect_against_forgery?
|
425
|
+
''
|
426
|
+
else
|
427
|
+
tag(:input, :type => "hidden", :name => request_forgery_protection_token.to_s, :value => form_authenticity_token)
|
428
|
+
end
|
429
|
+
end
|
174
430
|
end
|
175
431
|
end
|
176
432
|
end
|