actionpack 4.0.1 → 4.2.11.1

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

Potentially problematic release.


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

Files changed (241) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +402 -1173
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +7 -7
  5. data/lib/abstract_controller/base.rb +39 -7
  6. data/lib/abstract_controller/callbacks.rb +32 -53
  7. data/lib/abstract_controller/collector.rb +11 -1
  8. data/lib/abstract_controller/helpers.rb +26 -16
  9. data/lib/abstract_controller/railties/routes_helpers.rb +3 -3
  10. data/lib/abstract_controller/rendering.rb +57 -127
  11. data/lib/abstract_controller/url_for.rb +1 -1
  12. data/lib/abstract_controller.rb +1 -2
  13. data/lib/action_controller/base.rb +19 -10
  14. data/lib/action_controller/caching/fragments.rb +7 -1
  15. data/lib/action_controller/caching.rb +2 -12
  16. data/lib/action_controller/log_subscriber.rb +29 -20
  17. data/lib/action_controller/metal/conditional_get.rb +37 -12
  18. data/lib/action_controller/metal/data_streaming.rb +1 -1
  19. data/lib/action_controller/metal/etag_with_template_digest.rb +50 -0
  20. data/lib/action_controller/metal/exceptions.rb +1 -1
  21. data/lib/action_controller/metal/flash.rb +17 -0
  22. data/lib/action_controller/metal/force_ssl.rb +2 -2
  23. data/lib/action_controller/metal/head.rb +8 -6
  24. data/lib/action_controller/metal/helpers.rb +6 -2
  25. data/lib/action_controller/metal/http_authentication.rb +45 -23
  26. data/lib/action_controller/metal/instrumentation.rb +9 -6
  27. data/lib/action_controller/metal/live.rb +173 -20
  28. data/lib/action_controller/metal/mime_responds.rb +127 -232
  29. data/lib/action_controller/metal/params_wrapper.rb +16 -9
  30. data/lib/action_controller/metal/rack_delegation.rb +1 -1
  31. data/lib/action_controller/metal/redirecting.rb +34 -26
  32. data/lib/action_controller/metal/renderers.rb +39 -12
  33. data/lib/action_controller/metal/rendering.rb +41 -14
  34. data/lib/action_controller/metal/request_forgery_protection.rb +147 -19
  35. data/lib/action_controller/metal/streaming.rb +19 -21
  36. data/lib/action_controller/metal/strong_parameters.rb +166 -22
  37. data/lib/action_controller/metal/testing.rb +0 -1
  38. data/lib/action_controller/metal/url_for.rb +11 -12
  39. data/lib/action_controller/metal.rb +14 -8
  40. data/lib/action_controller/model_naming.rb +1 -1
  41. data/lib/action_controller/railtie.rb +5 -1
  42. data/lib/action_controller/test_case.rb +160 -94
  43. data/lib/action_controller.rb +2 -18
  44. data/lib/action_dispatch/http/cache.rb +5 -4
  45. data/lib/action_dispatch/http/filter_parameters.rb +2 -2
  46. data/lib/action_dispatch/http/filter_redirect.rb +5 -4
  47. data/lib/action_dispatch/http/headers.rb +46 -10
  48. data/lib/action_dispatch/http/mime_negotiation.rb +31 -4
  49. data/lib/action_dispatch/http/mime_type.rb +25 -26
  50. data/lib/action_dispatch/http/mime_types.rb +1 -0
  51. data/lib/action_dispatch/http/parameter_filter.rb +1 -1
  52. data/lib/action_dispatch/http/parameters.rb +25 -41
  53. data/lib/action_dispatch/http/request.rb +49 -32
  54. data/lib/action_dispatch/http/response.rb +127 -25
  55. data/lib/action_dispatch/http/upload.rb +9 -21
  56. data/lib/action_dispatch/http/url.rb +97 -70
  57. data/lib/action_dispatch/journey/formatter.rb +35 -19
  58. data/lib/action_dispatch/journey/gtg/builder.rb +3 -3
  59. data/lib/action_dispatch/journey/gtg/simulator.rb +10 -7
  60. data/lib/action_dispatch/journey/gtg/transition_table.rb +23 -33
  61. data/lib/action_dispatch/journey/nfa/dot.rb +2 -2
  62. data/lib/action_dispatch/journey/nfa/simulator.rb +1 -1
  63. data/lib/action_dispatch/journey/nfa/transition_table.rb +5 -5
  64. data/lib/action_dispatch/journey/nodes/node.rb +4 -0
  65. data/lib/action_dispatch/journey/parser.rb +51 -59
  66. data/lib/action_dispatch/journey/parser.y +12 -10
  67. data/lib/action_dispatch/journey/path/pattern.rb +16 -19
  68. data/lib/action_dispatch/journey/route.rb +8 -19
  69. data/lib/action_dispatch/journey/router/strexp.rb +9 -6
  70. data/lib/action_dispatch/journey/router/utils.rb +54 -18
  71. data/lib/action_dispatch/journey/router.rb +53 -75
  72. data/lib/action_dispatch/journey/routes.rb +4 -0
  73. data/lib/action_dispatch/journey/scanner.rb +5 -5
  74. data/lib/action_dispatch/journey/visitors.rb +81 -60
  75. data/lib/action_dispatch/journey/visualizer/fsm.css +0 -4
  76. data/lib/action_dispatch/journey/visualizer/index.html.erb +2 -2
  77. data/lib/action_dispatch/middleware/callbacks.rb +7 -7
  78. data/lib/action_dispatch/middleware/cookies.rb +119 -43
  79. data/lib/action_dispatch/middleware/debug_exceptions.rb +32 -13
  80. data/lib/action_dispatch/middleware/exception_wrapper.rb +60 -20
  81. data/lib/action_dispatch/middleware/flash.rb +37 -24
  82. data/lib/action_dispatch/middleware/params_parser.rb +2 -2
  83. data/lib/action_dispatch/middleware/public_exceptions.rb +12 -3
  84. data/lib/action_dispatch/middleware/reloader.rb +11 -2
  85. data/lib/action_dispatch/middleware/remote_ip.rb +40 -54
  86. data/lib/action_dispatch/middleware/request_id.rb +1 -1
  87. data/lib/action_dispatch/middleware/session/cache_store.rb +3 -3
  88. data/lib/action_dispatch/middleware/session/cookie_store.rb +8 -7
  89. data/lib/action_dispatch/middleware/show_exceptions.rb +6 -2
  90. data/lib/action_dispatch/middleware/ssl.rb +10 -7
  91. data/lib/action_dispatch/middleware/static.rb +79 -23
  92. data/lib/action_dispatch/middleware/templates/rescues/{_request_and_response.erb → _request_and_response.html.erb} +0 -0
  93. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +23 -0
  94. data/lib/action_dispatch/middleware/templates/rescues/_source.erb +21 -19
  95. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +52 -0
  96. data/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb +9 -0
  97. data/lib/action_dispatch/middleware/templates/rescues/{diagnostics.erb → diagnostics.html.erb} +1 -1
  98. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +9 -0
  99. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +6 -0
  100. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +11 -0
  101. data/lib/action_dispatch/middleware/templates/rescues/missing_template.text.erb +3 -0
  102. data/lib/action_dispatch/middleware/templates/rescues/{routing_error.erb → routing_error.html.erb} +3 -1
  103. data/lib/action_dispatch/middleware/templates/rescues/routing_error.text.erb +11 -0
  104. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +20 -0
  105. data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +7 -0
  106. data/lib/action_dispatch/middleware/templates/rescues/{unknown_action.erb → unknown_action.html.erb} +1 -1
  107. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +3 -0
  108. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +120 -64
  109. data/lib/action_dispatch/railtie.rb +5 -2
  110. data/lib/action_dispatch/request/session.rb +12 -0
  111. data/lib/action_dispatch/request/utils.rb +35 -0
  112. data/lib/action_dispatch/routing/endpoint.rb +10 -0
  113. data/lib/action_dispatch/routing/inspector.rb +11 -17
  114. data/lib/action_dispatch/routing/mapper.rb +519 -312
  115. data/lib/action_dispatch/routing/polymorphic_routes.rb +204 -79
  116. data/lib/action_dispatch/routing/redirection.rb +51 -26
  117. data/lib/action_dispatch/routing/route_set.rb +331 -206
  118. data/lib/action_dispatch/routing/routes_proxy.rb +5 -4
  119. data/lib/action_dispatch/routing/url_for.rb +19 -5
  120. data/lib/action_dispatch/routing.rb +9 -6
  121. data/lib/action_dispatch/testing/assertions/dom.rb +2 -26
  122. data/lib/action_dispatch/testing/assertions/response.rb +9 -15
  123. data/lib/action_dispatch/testing/assertions/routing.rb +22 -22
  124. data/lib/action_dispatch/testing/assertions/selector.rb +2 -429
  125. data/lib/action_dispatch/testing/assertions/tag.rb +2 -134
  126. data/lib/action_dispatch/testing/assertions.rb +11 -7
  127. data/lib/action_dispatch/testing/integration.rb +31 -29
  128. data/lib/action_dispatch/testing/test_request.rb +1 -1
  129. data/lib/action_dispatch/testing/test_response.rb +1 -5
  130. data/lib/action_dispatch.rb +5 -8
  131. data/lib/action_pack/gem_version.rb +15 -0
  132. data/lib/action_pack/version.rb +4 -7
  133. data/lib/action_pack.rb +1 -1
  134. metadata +77 -159
  135. data/lib/abstract_controller/layouts.rb +0 -423
  136. data/lib/abstract_controller/view_paths.rb +0 -96
  137. data/lib/action_controller/deprecated/integration_test.rb +0 -5
  138. data/lib/action_controller/deprecated.rb +0 -7
  139. data/lib/action_controller/metal/responder.rb +0 -287
  140. data/lib/action_controller/record_identifier.rb +0 -31
  141. data/lib/action_controller/vendor/html-scanner.rb +0 -5
  142. data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +0 -24
  143. data/lib/action_dispatch/middleware/templates/rescues/missing_template.erb +0 -7
  144. data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +0 -43
  145. data/lib/action_view/base.rb +0 -201
  146. data/lib/action_view/buffers.rb +0 -49
  147. data/lib/action_view/context.rb +0 -36
  148. data/lib/action_view/dependency_tracker.rb +0 -93
  149. data/lib/action_view/digestor.rb +0 -113
  150. data/lib/action_view/flows.rb +0 -76
  151. data/lib/action_view/helpers/active_model_helper.rb +0 -49
  152. data/lib/action_view/helpers/asset_tag_helper.rb +0 -320
  153. data/lib/action_view/helpers/asset_url_helper.rb +0 -355
  154. data/lib/action_view/helpers/atom_feed_helper.rb +0 -203
  155. data/lib/action_view/helpers/cache_helper.rb +0 -196
  156. data/lib/action_view/helpers/capture_helper.rb +0 -216
  157. data/lib/action_view/helpers/controller_helper.rb +0 -25
  158. data/lib/action_view/helpers/csrf_helper.rb +0 -30
  159. data/lib/action_view/helpers/date_helper.rb +0 -1083
  160. data/lib/action_view/helpers/debug_helper.rb +0 -39
  161. data/lib/action_view/helpers/form_helper.rb +0 -1880
  162. data/lib/action_view/helpers/form_options_helper.rb +0 -838
  163. data/lib/action_view/helpers/form_tag_helper.rb +0 -785
  164. data/lib/action_view/helpers/javascript_helper.rb +0 -117
  165. data/lib/action_view/helpers/number_helper.rb +0 -441
  166. data/lib/action_view/helpers/output_safety_helper.rb +0 -38
  167. data/lib/action_view/helpers/record_tag_helper.rb +0 -106
  168. data/lib/action_view/helpers/rendering_helper.rb +0 -90
  169. data/lib/action_view/helpers/sanitize_helper.rb +0 -256
  170. data/lib/action_view/helpers/tag_helper.rb +0 -173
  171. data/lib/action_view/helpers/tags/base.rb +0 -148
  172. data/lib/action_view/helpers/tags/check_box.rb +0 -64
  173. data/lib/action_view/helpers/tags/checkable.rb +0 -16
  174. data/lib/action_view/helpers/tags/collection_check_boxes.rb +0 -44
  175. data/lib/action_view/helpers/tags/collection_helpers.rb +0 -84
  176. data/lib/action_view/helpers/tags/collection_radio_buttons.rb +0 -36
  177. data/lib/action_view/helpers/tags/collection_select.rb +0 -28
  178. data/lib/action_view/helpers/tags/color_field.rb +0 -25
  179. data/lib/action_view/helpers/tags/date_field.rb +0 -13
  180. data/lib/action_view/helpers/tags/date_select.rb +0 -72
  181. data/lib/action_view/helpers/tags/datetime_field.rb +0 -22
  182. data/lib/action_view/helpers/tags/datetime_local_field.rb +0 -19
  183. data/lib/action_view/helpers/tags/datetime_select.rb +0 -8
  184. data/lib/action_view/helpers/tags/email_field.rb +0 -8
  185. data/lib/action_view/helpers/tags/file_field.rb +0 -8
  186. data/lib/action_view/helpers/tags/grouped_collection_select.rb +0 -29
  187. data/lib/action_view/helpers/tags/hidden_field.rb +0 -8
  188. data/lib/action_view/helpers/tags/label.rb +0 -66
  189. data/lib/action_view/helpers/tags/month_field.rb +0 -13
  190. data/lib/action_view/helpers/tags/number_field.rb +0 -18
  191. data/lib/action_view/helpers/tags/password_field.rb +0 -12
  192. data/lib/action_view/helpers/tags/radio_button.rb +0 -31
  193. data/lib/action_view/helpers/tags/range_field.rb +0 -8
  194. data/lib/action_view/helpers/tags/search_field.rb +0 -24
  195. data/lib/action_view/helpers/tags/select.rb +0 -40
  196. data/lib/action_view/helpers/tags/tel_field.rb +0 -8
  197. data/lib/action_view/helpers/tags/text_area.rb +0 -18
  198. data/lib/action_view/helpers/tags/text_field.rb +0 -29
  199. data/lib/action_view/helpers/tags/time_field.rb +0 -13
  200. data/lib/action_view/helpers/tags/time_select.rb +0 -8
  201. data/lib/action_view/helpers/tags/time_zone_select.rb +0 -20
  202. data/lib/action_view/helpers/tags/url_field.rb +0 -8
  203. data/lib/action_view/helpers/tags/week_field.rb +0 -13
  204. data/lib/action_view/helpers/tags.rb +0 -39
  205. data/lib/action_view/helpers/text_helper.rb +0 -443
  206. data/lib/action_view/helpers/translation_helper.rb +0 -107
  207. data/lib/action_view/helpers/url_helper.rb +0 -635
  208. data/lib/action_view/helpers.rb +0 -58
  209. data/lib/action_view/locale/en.yml +0 -56
  210. data/lib/action_view/log_subscriber.rb +0 -30
  211. data/lib/action_view/lookup_context.rb +0 -241
  212. data/lib/action_view/model_naming.rb +0 -12
  213. data/lib/action_view/path_set.rb +0 -77
  214. data/lib/action_view/railtie.rb +0 -43
  215. data/lib/action_view/record_identifier.rb +0 -84
  216. data/lib/action_view/renderer/abstract_renderer.rb +0 -47
  217. data/lib/action_view/renderer/partial_renderer.rb +0 -492
  218. data/lib/action_view/renderer/renderer.rb +0 -50
  219. data/lib/action_view/renderer/streaming_template_renderer.rb +0 -103
  220. data/lib/action_view/renderer/template_renderer.rb +0 -96
  221. data/lib/action_view/routing_url_for.rb +0 -107
  222. data/lib/action_view/tasks/dependencies.rake +0 -17
  223. data/lib/action_view/template/error.rb +0 -138
  224. data/lib/action_view/template/handlers/builder.rb +0 -26
  225. data/lib/action_view/template/handlers/erb.rb +0 -146
  226. data/lib/action_view/template/handlers/raw.rb +0 -11
  227. data/lib/action_view/template/handlers.rb +0 -53
  228. data/lib/action_view/template/resolver.rb +0 -326
  229. data/lib/action_view/template/text.rb +0 -34
  230. data/lib/action_view/template/types.rb +0 -57
  231. data/lib/action_view/template.rb +0 -339
  232. data/lib/action_view/test_case.rb +0 -270
  233. data/lib/action_view/testing/resolvers.rb +0 -50
  234. data/lib/action_view/vendor/html-scanner/html/document.rb +0 -68
  235. data/lib/action_view/vendor/html-scanner/html/node.rb +0 -532
  236. data/lib/action_view/vendor/html-scanner/html/sanitizer.rb +0 -188
  237. data/lib/action_view/vendor/html-scanner/html/selector.rb +0 -830
  238. data/lib/action_view/vendor/html-scanner/html/tokenizer.rb +0 -107
  239. data/lib/action_view/vendor/html-scanner/html/version.rb +0 -11
  240. data/lib/action_view/vendor/html-scanner.rb +0 -20
  241. data/lib/action_view.rb +0 -93
@@ -1,785 +0,0 @@
1
- require 'cgi'
2
- require 'action_view/helpers/tag_helper'
3
- require 'active_support/core_ext/string/output_safety'
4
- require 'active_support/core_ext/module/attribute_accessors'
5
-
6
- module ActionView
7
- # = Action View Form Tag Helpers
8
- module Helpers
9
- # Provides a number of methods for creating form tags that don't rely on an Active Record object assigned to the template like
10
- # FormHelper does. Instead, you provide the names and values manually.
11
- #
12
- # NOTE: The HTML options <tt>disabled</tt>, <tt>readonly</tt>, and <tt>multiple</tt> can all be treated as booleans. So specifying
13
- # <tt>disabled: true</tt> will give <tt>disabled="disabled"</tt>.
14
- module FormTagHelper
15
- extend ActiveSupport::Concern
16
-
17
- include UrlHelper
18
- include TextHelper
19
-
20
- mattr_accessor :embed_authenticity_token_in_remote_forms
21
- self.embed_authenticity_token_in_remote_forms = false
22
-
23
- # Starts a form tag that points the action to an url configured with <tt>url_for_options</tt> just like
24
- # ActionController::Base#url_for. The method for the form defaults to POST.
25
- #
26
- # ==== Options
27
- # * <tt>:multipart</tt> - If set to true, the enctype is set to "multipart/form-data".
28
- # * <tt>:method</tt> - The method to use when submitting the form, usually either "get" or "post".
29
- # If "patch", "put", "delete", or another verb is used, a hidden input with name <tt>_method</tt>
30
- # is added to simulate the verb over post.
31
- # * <tt>:authenticity_token</tt> - Authenticity token to use in the form. Use only if you need to
32
- # pass custom authenticity token string, or to not add authenticity_token field at all
33
- # (by passing <tt>false</tt>). Remote forms may omit the embedded authenticity token
34
- # by setting <tt>config.action_view.embed_authenticity_token_in_remote_forms = false</tt>.
35
- # This is helpful when you're fragment-caching the form. Remote forms get the
36
- # authenticity token from the <tt>meta</tt> tag, so embedding is unnecessary unless you
37
- # support browsers without JavaScript.
38
- # * A list of parameters to feed to the URL the form will be posted to.
39
- # * <tt>:remote</tt> - If set to true, will allow the Unobtrusive JavaScript drivers to control the
40
- # submit behavior. By default this behavior is an ajax submit.
41
- #
42
- # ==== Examples
43
- # form_tag('/posts')
44
- # # => <form action="/posts" method="post">
45
- #
46
- # form_tag('/posts/1', method: :put)
47
- # # => <form action="/posts/1" method="post"> ... <input name="_method" type="hidden" value="put" /> ...
48
- #
49
- # form_tag('/upload', multipart: true)
50
- # # => <form action="/upload" method="post" enctype="multipart/form-data">
51
- #
52
- # <%= form_tag('/posts') do -%>
53
- # <div><%= submit_tag 'Save' %></div>
54
- # <% end -%>
55
- # # => <form action="/posts" method="post"><div><input type="submit" name="commit" value="Save" /></div></form>
56
- #
57
- # <%= form_tag('/posts', remote: true) %>
58
- # # => <form action="/posts" method="post" data-remote="true">
59
- #
60
- # form_tag('http://far.away.com/form', authenticity_token: false)
61
- # # form without authenticity token
62
- #
63
- # form_tag('http://far.away.com/form', authenticity_token: "cf50faa3fe97702ca1ae")
64
- # # form with custom authenticity token
65
- #
66
- def form_tag(url_for_options = {}, options = {}, &block)
67
- html_options = html_options_for_form(url_for_options, options)
68
- if block_given?
69
- form_tag_in_block(html_options, &block)
70
- else
71
- form_tag_html(html_options)
72
- end
73
- end
74
-
75
- # Creates a dropdown selection box, or if the <tt>:multiple</tt> option is set to true, a multiple
76
- # choice selection box.
77
- #
78
- # Helpers::FormOptions can be used to create common select boxes such as countries, time zones, or
79
- # associated records. <tt>option_tags</tt> is a string containing the option tags for the select box.
80
- #
81
- # ==== Options
82
- # * <tt>:multiple</tt> - If set to true the selection will allow multiple choices.
83
- # * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
84
- # * <tt>:include_blank</tt> - If set to true, an empty option will be created.
85
- # * <tt>:prompt</tt> - Create a prompt option with blank value and the text asking user to select something
86
- # * Any other key creates standard HTML attributes for the tag.
87
- #
88
- # ==== Examples
89
- # select_tag "people", options_from_collection_for_select(@people, "id", "name")
90
- # # <select id="people" name="people"><option value="1">David</option></select>
91
- #
92
- # select_tag "people", "<option>David</option>".html_safe
93
- # # => <select id="people" name="people"><option>David</option></select>
94
- #
95
- # select_tag "count", "<option>1</option><option>2</option><option>3</option><option>4</option>".html_safe
96
- # # => <select id="count" name="count"><option>1</option><option>2</option>
97
- # # <option>3</option><option>4</option></select>
98
- #
99
- # select_tag "colors", "<option>Red</option><option>Green</option><option>Blue</option>".html_safe, multiple: true
100
- # # => <select id="colors" multiple="multiple" name="colors[]"><option>Red</option>
101
- # # <option>Green</option><option>Blue</option></select>
102
- #
103
- # select_tag "locations", "<option>Home</option><option selected='selected'>Work</option><option>Out</option>".html_safe
104
- # # => <select id="locations" name="locations"><option>Home</option><option selected='selected'>Work</option>
105
- # # <option>Out</option></select>
106
- #
107
- # select_tag "access", "<option>Read</option><option>Write</option>".html_safe, multiple: true, class: 'form_input'
108
- # # => <select class="form_input" id="access" multiple="multiple" name="access[]"><option>Read</option>
109
- # # <option>Write</option></select>
110
- #
111
- # select_tag "people", options_from_collection_for_select(@people, "id", "name"), include_blank: true
112
- # # => <select id="people" name="people"><option value=""></option><option value="1">David</option></select>
113
- #
114
- # select_tag "people", options_from_collection_for_select(@people, "id", "name"), prompt: "Select something"
115
- # # => <select id="people" name="people"><option value="">Select something</option><option value="1">David</option></select>
116
- #
117
- # select_tag "destination", "<option>NYC</option><option>Paris</option><option>Rome</option>".html_safe, disabled: true
118
- # # => <select disabled="disabled" id="destination" name="destination"><option>NYC</option>
119
- # # <option>Paris</option><option>Rome</option></select>
120
- #
121
- # select_tag "credit_card", options_for_select([ "VISA", "MasterCard" ], "MasterCard")
122
- # # => <select id="credit_card" name="credit_card"><option>VISA</option>
123
- # # <option selected="selected">MasterCard</option></select>
124
- def select_tag(name, option_tags = nil, options = {})
125
- option_tags ||= ""
126
- html_name = (options[:multiple] == true && !name.to_s.ends_with?("[]")) ? "#{name}[]" : name
127
-
128
- if options.delete(:include_blank)
129
- option_tags = content_tag(:option, '', :value => '').safe_concat(option_tags)
130
- end
131
-
132
- if prompt = options.delete(:prompt)
133
- option_tags = content_tag(:option, prompt, :value => '').safe_concat(option_tags)
134
- end
135
-
136
- content_tag :select, option_tags, { "name" => html_name, "id" => sanitize_to_id(name) }.update(options.stringify_keys)
137
- end
138
-
139
- # Creates a standard text field; use these text fields to input smaller chunks of text like a username
140
- # or a search query.
141
- #
142
- # ==== Options
143
- # * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
144
- # * <tt>:size</tt> - The number of visible characters that will fit in the input.
145
- # * <tt>:maxlength</tt> - The maximum number of characters that the browser will allow the user to enter.
146
- # * <tt>:placeholder</tt> - The text contained in the field by default which is removed when the field receives focus.
147
- # * Any other key creates standard HTML attributes for the tag.
148
- #
149
- # ==== Examples
150
- # text_field_tag 'name'
151
- # # => <input id="name" name="name" type="text" />
152
- #
153
- # text_field_tag 'query', 'Enter your search query here'
154
- # # => <input id="query" name="query" type="text" value="Enter your search query here" />
155
- #
156
- # text_field_tag 'search', nil, placeholder: 'Enter search term...'
157
- # # => <input id="search" name="search" placeholder="Enter search term..." type="text" />
158
- #
159
- # text_field_tag 'request', nil, class: 'special_input'
160
- # # => <input class="special_input" id="request" name="request" type="text" />
161
- #
162
- # text_field_tag 'address', '', size: 75
163
- # # => <input id="address" name="address" size="75" type="text" value="" />
164
- #
165
- # text_field_tag 'zip', nil, maxlength: 5
166
- # # => <input id="zip" maxlength="5" name="zip" type="text" />
167
- #
168
- # text_field_tag 'payment_amount', '$0.00', disabled: true
169
- # # => <input disabled="disabled" id="payment_amount" name="payment_amount" type="text" value="$0.00" />
170
- #
171
- # text_field_tag 'ip', '0.0.0.0', maxlength: 15, size: 20, class: "ip-input"
172
- # # => <input class="ip-input" id="ip" maxlength="15" name="ip" size="20" type="text" value="0.0.0.0" />
173
- def text_field_tag(name, value = nil, options = {})
174
- tag :input, { "type" => "text", "name" => name, "id" => sanitize_to_id(name), "value" => value }.update(options.stringify_keys)
175
- end
176
-
177
- # Creates a label element. Accepts a block.
178
- #
179
- # ==== Options
180
- # * Creates standard HTML attributes for the tag.
181
- #
182
- # ==== Examples
183
- # label_tag 'name'
184
- # # => <label for="name">Name</label>
185
- #
186
- # label_tag 'name', 'Your name'
187
- # # => <label for="name">Your name</label>
188
- #
189
- # label_tag 'name', nil, class: 'small_label'
190
- # # => <label for="name" class="small_label">Name</label>
191
- def label_tag(name = nil, content_or_options = nil, options = nil, &block)
192
- if block_given? && content_or_options.is_a?(Hash)
193
- options = content_or_options = content_or_options.stringify_keys
194
- else
195
- options ||= {}
196
- options = options.stringify_keys
197
- end
198
- options["for"] = sanitize_to_id(name) unless name.blank? || options.has_key?("for")
199
- content_tag :label, content_or_options || name.to_s.humanize, options, &block
200
- end
201
-
202
- # Creates a hidden form input field used to transmit data that would be lost due to HTTP's statelessness or
203
- # data that should be hidden from the user.
204
- #
205
- # ==== Options
206
- # * Creates standard HTML attributes for the tag.
207
- #
208
- # ==== Examples
209
- # hidden_field_tag 'tags_list'
210
- # # => <input id="tags_list" name="tags_list" type="hidden" />
211
- #
212
- # hidden_field_tag 'token', 'VUBJKB23UIVI1UU1VOBVI@'
213
- # # => <input id="token" name="token" type="hidden" value="VUBJKB23UIVI1UU1VOBVI@" />
214
- #
215
- # hidden_field_tag 'collected_input', '', onchange: "alert('Input collected!')"
216
- # # => <input id="collected_input" name="collected_input" onchange="alert('Input collected!')"
217
- # # type="hidden" value="" />
218
- def hidden_field_tag(name, value = nil, options = {})
219
- text_field_tag(name, value, options.stringify_keys.update("type" => "hidden"))
220
- end
221
-
222
- # Creates a file upload field. If you are using file uploads then you will also need
223
- # to set the multipart option for the form tag:
224
- #
225
- # <%= form_tag '/upload', multipart: true do %>
226
- # <label for="file">File to Upload</label> <%= file_field_tag "file" %>
227
- # <%= submit_tag %>
228
- # <% end %>
229
- #
230
- # The specified URL will then be passed a File object containing the selected file, or if the field
231
- # was left blank, a StringIO object.
232
- #
233
- # ==== Options
234
- # * Creates standard HTML attributes for the tag.
235
- # * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
236
- # * <tt>:multiple</tt> - If set to true, *in most updated browsers* the user will be allowed to select multiple files.
237
- # * <tt>:accept</tt> - If set to one or multiple mime-types, the user will be suggested a filter when choosing a file. You still need to set up model validations.
238
- #
239
- # ==== Examples
240
- # file_field_tag 'attachment'
241
- # # => <input id="attachment" name="attachment" type="file" />
242
- #
243
- # file_field_tag 'avatar', class: 'profile_input'
244
- # # => <input class="profile_input" id="avatar" name="avatar" type="file" />
245
- #
246
- # file_field_tag 'picture', disabled: true
247
- # # => <input disabled="disabled" id="picture" name="picture" type="file" />
248
- #
249
- # file_field_tag 'resume', value: '~/resume.doc'
250
- # # => <input id="resume" name="resume" type="file" value="~/resume.doc" />
251
- #
252
- # file_field_tag 'user_pic', accept: 'image/png,image/gif,image/jpeg'
253
- # # => <input accept="image/png,image/gif,image/jpeg" id="user_pic" name="user_pic" type="file" />
254
- #
255
- # file_field_tag 'file', accept: 'text/html', class: 'upload', value: 'index.html'
256
- # # => <input accept="text/html" class="upload" id="file" name="file" type="file" value="index.html" />
257
- def file_field_tag(name, options = {})
258
- text_field_tag(name, nil, options.update("type" => "file"))
259
- end
260
-
261
- # Creates a password field, a masked text field that will hide the users input behind a mask character.
262
- #
263
- # ==== Options
264
- # * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
265
- # * <tt>:size</tt> - The number of visible characters that will fit in the input.
266
- # * <tt>:maxlength</tt> - The maximum number of characters that the browser will allow the user to enter.
267
- # * Any other key creates standard HTML attributes for the tag.
268
- #
269
- # ==== Examples
270
- # password_field_tag 'pass'
271
- # # => <input id="pass" name="pass" type="password" />
272
- #
273
- # password_field_tag 'secret', 'Your secret here'
274
- # # => <input id="secret" name="secret" type="password" value="Your secret here" />
275
- #
276
- # password_field_tag 'masked', nil, class: 'masked_input_field'
277
- # # => <input class="masked_input_field" id="masked" name="masked" type="password" />
278
- #
279
- # password_field_tag 'token', '', size: 15
280
- # # => <input id="token" name="token" size="15" type="password" value="" />
281
- #
282
- # password_field_tag 'key', nil, maxlength: 16
283
- # # => <input id="key" maxlength="16" name="key" type="password" />
284
- #
285
- # password_field_tag 'confirm_pass', nil, disabled: true
286
- # # => <input disabled="disabled" id="confirm_pass" name="confirm_pass" type="password" />
287
- #
288
- # password_field_tag 'pin', '1234', maxlength: 4, size: 6, class: "pin_input"
289
- # # => <input class="pin_input" id="pin" maxlength="4" name="pin" size="6" type="password" value="1234" />
290
- def password_field_tag(name = "password", value = nil, options = {})
291
- text_field_tag(name, value, options.update("type" => "password"))
292
- end
293
-
294
- # Creates a text input area; use a textarea for longer text inputs such as blog posts or descriptions.
295
- #
296
- # ==== Options
297
- # * <tt>:size</tt> - A string specifying the dimensions (columns by rows) of the textarea (e.g., "25x10").
298
- # * <tt>:rows</tt> - Specify the number of rows in the textarea
299
- # * <tt>:cols</tt> - Specify the number of columns in the textarea
300
- # * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
301
- # * <tt>:escape</tt> - By default, the contents of the text input are HTML escaped.
302
- # If you need unescaped contents, set this to false.
303
- # * Any other key creates standard HTML attributes for the tag.
304
- #
305
- # ==== Examples
306
- # text_area_tag 'post'
307
- # # => <textarea id="post" name="post"></textarea>
308
- #
309
- # text_area_tag 'bio', @user.bio
310
- # # => <textarea id="bio" name="bio">This is my biography.</textarea>
311
- #
312
- # text_area_tag 'body', nil, rows: 10, cols: 25
313
- # # => <textarea cols="25" id="body" name="body" rows="10"></textarea>
314
- #
315
- # text_area_tag 'body', nil, size: "25x10"
316
- # # => <textarea name="body" id="body" cols="25" rows="10"></textarea>
317
- #
318
- # text_area_tag 'description', "Description goes here.", disabled: true
319
- # # => <textarea disabled="disabled" id="description" name="description">Description goes here.</textarea>
320
- #
321
- # text_area_tag 'comment', nil, class: 'comment_input'
322
- # # => <textarea class="comment_input" id="comment" name="comment"></textarea>
323
- def text_area_tag(name, content = nil, options = {})
324
- options = options.stringify_keys
325
-
326
- if size = options.delete("size")
327
- options["cols"], options["rows"] = size.split("x") if size.respond_to?(:split)
328
- end
329
-
330
- escape = options.delete("escape") { true }
331
- content = ERB::Util.html_escape(content) if escape
332
-
333
- content_tag :textarea, content.to_s.html_safe, { "name" => name, "id" => sanitize_to_id(name) }.update(options)
334
- end
335
-
336
- # Creates a check box form input tag.
337
- #
338
- # ==== Options
339
- # * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
340
- # * Any other key creates standard HTML options for the tag.
341
- #
342
- # ==== Examples
343
- # check_box_tag 'accept'
344
- # # => <input id="accept" name="accept" type="checkbox" value="1" />
345
- #
346
- # check_box_tag 'rock', 'rock music'
347
- # # => <input id="rock" name="rock" type="checkbox" value="rock music" />
348
- #
349
- # check_box_tag 'receive_email', 'yes', true
350
- # # => <input checked="checked" id="receive_email" name="receive_email" type="checkbox" value="yes" />
351
- #
352
- # check_box_tag 'tos', 'yes', false, class: 'accept_tos'
353
- # # => <input class="accept_tos" id="tos" name="tos" type="checkbox" value="yes" />
354
- #
355
- # check_box_tag 'eula', 'accepted', false, disabled: true
356
- # # => <input disabled="disabled" id="eula" name="eula" type="checkbox" value="accepted" />
357
- def check_box_tag(name, value = "1", checked = false, options = {})
358
- html_options = { "type" => "checkbox", "name" => name, "id" => sanitize_to_id(name), "value" => value }.update(options.stringify_keys)
359
- html_options["checked"] = "checked" if checked
360
- tag :input, html_options
361
- end
362
-
363
- # Creates a radio button; use groups of radio buttons named the same to allow users to
364
- # select from a group of options.
365
- #
366
- # ==== Options
367
- # * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
368
- # * Any other key creates standard HTML options for the tag.
369
- #
370
- # ==== Examples
371
- # radio_button_tag 'gender', 'male'
372
- # # => <input id="gender_male" name="gender" type="radio" value="male" />
373
- #
374
- # radio_button_tag 'receive_updates', 'no', true
375
- # # => <input checked="checked" id="receive_updates_no" name="receive_updates" type="radio" value="no" />
376
- #
377
- # radio_button_tag 'time_slot', "3:00 p.m.", false, disabled: true
378
- # # => <input disabled="disabled" id="time_slot_300_pm" name="time_slot" type="radio" value="3:00 p.m." />
379
- #
380
- # radio_button_tag 'color', "green", true, class: "color_input"
381
- # # => <input checked="checked" class="color_input" id="color_green" name="color" type="radio" value="green" />
382
- def radio_button_tag(name, value, checked = false, options = {})
383
- html_options = { "type" => "radio", "name" => name, "id" => "#{sanitize_to_id(name)}_#{sanitize_to_id(value)}", "value" => value }.update(options.stringify_keys)
384
- html_options["checked"] = "checked" if checked
385
- tag :input, html_options
386
- end
387
-
388
- # Creates a submit button with the text <tt>value</tt> as the caption.
389
- #
390
- # ==== Options
391
- # * <tt>:data</tt> - This option can be used to add custom data attributes.
392
- # * <tt>:disabled</tt> - If true, the user will not be able to use this input.
393
- # * Any other key creates standard HTML options for the tag.
394
- #
395
- # ==== Data attributes
396
- #
397
- # * <tt>confirm: 'question?'</tt> - If present the unobtrusive JavaScript
398
- # drivers will provide a prompt with the question specified. If the user accepts,
399
- # the form is processed normally, otherwise no action is taken.
400
- # * <tt>:disable_with</tt> - Value of this parameter will be used as the value for a
401
- # disabled version of the submit button when the form is submitted. This feature is
402
- # provided by the unobtrusive JavaScript driver.
403
- #
404
- # ==== Examples
405
- # submit_tag
406
- # # => <input name="commit" type="submit" value="Save changes" />
407
- #
408
- # submit_tag "Edit this article"
409
- # # => <input name="commit" type="submit" value="Edit this article" />
410
- #
411
- # submit_tag "Save edits", disabled: true
412
- # # => <input disabled="disabled" name="commit" type="submit" value="Save edits" />
413
- #
414
- # submit_tag "Complete sale", data: { disable_with: "Please wait..." }
415
- # # => <input name="commit" data-disable-with="Please wait..." type="submit" value="Complete sale" />
416
- #
417
- # submit_tag nil, class: "form_submit"
418
- # # => <input class="form_submit" name="commit" type="submit" />
419
- #
420
- # submit_tag "Edit", class: "edit_button"
421
- # # => <input class="edit_button" name="commit" type="submit" value="Edit" />
422
- #
423
- # submit_tag "Save", data: { confirm: "Are you sure?" }
424
- # # => <input name='commit' type='submit' value='Save' data-confirm="Are you sure?" />
425
- #
426
- def submit_tag(value = "Save changes", options = {})
427
- options = options.stringify_keys
428
-
429
- if disable_with = options.delete("disable_with")
430
- message = ":disable_with option is deprecated and will be removed from Rails 4.1. " \
431
- "Use 'data: { disable_with: \'Text\' }' instead."
432
- ActiveSupport::Deprecation.warn message
433
-
434
- options["data-disable-with"] = disable_with
435
- end
436
-
437
- if confirm = options.delete("confirm")
438
- message = ":confirm option is deprecated and will be removed from Rails 4.1. " \
439
- "Use 'data: { confirm: \'Text\' }' instead'."
440
- ActiveSupport::Deprecation.warn message
441
-
442
- options["data-confirm"] = confirm
443
- end
444
-
445
- tag :input, { "type" => "submit", "name" => "commit", "value" => value }.update(options)
446
- end
447
-
448
- # Creates a button element that defines a <tt>submit</tt> button,
449
- # <tt>reset</tt>button or a generic button which can be used in
450
- # JavaScript, for example. You can use the button tag as a regular
451
- # submit tag but it isn't supported in legacy browsers. However,
452
- # the button tag allows richer labels such as images and emphasis,
453
- # so this helper will also accept a block.
454
- #
455
- # ==== Options
456
- # * <tt>:data</tt> - This option can be used to add custom data attributes.
457
- # * <tt>:disabled</tt> - If true, the user will not be able to
458
- # use this input.
459
- # * Any other key creates standard HTML options for the tag.
460
- #
461
- # ==== Data attributes
462
- #
463
- # * <tt>confirm: 'question?'</tt> - If present, the
464
- # unobtrusive JavaScript drivers will provide a prompt with
465
- # the question specified. If the user accepts, the form is
466
- # processed normally, otherwise no action is taken.
467
- # * <tt>:disable_with</tt> - Value of this parameter will be
468
- # used as the value for a disabled version of the submit
469
- # button when the form is submitted. This feature is provided
470
- # by the unobtrusive JavaScript driver.
471
- #
472
- # ==== Examples
473
- # button_tag
474
- # # => <button name="button" type="submit">Button</button>
475
- #
476
- # button_tag(type: 'button') do
477
- # content_tag(:strong, 'Ask me!')
478
- # end
479
- # # => <button name="button" type="button">
480
- # # <strong>Ask me!</strong>
481
- # # </button>
482
- #
483
- # button_tag "Checkout", data: { disable_with => "Please wait..." }
484
- # # => <button data-disable-with="Please wait..." name="button" type="submit">Checkout</button>
485
- #
486
- def button_tag(content_or_options = nil, options = nil, &block)
487
- options = content_or_options if block_given? && content_or_options.is_a?(Hash)
488
- options ||= {}
489
- options = options.stringify_keys
490
-
491
- if disable_with = options.delete("disable_with")
492
- message = ":disable_with option is deprecated and will be removed from Rails 4.1. " \
493
- "Use 'data: { disable_with: \'Text\' }' instead."
494
- ActiveSupport::Deprecation.warn message
495
-
496
- options["data-disable-with"] = disable_with
497
- end
498
-
499
- if confirm = options.delete("confirm")
500
- message = ":confirm option is deprecated and will be removed from Rails 4.1. " \
501
- "Use 'data: { confirm: \'Text\' }' instead'."
502
- ActiveSupport::Deprecation.warn message
503
-
504
- options["data-confirm"] = confirm
505
- end
506
-
507
- options.reverse_merge! 'name' => 'button', 'type' => 'submit'
508
-
509
- content_tag :button, content_or_options || 'Button', options, &block
510
- end
511
-
512
- # Displays an image which when clicked will submit the form.
513
- #
514
- # <tt>source</tt> is passed to AssetTagHelper#path_to_image
515
- #
516
- # ==== Options
517
- # * <tt>:data</tt> - This option can be used to add custom data attributes.
518
- # * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
519
- # * Any other key creates standard HTML options for the tag.
520
- #
521
- # ==== Data attributes
522
- #
523
- # * <tt>confirm: 'question?'</tt> - This will add a JavaScript confirm
524
- # prompt with the question specified. If the user accepts, the form is
525
- # processed normally, otherwise no action is taken.
526
- #
527
- # ==== Examples
528
- # image_submit_tag("login.png")
529
- # # => <input alt="Login" src="/images/login.png" type="image" />
530
- #
531
- # image_submit_tag("purchase.png", disabled: true)
532
- # # => <input alt="Purchase" disabled="disabled" src="/images/purchase.png" type="image" />
533
- #
534
- # image_submit_tag("search.png", class: 'search_button', alt: 'Find')
535
- # # => <input alt="Find" class="search_button" src="/images/search.png" type="image" />
536
- #
537
- # image_submit_tag("agree.png", disabled: true, class: "agree_disagree_button")
538
- # # => <input alt="Agree" class="agree_disagree_button" disabled="disabled" src="/images/agree.png" type="image" />
539
- #
540
- # image_submit_tag("save.png", data: { confirm: "Are you sure?" })
541
- # # => <input alt="Save" src="/images/save.png" data-confirm="Are you sure?" type="image" />
542
- def image_submit_tag(source, options = {})
543
- options = options.stringify_keys
544
-
545
- if confirm = options.delete("confirm")
546
- message = ":confirm option is deprecated and will be removed from Rails 4.1. " \
547
- "Use 'data: { confirm: \'Text\' }' instead'."
548
- ActiveSupport::Deprecation.warn message
549
-
550
- options["data-confirm"] = confirm
551
- end
552
-
553
- tag :input, { "alt" => image_alt(source), "type" => "image", "src" => path_to_image(source) }.update(options)
554
- end
555
-
556
- # Creates a field set for grouping HTML form elements.
557
- #
558
- # <tt>legend</tt> will become the fieldset's title (optional as per W3C).
559
- # <tt>options</tt> accept the same values as tag.
560
- #
561
- # ==== Examples
562
- # <%= field_set_tag do %>
563
- # <p><%= text_field_tag 'name' %></p>
564
- # <% end %>
565
- # # => <fieldset><p><input id="name" name="name" type="text" /></p></fieldset>
566
- #
567
- # <%= field_set_tag 'Your details' do %>
568
- # <p><%= text_field_tag 'name' %></p>
569
- # <% end %>
570
- # # => <fieldset><legend>Your details</legend><p><input id="name" name="name" type="text" /></p></fieldset>
571
- #
572
- # <%= field_set_tag nil, class: 'format' do %>
573
- # <p><%= text_field_tag 'name' %></p>
574
- # <% end %>
575
- # # => <fieldset class="format"><p><input id="name" name="name" type="text" /></p></fieldset>
576
- def field_set_tag(legend = nil, options = nil, &block)
577
- output = tag(:fieldset, options, true)
578
- output.safe_concat(content_tag(:legend, legend)) unless legend.blank?
579
- output.concat(capture(&block)) if block_given?
580
- output.safe_concat("</fieldset>")
581
- end
582
-
583
- # Creates a text field of type "color".
584
- #
585
- # ==== Options
586
- # * Accepts the same options as text_field_tag.
587
- def color_field_tag(name, value = nil, options = {})
588
- text_field_tag(name, value, options.stringify_keys.update("type" => "color"))
589
- end
590
-
591
- # Creates a text field of type "search".
592
- #
593
- # ==== Options
594
- # * Accepts the same options as text_field_tag.
595
- def search_field_tag(name, value = nil, options = {})
596
- text_field_tag(name, value, options.stringify_keys.update("type" => "search"))
597
- end
598
-
599
- # Creates a text field of type "tel".
600
- #
601
- # ==== Options
602
- # * Accepts the same options as text_field_tag.
603
- def telephone_field_tag(name, value = nil, options = {})
604
- text_field_tag(name, value, options.stringify_keys.update("type" => "tel"))
605
- end
606
- alias phone_field_tag telephone_field_tag
607
-
608
- # Creates a text field of type "date".
609
- #
610
- # ==== Options
611
- # * Accepts the same options as text_field_tag.
612
- def date_field_tag(name, value = nil, options = {})
613
- text_field_tag(name, value, options.stringify_keys.update("type" => "date"))
614
- end
615
-
616
- # Creates a text field of type "time".
617
- #
618
- # === Options
619
- # * <tt>:min</tt> - The minimum acceptable value.
620
- # * <tt>:max</tt> - The maximum acceptable value.
621
- # * <tt>:step</tt> - The acceptable value granularity.
622
- # * Otherwise accepts the same options as text_field_tag.
623
- def time_field_tag(name, value = nil, options = {})
624
- text_field_tag(name, value, options.stringify_keys.update("type" => "time"))
625
- end
626
-
627
- # Creates a text field of type "datetime".
628
- #
629
- # === Options
630
- # * <tt>:min</tt> - The minimum acceptable value.
631
- # * <tt>:max</tt> - The maximum acceptable value.
632
- # * <tt>:step</tt> - The acceptable value granularity.
633
- # * Otherwise accepts the same options as text_field_tag.
634
- def datetime_field_tag(name, value = nil, options = {})
635
- text_field_tag(name, value, options.stringify_keys.update("type" => "datetime"))
636
- end
637
-
638
- # Creates a text field of type "datetime-local".
639
- #
640
- # === Options
641
- # * <tt>:min</tt> - The minimum acceptable value.
642
- # * <tt>:max</tt> - The maximum acceptable value.
643
- # * <tt>:step</tt> - The acceptable value granularity.
644
- # * Otherwise accepts the same options as text_field_tag.
645
- def datetime_local_field_tag(name, value = nil, options = {})
646
- text_field_tag(name, value, options.stringify_keys.update("type" => "datetime-local"))
647
- end
648
-
649
- # Creates a text field of type "month".
650
- #
651
- # === Options
652
- # * <tt>:min</tt> - The minimum acceptable value.
653
- # * <tt>:max</tt> - The maximum acceptable value.
654
- # * <tt>:step</tt> - The acceptable value granularity.
655
- # * Otherwise accepts the same options as text_field_tag.
656
- def month_field_tag(name, value = nil, options = {})
657
- text_field_tag(name, value, options.stringify_keys.update("type" => "month"))
658
- end
659
-
660
- # Creates a text field of type "week".
661
- #
662
- # === Options
663
- # * <tt>:min</tt> - The minimum acceptable value.
664
- # * <tt>:max</tt> - The maximum acceptable value.
665
- # * <tt>:step</tt> - The acceptable value granularity.
666
- # * Otherwise accepts the same options as text_field_tag.
667
- def week_field_tag(name, value = nil, options = {})
668
- text_field_tag(name, value, options.stringify_keys.update("type" => "week"))
669
- end
670
-
671
- # Creates a text field of type "url".
672
- #
673
- # ==== Options
674
- # * Accepts the same options as text_field_tag.
675
- def url_field_tag(name, value = nil, options = {})
676
- text_field_tag(name, value, options.stringify_keys.update("type" => "url"))
677
- end
678
-
679
- # Creates a text field of type "email".
680
- #
681
- # ==== Options
682
- # * Accepts the same options as text_field_tag.
683
- def email_field_tag(name, value = nil, options = {})
684
- text_field_tag(name, value, options.stringify_keys.update("type" => "email"))
685
- end
686
-
687
- # Creates a number field.
688
- #
689
- # ==== Options
690
- # * <tt>:min</tt> - The minimum acceptable value.
691
- # * <tt>:max</tt> - The maximum acceptable value.
692
- # * <tt>:in</tt> - A range specifying the <tt>:min</tt> and
693
- # <tt>:max</tt> values.
694
- # * <tt>:step</tt> - The acceptable value granularity.
695
- # * Otherwise accepts the same options as text_field_tag.
696
- #
697
- # ==== Examples
698
- # number_field_tag 'quantity', nil, in: 1...10
699
- # # => <input id="quantity" name="quantity" min="1" max="9" type="number" />
700
- def number_field_tag(name, value = nil, options = {})
701
- options = options.stringify_keys
702
- options["type"] ||= "number"
703
- if range = options.delete("in") || options.delete("within")
704
- options.update("min" => range.min, "max" => range.max)
705
- end
706
- text_field_tag(name, value, options)
707
- end
708
-
709
- # Creates a range form element.
710
- #
711
- # ==== Options
712
- # * Accepts the same options as number_field_tag.
713
- def range_field_tag(name, value = nil, options = {})
714
- number_field_tag(name, value, options.stringify_keys.update("type" => "range"))
715
- end
716
-
717
- # Creates the hidden UTF8 enforcer tag. Override this method in a helper
718
- # to customize the tag.
719
- def utf8_enforcer_tag
720
- tag(:input, :type => "hidden", :name => "utf8", :value => "&#x2713;".html_safe)
721
- end
722
-
723
- private
724
- def html_options_for_form(url_for_options, options)
725
- options.stringify_keys.tap do |html_options|
726
- html_options["enctype"] = "multipart/form-data" if html_options.delete("multipart")
727
- # The following URL is unescaped, this is just a hash of options, and it is the
728
- # responsibility of the caller to escape all the values.
729
- html_options["action"] = url_for(url_for_options)
730
- html_options["accept-charset"] = "UTF-8"
731
-
732
- html_options["data-remote"] = true if html_options.delete("remote")
733
-
734
- if html_options["data-remote"] &&
735
- !embed_authenticity_token_in_remote_forms &&
736
- html_options["authenticity_token"].blank?
737
- # The authenticity token is taken from the meta tag in this case
738
- html_options["authenticity_token"] = false
739
- elsif html_options["authenticity_token"] == true
740
- # Include the default authenticity_token, which is only generated when its set to nil,
741
- # but we needed the true value to override the default of no authenticity_token on data-remote.
742
- html_options["authenticity_token"] = nil
743
- end
744
- end
745
- end
746
-
747
- def extra_tags_for_form(html_options)
748
- authenticity_token = html_options.delete("authenticity_token")
749
- method = html_options.delete("method").to_s
750
-
751
- method_tag = case method
752
- when /^get$/i # must be case-insensitive, but can't use downcase as might be nil
753
- html_options["method"] = "get"
754
- ''
755
- when /^post$/i, "", nil
756
- html_options["method"] = "post"
757
- token_tag(authenticity_token)
758
- else
759
- html_options["method"] = "post"
760
- method_tag(method) + token_tag(authenticity_token)
761
- end
762
-
763
- tags = utf8_enforcer_tag << method_tag
764
- content_tag(:div, tags, :style => 'margin:0;padding:0;display:inline')
765
- end
766
-
767
- def form_tag_html(html_options)
768
- extra_tags = extra_tags_for_form(html_options)
769
- tag(:form, html_options, true) + extra_tags
770
- end
771
-
772
- def form_tag_in_block(html_options, &block)
773
- content = capture(&block)
774
- output = form_tag_html(html_options)
775
- output << content
776
- output.safe_concat("</form>")
777
- end
778
-
779
- # see http://www.w3.org/TR/html4/types.html#type-name
780
- def sanitize_to_id(name)
781
- name.to_s.delete(']').gsub(/[^-a-zA-Z0-9:.]/, "_")
782
- end
783
- end
784
- end
785
- end