actionview 6.1.5 → 7.0.0.alpha1

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

Potentially problematic release.


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

Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +90 -332
  3. data/MIT-LICENSE +2 -1
  4. data/lib/action_view/base.rb +3 -3
  5. data/lib/action_view/buffers.rb +2 -2
  6. data/lib/action_view/cache_expiry.rb +46 -32
  7. data/lib/action_view/dependency_tracker/erb_tracker.rb +154 -0
  8. data/lib/action_view/dependency_tracker/ripper_tracker.rb +59 -0
  9. data/lib/action_view/dependency_tracker.rb +6 -147
  10. data/lib/action_view/digestor.rb +7 -4
  11. data/lib/action_view/flows.rb +4 -4
  12. data/lib/action_view/gem_version.rb +4 -4
  13. data/lib/action_view/helpers/active_model_helper.rb +1 -1
  14. data/lib/action_view/helpers/asset_tag_helper.rb +84 -29
  15. data/lib/action_view/helpers/asset_url_helper.rb +7 -7
  16. data/lib/action_view/helpers/atom_feed_helper.rb +3 -4
  17. data/lib/action_view/helpers/cache_helper.rb +51 -3
  18. data/lib/action_view/helpers/capture_helper.rb +2 -2
  19. data/lib/action_view/helpers/controller_helper.rb +2 -2
  20. data/lib/action_view/helpers/csp_helper.rb +1 -1
  21. data/lib/action_view/helpers/csrf_helper.rb +1 -1
  22. data/lib/action_view/helpers/date_helper.rb +6 -7
  23. data/lib/action_view/helpers/debug_helper.rb +3 -1
  24. data/lib/action_view/helpers/form_helper.rb +72 -12
  25. data/lib/action_view/helpers/form_options_helper.rb +65 -33
  26. data/lib/action_view/helpers/form_tag_helper.rb +75 -32
  27. data/lib/action_view/helpers/javascript_helper.rb +3 -5
  28. data/lib/action_view/helpers/number_helper.rb +3 -4
  29. data/lib/action_view/helpers/output_safety_helper.rb +2 -2
  30. data/lib/action_view/helpers/rendering_helper.rb +1 -1
  31. data/lib/action_view/helpers/sanitize_helper.rb +2 -2
  32. data/lib/action_view/helpers/tag_helper.rb +17 -4
  33. data/lib/action_view/helpers/tags/base.rb +3 -15
  34. data/lib/action_view/helpers/tags/check_box.rb +2 -2
  35. data/lib/action_view/helpers/tags/collection_select.rb +1 -1
  36. data/lib/action_view/helpers/tags/hidden_field.rb +0 -4
  37. data/lib/action_view/helpers/tags/time_field.rb +10 -1
  38. data/lib/action_view/helpers/tags/weekday_select.rb +27 -0
  39. data/lib/action_view/helpers/tags.rb +3 -2
  40. data/lib/action_view/helpers/text_helper.rb +24 -13
  41. data/lib/action_view/helpers/translation_helper.rb +1 -2
  42. data/lib/action_view/helpers/url_helper.rb +102 -77
  43. data/lib/action_view/helpers.rb +25 -25
  44. data/lib/action_view/lookup_context.rb +33 -52
  45. data/lib/action_view/model_naming.rb +1 -1
  46. data/lib/action_view/path_set.rb +16 -22
  47. data/lib/action_view/railtie.rb +14 -1
  48. data/lib/action_view/render_parser.rb +188 -0
  49. data/lib/action_view/renderer/abstract_renderer.rb +2 -2
  50. data/lib/action_view/renderer/partial_renderer.rb +0 -34
  51. data/lib/action_view/renderer/renderer.rb +4 -4
  52. data/lib/action_view/renderer/streaming_template_renderer.rb +3 -3
  53. data/lib/action_view/renderer/template_renderer.rb +6 -2
  54. data/lib/action_view/rendering.rb +2 -2
  55. data/lib/action_view/ripper_ast_parser.rb +198 -0
  56. data/lib/action_view/routing_url_for.rb +1 -1
  57. data/lib/action_view/template/error.rb +108 -13
  58. data/lib/action_view/template/handlers/erb.rb +6 -0
  59. data/lib/action_view/template/handlers.rb +3 -3
  60. data/lib/action_view/template/html.rb +3 -3
  61. data/lib/action_view/template/inline.rb +3 -3
  62. data/lib/action_view/template/raw_file.rb +3 -3
  63. data/lib/action_view/template/resolver.rb +84 -311
  64. data/lib/action_view/template/text.rb +3 -3
  65. data/lib/action_view/template/types.rb +14 -12
  66. data/lib/action_view/template.rb +10 -1
  67. data/lib/action_view/template_details.rb +66 -0
  68. data/lib/action_view/template_path.rb +64 -0
  69. data/lib/action_view/test_case.rb +6 -2
  70. data/lib/action_view/testing/resolvers.rb +11 -12
  71. data/lib/action_view/unbound_template.rb +33 -7
  72. data/lib/action_view.rb +3 -4
  73. metadata +22 -16
@@ -3,7 +3,7 @@
3
3
  module ActionView
4
4
  module Helpers
5
5
  module Tags # :nodoc:
6
- class CollectionSelect < Base #:nodoc:
6
+ class CollectionSelect < Base # :nodoc:
7
7
  def initialize(object_name, method_name, template_object, collection, value_method, text_method, options, html_options)
8
8
  @collection = collection
9
9
  @value_method = value_method
@@ -4,10 +4,6 @@ module ActionView
4
4
  module Helpers
5
5
  module Tags # :nodoc:
6
6
  class HiddenField < TextField # :nodoc:
7
- def render
8
- @options[:autocomplete] = "off"
9
- super
10
- end
11
7
  end
12
8
  end
13
9
  end
@@ -4,9 +4,18 @@ module ActionView
4
4
  module Helpers
5
5
  module Tags # :nodoc:
6
6
  class TimeField < DatetimeField # :nodoc:
7
+ def initialize(object_name, method_name, template_object, options = {})
8
+ @include_seconds = options.delete(:include_seconds) { true }
9
+ super
10
+ end
11
+
7
12
  private
8
13
  def format_date(value)
9
- value&.strftime("%T.%L")
14
+ if @include_seconds
15
+ value&.strftime("%T.%L")
16
+ else
17
+ value&.strftime("%H:%M")
18
+ end
10
19
  end
11
20
  end
12
21
  end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionView
4
+ module Helpers
5
+ module Tags # :nodoc:
6
+ class WeekdaySelect < Base # :nodoc:
7
+ def initialize(object_name, method_name, template_object, options, html_options)
8
+ @html_options = html_options
9
+
10
+ super(object_name, method_name, template_object, options)
11
+ end
12
+
13
+ def render
14
+ select_content_tag(
15
+ weekday_options_for_select(
16
+ value || @options[:selected],
17
+ index_as_value: @options.fetch(:index_as_value, false),
18
+ day_format: @options.fetch(:day_format, :day_names)
19
+ ),
20
+ @options,
21
+ @html_options
22
+ )
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActionView
4
- module Helpers #:nodoc:
5
- module Tags #:nodoc:
4
+ module Helpers # :nodoc:
5
+ module Tags # :nodoc:
6
6
  extend ActiveSupport::Autoload
7
7
 
8
8
  eager_autoload do
@@ -38,6 +38,7 @@ module ActionView
38
38
  autoload :TimeZoneSelect
39
39
  autoload :UrlField
40
40
  autoload :WeekField
41
+ autoload :WeekdaySelect
41
42
  end
42
43
  end
43
44
  end
@@ -1,11 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/core_ext/string/filters"
4
+ require "active_support/core_ext/string/access"
4
5
  require "active_support/core_ext/array/extract_options"
6
+ require "action_view/helpers/sanitize_helper"
7
+ require "action_view/helpers/tag_helper"
8
+ require "action_view/helpers/output_safety_helper"
5
9
 
6
10
  module ActionView
7
11
  # = Action View Text Helpers
8
- module Helpers #:nodoc:
12
+ module Helpers # :nodoc:
9
13
  # The TextHelper module provides a set of methods for filtering, formatting
10
14
  # and transforming strings, which can reduce the amount of inline Ruby code in
11
15
  # your views. These helper methods extend Action View making them callable
@@ -129,7 +133,7 @@ module ActionView
129
133
  #
130
134
  # highlight('<a href="javascript:alert(\'no!\')">ruby</a> on rails', 'rails', sanitize: false)
131
135
  # # => <a href="javascript:alert('no!')">ruby</a> on <mark>rails</mark>
132
- def highlight(text, phrases, options = {})
136
+ def highlight(text, phrases, options = {}, &block)
133
137
  text = sanitize(text) if options.fetch(:sanitize, true)
134
138
 
135
139
  if text.blank? || phrases.blank?
@@ -140,7 +144,7 @@ module ActionView
140
144
  end.join("|")
141
145
 
142
146
  if block_given?
143
- text.gsub(/(#{match})(?![^<]*?>)/i) { |found| yield found }
147
+ text.gsub(/(#{match})(?![^<]*?>)/i, &block)
144
148
  else
145
149
  highlighter = options.fetch(:highlighter, '<mark>\1</mark>')
146
150
  text.gsub(/(#{match})(?![^<]*?>)/i, highlighter)
@@ -403,7 +407,7 @@ module ActionView
403
407
  cycle.reset if cycle
404
408
  end
405
409
 
406
- class Cycle #:nodoc:
410
+ class Cycle # :nodoc:
407
411
  attr_reader :values
408
412
 
409
413
  def initialize(first_value, *values)
@@ -467,18 +471,25 @@ module ActionView
467
471
  radius = options.fetch(:radius, 100)
468
472
  omission = options.fetch(:omission, "...")
469
473
 
470
- part = part.split(separator)
471
- part.delete("")
472
- affix = part.size > radius ? omission : ""
474
+ if separator != ""
475
+ part = part.split(separator)
476
+ part.delete("")
477
+ end
473
478
 
474
- part = if part_position == :first
475
- drop_index = [part.length - radius, 0].max
476
- part.drop(drop_index)
477
- else
478
- part.first(radius)
479
+ affix = part.length > radius ? omission : ""
480
+
481
+ part =
482
+ if part_position == :first
483
+ part.last(radius)
484
+ else
485
+ part.first(radius)
486
+ end
487
+
488
+ if separator != ""
489
+ part = part.join(separator)
479
490
  end
480
491
 
481
- return affix, part.join(separator)
492
+ return affix, part
482
493
  end
483
494
  end
484
495
  end
@@ -1,11 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "action_view/helpers/tag_helper"
4
- require "active_support/core_ext/symbol/starts_ends_with"
5
4
 
6
5
  module ActionView
7
6
  # = Action View Translation Helpers
8
- module Helpers #:nodoc:
7
+ module Helpers # :nodoc:
9
8
  module TranslationHelper
10
9
  extend ActiveSupport::Concern
11
10
 
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "action_view/helpers/javascript_helper"
4
3
  require "active_support/core_ext/array/access"
5
4
  require "active_support/core_ext/hash/keys"
6
5
  require "active_support/core_ext/string/output_safety"
6
+ require "action_view/helpers/tag_helper"
7
7
 
8
8
  module ActionView
9
9
  # = Action View URL Helpers
10
- module Helpers #:nodoc:
10
+ module Helpers # :nodoc:
11
11
  # Provides a set of methods for making links and getting URLs that
12
12
  # depend on the routing subsystem (see ActionDispatch::Routing).
13
13
  # This allows you to use the same format for links in views
@@ -29,6 +29,8 @@ module ActionView
29
29
  end
30
30
  end
31
31
 
32
+ mattr_accessor :button_to_generates_button_tag, default: false
33
+
32
34
  # Basic implementation of url_for to allow use helpers without routes existence
33
35
  def url_for(options = nil) # :nodoc:
34
36
  case options
@@ -101,17 +103,8 @@ module ActionView
101
103
  # completion of the Ajax request and performing JavaScript operations once
102
104
  # they're complete
103
105
  #
104
- # ==== Data attributes
105
- #
106
- # * <tt>confirm: 'question?'</tt> - This will allow the unobtrusive JavaScript
107
- # driver to prompt with the question specified (in this case, the
108
- # resulting text would be <tt>question?</tt>. If the user accepts, the
109
- # link is processed normally, otherwise no action is taken.
110
- # * <tt>:disable_with</tt> - Value of this parameter will be used as the
111
- # name for a disabled version of the link. This feature is provided by
112
- # the unobtrusive JavaScript driver.
113
- #
114
106
  # ==== Examples
107
+ #
115
108
  # Because it relies on +url_for+, +link_to+ supports both older-style controller/action/id arguments
116
109
  # and newer RESTful routes. Current Rails style favors RESTful routes whenever possible, so base
117
110
  # your application on resources and use
@@ -184,15 +177,27 @@ module ActionView
184
177
  # link_to("Destroy", "http://www.example.com", method: :delete)
185
178
  # # => <a href='http://www.example.com' rel="nofollow" data-method="delete">Destroy</a>
186
179
  #
187
- # You can also use custom data attributes using the <tt>:data</tt> option:
188
- #
189
- # link_to "Visit Other Site", "http://www.rubyonrails.org/", data: { confirm: "Are you sure?" }
190
- # # => <a href="http://www.rubyonrails.org/" data-confirm="Are you sure?">Visit Other Site</a>
191
- #
192
180
  # Also you can set any link attributes such as <tt>target</tt>, <tt>rel</tt>, <tt>type</tt>:
193
181
  #
194
182
  # link_to "External link", "http://www.rubyonrails.org/", target: "_blank", rel: "nofollow"
195
183
  # # => <a href="http://www.rubyonrails.org/" target="_blank" rel="nofollow">External link</a>
184
+ #
185
+ # ==== Deprecated: Rails UJS attributes
186
+ #
187
+ # Prior to Rails 7, Rails shipped with a JavaScript library called @rails/ujs on by default. Following Rails 7,
188
+ # this library is no longer on by default. This library integrated with the following options:
189
+ #
190
+ # * <tt>confirm: 'question?'</tt> - This will allow the unobtrusive JavaScript
191
+ # driver to prompt with the question specified (in this case, the
192
+ # resulting text would be <tt>question?</tt>. If the user accepts, the
193
+ # link is processed normally, otherwise no action is taken.
194
+ # * <tt>:disable_with</tt> - Value of this parameter will be used as the
195
+ # name for a disabled version of the link. This feature is provided by
196
+ # the unobtrusive JavaScript driver.
197
+ #
198
+ # link_to "Visit Other Site", "http://www.rubyonrails.org/", data: { confirm: "Are you sure?" }
199
+ # # => <a href="http://www.rubyonrails.org/" data-confirm="Are you sure?">Visit Other Site</a>
200
+ #
196
201
  def link_to(name = nil, options = nil, html_options = nil, &block)
197
202
  html_options, options, name = options, name, block if block_given?
198
203
  options ||= {}
@@ -212,20 +217,24 @@ module ActionView
212
217
  # using the +link_to+ method with the <tt>:method</tt> modifier as described in
213
218
  # the +link_to+ documentation.
214
219
  #
215
- # By default, the generated form element has a class name of <tt>button_to</tt>
216
- # to allow styling of the form itself and its children. This can be changed
217
- # using the <tt>:form_class</tt> modifier within +html_options+. You can control
218
- # the form submission and input element behavior using +html_options+.
219
- # This method accepts the <tt>:method</tt> modifier described in the +link_to+ documentation.
220
- # If no <tt>:method</tt> modifier is given, it will default to performing a POST operation.
221
- # You can also disable the button by passing <tt>disabled: true</tt> in +html_options+.
222
- # If you are using RESTful routes, you can pass the <tt>:method</tt>
223
- # to change the HTTP verb used to submit the form.
220
+ # You can control the form and button behavior with +html_options+. Most
221
+ # values in +html_options+ are passed through to the button element. For
222
+ # example, passing a +:class+ option within +html_options+ will set the
223
+ # class attribute of the button element.
224
+ #
225
+ # The class attribute of the form element can be set by passing a
226
+ # +:form_class+ option within +html_options+. It defaults to
227
+ # <tt>"button_to"</tt> to allow styling of the form and its children.
228
+ #
229
+ # The form submits a POST request by default. You can specify a different
230
+ # HTTP verb via the +:method+ option within +html_options+.
224
231
  #
225
232
  # ==== Options
226
233
  # The +options+ hash accepts the same options as +url_for+.
227
234
  #
228
- # There are a few special +html_options+:
235
+ # Most values in +html_options+ are passed through to the button element,
236
+ # but there are a few special options:
237
+ #
229
238
  # * <tt>:method</tt> - \Symbol of HTTP verb. Supported verbs are <tt>:post</tt>, <tt>:get</tt>,
230
239
  # <tt>:delete</tt>, <tt>:patch</tt>, and <tt>:put</tt>. By default it will be <tt>:post</tt>.
231
240
  # * <tt>:disabled</tt> - If set to true, it will generate a disabled button.
@@ -250,12 +259,21 @@ module ActionView
250
259
  # ==== Examples
251
260
  # <%= button_to "New", action: "new" %>
252
261
  # # => "<form method="post" action="/controller/new" class="button_to">
253
- # # <input value="New" type="submit" />
262
+ # # <button type="submit">New</button>
263
+ # # <input name="authenticity_token" type="hidden" value="10f2163b45388899ad4d5ae948988266befcb6c3d1b2451cf657a0c293d605a6"/>
254
264
  # # </form>"
255
265
  #
256
266
  # <%= button_to "New", new_article_path %>
257
267
  # # => "<form method="post" action="/articles/new" class="button_to">
258
- # # <input value="New" type="submit" />
268
+ # # <button type="submit">New</button>
269
+ # # <input name="authenticity_token" type="hidden" value="10f2163b45388899ad4d5ae948988266befcb6c3d1b2451cf657a0c293d605a6"/>
270
+ # # </form>"
271
+ #
272
+ # <%= button_to "New", new_article_path, params: { time: Time.now } %>
273
+ # # => "<form method="post" action="/articles/new" class="button_to">
274
+ # # <button type="submit">New</button>
275
+ # # <input name="authenticity_token" type="hidden" value="10f2163b45388899ad4d5ae948988266befcb6c3d1b2451cf657a0c293d605a6"/>
276
+ # # <input type="hidden" name="time" value="2021-04-08 14:06:09 -0500">
259
277
  # # </form>"
260
278
  #
261
279
  # <%= button_to [:make_happy, @user] do %>
@@ -265,35 +283,34 @@ module ActionView
265
283
  # # <button type="submit">
266
284
  # # Make happy <strong><%= @user.name %></strong>
267
285
  # # </button>
286
+ # # <input name="authenticity_token" type="hidden" value="10f2163b45388899ad4d5ae948988266befcb6c3d1b2451cf657a0c293d605a6"/>
268
287
  # # </form>"
269
288
  #
270
289
  # <%= button_to "New", { action: "new" }, form_class: "new-thing" %>
271
290
  # # => "<form method="post" action="/controller/new" class="new-thing">
272
- # # <input value="New" type="submit" />
291
+ # # <button type="submit">New</button>
292
+ # # <input name="authenticity_token" type="hidden" value="10f2163b45388899ad4d5ae948988266befcb6c3d1b2451cf657a0c293d605a6"/>
273
293
  # # </form>"
274
294
  #
275
- #
276
295
  # <%= button_to "Create", { action: "create" }, remote: true, form: { "data-type" => "json" } %>
277
296
  # # => "<form method="post" action="/images/create" class="button_to" data-remote="true" data-type="json">
278
- # # <input value="Create" type="submit" />
297
+ # # <button type="submit">Create</button>
279
298
  # # <input name="authenticity_token" type="hidden" value="10f2163b45388899ad4d5ae948988266befcb6c3d1b2451cf657a0c293d605a6"/>
280
299
  # # </form>"
281
300
  #
282
- #
283
301
  # <%= button_to "Delete Image", { action: "delete", id: @image.id },
284
302
  # method: :delete, data: { confirm: "Are you sure?" } %>
285
303
  # # => "<form method="post" action="/images/delete/1" class="button_to">
286
304
  # # <input type="hidden" name="_method" value="delete" />
287
- # # <input data-confirm='Are you sure?' value="Delete Image" type="submit" />
305
+ # # <button data-confirm='Are you sure?' type="submit">Delete Image</button>
288
306
  # # <input name="authenticity_token" type="hidden" value="10f2163b45388899ad4d5ae948988266befcb6c3d1b2451cf657a0c293d605a6"/>
289
307
  # # </form>"
290
308
  #
291
- #
292
309
  # <%= button_to('Destroy', 'http://www.example.com',
293
310
  # method: :delete, remote: true, data: { confirm: 'Are you sure?', disable_with: 'loading...' }) %>
294
311
  # # => "<form class='button_to' method='post' action='http://www.example.com' data-remote='true'>
295
312
  # # <input name='_method' value='delete' type='hidden' />
296
- # # <input value='Destroy' type='submit' data-disable-with='loading...' data-confirm='Are you sure?' />
313
+ # # <button type='submit' data-disable-with='loading...' data-confirm='Are you sure?'>Destroy</button>
297
314
  # # <input name="authenticity_token" type="hidden" value="10f2163b45388899ad4d5ae948988266befcb6c3d1b2451cf657a0c293d605a6"/>
298
315
  # # </form>"
299
316
  # #
@@ -327,8 +344,8 @@ module ActionView
327
344
  html_options = convert_options_to_data_attributes(options, html_options)
328
345
  html_options["type"] = "submit"
329
346
 
330
- button = if block_given?
331
- content_tag("button", html_options, &block)
347
+ button = if block_given? || button_to_generates_button_tag
348
+ content_tag("button", name || url, html_options, &block)
332
349
  else
333
350
  html_options["value"] = name || url
334
351
  tag("input", html_options)
@@ -337,8 +354,7 @@ module ActionView
337
354
  inner_tags = method_tag.safe_concat(button).safe_concat(request_token_tag)
338
355
  if params
339
356
  to_form_params(params).each do |param|
340
- inner_tags.safe_concat tag(:input, type: "hidden", name: param[:name], value: param[:value],
341
- autocomplete: "off")
357
+ inner_tags.safe_concat tag(:input, type: "hidden", name: param[:name], value: param[:value])
342
358
  end
343
359
  end
344
360
  content_tag("form", inner_tags, form_options)
@@ -467,9 +483,9 @@ module ActionView
467
483
  # mail_to "me@domain.com", "My email"
468
484
  # # => <a href="mailto:me@domain.com">My email</a>
469
485
  #
470
- # mail_to "me@domain.com", "My email", cc: "ccaddress@domain.com",
486
+ # mail_to "me@domain.com", cc: "ccaddress@domain.com",
471
487
  # subject: "This is an example email"
472
- # # => <a href="mailto:me@domain.com?cc=ccaddress@domain.com&subject=This%20is%20an%20example%20email">My email</a>
488
+ # # => <a href="mailto:me@domain.com?cc=ccaddress@domain.com&subject=This%20is%20an%20example%20email">me@domain.com</a>
473
489
  #
474
490
  # You can use a block as well if your link target is hard to fit into the name parameter. ERB example:
475
491
  #
@@ -480,7 +496,7 @@ module ActionView
480
496
  # <strong>Email me:</strong> <span>me@domain.com</span>
481
497
  # </a>
482
498
  def mail_to(email_address, name = nil, html_options = {}, &block)
483
- html_options, name = name, nil if block_given?
499
+ html_options, name = name, nil if name.is_a?(Hash)
484
500
  html_options = (html_options || {}).stringify_keys
485
501
 
486
502
  extras = %w{ cc bcc body subject reply_to }.map! { |item|
@@ -583,29 +599,37 @@ module ActionView
583
599
  end
584
600
  end
585
601
 
586
- # Creates an SMS anchor link tag to the specified +phone_number+, which is
587
- # also used as the name of the link unless +name+ is specified. Additional
588
- # HTML attributes for the link can be passed in +html_options+.
602
+ # Creates an SMS anchor link tag to the specified +phone_number+. When the
603
+ # link is clicked, the default SMS messaging app is opened ready to send a
604
+ # message to the linked phone number. If the +body+ option is specified,
605
+ # the contents of the message will be preset to +body+.
589
606
  #
590
- # When clicked, an SMS message is prepopulated with the passed phone number
591
- # and optional +body+ value.
607
+ # If +name+ is not specified, +phone_number+ will be used as the name of
608
+ # the link.
592
609
  #
593
- # +sms_to+ has a +body+ option for customizing the SMS message itself by
594
- # passing special keys to +html_options+.
610
+ # A +country_code+ option is supported, which prepends a plus sign and the
611
+ # given country code to the linked phone number. For example,
612
+ # <tt>country_code: "01"</tt> will prepend <tt>+01</tt> to the linked
613
+ # phone number.
614
+ #
615
+ # Additional HTML attributes for the link can be passed via +html_options+.
595
616
  #
596
617
  # ==== Options
618
+ # * <tt>:country_code</tt> - Prepend the country code to the phone number.
597
619
  # * <tt>:body</tt> - Preset the body of the message.
598
620
  #
599
621
  # ==== Examples
600
622
  # sms_to "5155555785"
601
623
  # # => <a href="sms:5155555785;">5155555785</a>
602
624
  #
625
+ # sms_to "5155555785", country_code: "01"
626
+ # # => <a href="sms:+015155555785;">5155555785</a>
627
+ #
603
628
  # sms_to "5155555785", "Text me"
604
629
  # # => <a href="sms:5155555785;">Text me</a>
605
630
  #
606
- # sms_to "5155555785", "Text me",
607
- # body: "Hello Jim I have a question about your product."
608
- # # => <a href="sms:5155555785;?body=Hello%20Jim%20I%20have%20a%20question%20about%20your%20product">Text me</a>
631
+ # sms_to "5155555785", body: "I have a question about your product."
632
+ # # => <a href="sms:5155555785;?body=I%20have%20a%20question%20about%20your%20product">5155555785</a>
609
633
  #
610
634
  # You can use a block as well if your link target is hard to fit into the name parameter. \ERB example:
611
635
  #
@@ -616,46 +640,47 @@ module ActionView
616
640
  # <strong>Text me:</strong>
617
641
  # </a>
618
642
  def sms_to(phone_number, name = nil, html_options = {}, &block)
619
- html_options, name = name, nil if block_given?
643
+ html_options, name = name, nil if name.is_a?(Hash)
620
644
  html_options = (html_options || {}).stringify_keys
621
645
 
622
- extras = %w{ body }.map! { |item|
623
- option = html_options.delete(item).presence || next
624
- "#{item.dasherize}=#{ERB::Util.url_encode(option)}"
625
- }.compact
626
- extras = extras.empty? ? "" : "?&" + extras.join("&")
646
+ country_code = html_options.delete("country_code").presence
647
+ country_code = country_code ? "+#{ERB::Util.url_encode(country_code)}" : ""
648
+
649
+ body = html_options.delete("body").presence
650
+ body = body ? "?&body=#{ERB::Util.url_encode(body)}" : ""
627
651
 
628
652
  encoded_phone_number = ERB::Util.url_encode(phone_number)
629
- html_options["href"] = "sms:#{encoded_phone_number};#{extras}"
653
+ html_options["href"] = "sms:#{country_code}#{encoded_phone_number};#{body}"
630
654
 
631
655
  content_tag("a", name || phone_number, html_options, &block)
632
656
  end
633
657
 
634
- # Creates a TEL anchor link tag to the specified +phone_number+, which is
635
- # also used as the name of the link unless +name+ is specified. Additional
636
- # HTML attributes for the link can be passed in +html_options+.
658
+ # Creates a TEL anchor link tag to the specified +phone_number+. When the
659
+ # link is clicked, the default app to make phone calls is opened and
660
+ # prepopulated with the phone number.
661
+ #
662
+ # If +name+ is not specified, +phone_number+ will be used as the name of
663
+ # the link.
637
664
  #
638
- # When clicked, the default app to make calls is opened, and it
639
- # is prepopulated with the passed phone number and optional
640
- # +country_code+ value.
665
+ # A +country_code+ option is supported, which prepends a plus sign and the
666
+ # given country code to the linked phone number. For example,
667
+ # <tt>country_code: "01"</tt> will prepend <tt>+01</tt> to the linked
668
+ # phone number.
641
669
  #
642
- # +phone_to+ has an optional +country_code+ option which automatically adds the country
643
- # code as well as the + sign in the phone numer that gets prepopulated,
644
- # for example if +country_code: "01"+ +\+01+ will be prepended to the
645
- # phone numer, by passing special keys to +html_options+.
670
+ # Additional HTML attributes for the link can be passed via +html_options+.
646
671
  #
647
672
  # ==== Options
648
- # * <tt>:country_code</tt> - Prepends the country code to the number
673
+ # * <tt>:country_code</tt> - Prepends the country code to the phone number
649
674
  #
650
675
  # ==== Examples
651
676
  # phone_to "1234567890"
652
677
  # # => <a href="tel:1234567890">1234567890</a>
653
678
  #
654
679
  # phone_to "1234567890", "Phone me"
655
- # # => <a href="tel:134567890">Phone me</a>
680
+ # # => <a href="tel:1234567890">Phone me</a>
656
681
  #
657
- # phone_to "1234567890", "Phone me", country_code: "01"
658
- # # => <a href="tel:+015155555785">Phone me</a>
682
+ # phone_to "1234567890", country_code: "01"
683
+ # # => <a href="tel:+011234567890">1234567890</a>
659
684
  #
660
685
  # You can use a block as well if your link target is hard to fit into the name parameter. \ERB example:
661
686
  #
@@ -666,7 +691,7 @@ module ActionView
666
691
  # <strong>Phone me:</strong>
667
692
  # </a>
668
693
  def phone_to(phone_number, name = nil, html_options = {}, &block)
669
- html_options, name = name, nil if block_given?
694
+ html_options, name = name, nil if name.is_a?(Hash)
670
695
  html_options = (html_options || {}).stringify_keys
671
696
 
672
697
  country_code = html_options.delete("country_code").presence
@@ -727,14 +752,14 @@ module ActionView
727
752
  def token_tag(token = nil, form_options: {})
728
753
  if token != false && defined?(protect_against_forgery?) && protect_against_forgery?
729
754
  token ||= form_authenticity_token(form_options: form_options)
730
- tag(:input, type: "hidden", name: request_forgery_protection_token.to_s, value: token, autocomplete: "off")
755
+ tag(:input, type: "hidden", name: request_forgery_protection_token.to_s, value: token)
731
756
  else
732
757
  ""
733
758
  end
734
759
  end
735
760
 
736
761
  def method_tag(method)
737
- tag("input", type: "hidden", name: "_method", value: method.to_s, autocomplete: "off")
762
+ tag("input", type: "hidden", name: "_method", value: method.to_s)
738
763
  end
739
764
 
740
765
  # Returns an array of hashes each containing :name and :value keys
@@ -1,34 +1,34 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/benchmarkable"
4
+ require "action_view/helpers/capture_helper"
5
+ require "action_view/helpers/output_safety_helper"
6
+ require "action_view/helpers/tag_helper"
7
+ require "action_view/helpers/url_helper"
8
+ require "action_view/helpers/sanitize_helper"
9
+ require "action_view/helpers/text_helper"
10
+ require "action_view/helpers/active_model_helper"
11
+ require "action_view/helpers/asset_tag_helper"
12
+ require "action_view/helpers/asset_url_helper"
13
+ require "action_view/helpers/atom_feed_helper"
14
+ require "action_view/helpers/cache_helper"
15
+ require "action_view/helpers/controller_helper"
16
+ require "action_view/helpers/csp_helper"
17
+ require "action_view/helpers/csrf_helper"
18
+ require "action_view/helpers/date_helper"
19
+ require "action_view/helpers/debug_helper"
20
+ require "action_view/helpers/form_tag_helper"
21
+ require "action_view/helpers/form_helper"
22
+ require "action_view/helpers/form_options_helper"
23
+ require "action_view/helpers/javascript_helper"
24
+ require "action_view/helpers/number_helper"
25
+ require "action_view/helpers/rendering_helper"
26
+ require "action_view/helpers/translation_helper"
4
27
 
5
- module ActionView #:nodoc:
6
- module Helpers #:nodoc:
28
+ module ActionView # :nodoc:
29
+ module Helpers # :nodoc:
7
30
  extend ActiveSupport::Autoload
8
31
 
9
- autoload :ActiveModelHelper
10
- autoload :AssetTagHelper
11
- autoload :AssetUrlHelper
12
- autoload :AtomFeedHelper
13
- autoload :CacheHelper
14
- autoload :CaptureHelper
15
- autoload :ControllerHelper
16
- autoload :CspHelper
17
- autoload :CsrfHelper
18
- autoload :DateHelper
19
- autoload :DebugHelper
20
- autoload :FormHelper
21
- autoload :FormOptionsHelper
22
- autoload :FormTagHelper
23
- autoload :JavaScriptHelper, "action_view/helpers/javascript_helper"
24
- autoload :NumberHelper
25
- autoload :OutputSafetyHelper
26
- autoload :RenderingHelper
27
- autoload :SanitizeHelper
28
- autoload :TagHelper
29
- autoload :TextHelper
30
- autoload :TranslationHelper
31
- autoload :UrlHelper
32
32
  autoload :Tags
33
33
 
34
34
  def self.eager_load!