actionview 7.0.4 → 7.1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +343 -232
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +3 -3
  5. data/app/assets/javascripts/rails-ujs.esm.js +686 -0
  6. data/app/assets/javascripts/rails-ujs.js +630 -0
  7. data/lib/action_view/base.rb +34 -14
  8. data/lib/action_view/buffers.rb +106 -8
  9. data/lib/action_view/cache_expiry.rb +40 -43
  10. data/lib/action_view/context.rb +1 -1
  11. data/lib/action_view/deprecator.rb +7 -0
  12. data/lib/action_view/digestor.rb +1 -1
  13. data/lib/action_view/gem_version.rb +4 -4
  14. data/lib/action_view/helpers/active_model_helper.rb +1 -1
  15. data/lib/action_view/helpers/asset_tag_helper.rb +136 -52
  16. data/lib/action_view/helpers/asset_url_helper.rb +6 -5
  17. data/lib/action_view/helpers/atom_feed_helper.rb +5 -5
  18. data/lib/action_view/helpers/cache_helper.rb +7 -13
  19. data/lib/action_view/helpers/capture_helper.rb +32 -12
  20. data/lib/action_view/helpers/content_exfiltration_prevention_helper.rb +70 -0
  21. data/lib/action_view/helpers/controller_helper.rb +6 -0
  22. data/lib/action_view/helpers/csp_helper.rb +2 -2
  23. data/lib/action_view/helpers/csrf_helper.rb +3 -3
  24. data/lib/action_view/helpers/date_helper.rb +67 -59
  25. data/lib/action_view/helpers/debug_helper.rb +3 -3
  26. data/lib/action_view/helpers/form_helper.rb +56 -26
  27. data/lib/action_view/helpers/form_options_helper.rb +4 -1
  28. data/lib/action_view/helpers/form_tag_helper.rb +49 -15
  29. data/lib/action_view/helpers/javascript_helper.rb +1 -0
  30. data/lib/action_view/helpers/number_helper.rb +37 -329
  31. data/lib/action_view/helpers/output_safety_helper.rb +4 -4
  32. data/lib/action_view/helpers/rendering_helper.rb +1 -1
  33. data/lib/action_view/helpers/sanitize_helper.rb +51 -21
  34. data/lib/action_view/helpers/tag_helper.rb +5 -27
  35. data/lib/action_view/helpers/tags/base.rb +11 -52
  36. data/lib/action_view/helpers/tags/collection_check_boxes.rb +1 -0
  37. data/lib/action_view/helpers/tags/collection_radio_buttons.rb +1 -0
  38. data/lib/action_view/helpers/tags/collection_select.rb +3 -0
  39. data/lib/action_view/helpers/tags/date_field.rb +1 -1
  40. data/lib/action_view/helpers/tags/date_select.rb +2 -0
  41. data/lib/action_view/helpers/tags/datetime_field.rb +14 -6
  42. data/lib/action_view/helpers/tags/datetime_local_field.rb +11 -2
  43. data/lib/action_view/helpers/tags/grouped_collection_select.rb +3 -0
  44. data/lib/action_view/helpers/tags/month_field.rb +1 -1
  45. data/lib/action_view/helpers/tags/select.rb +4 -1
  46. data/lib/action_view/helpers/tags/select_renderer.rb +56 -0
  47. data/lib/action_view/helpers/tags/time_field.rb +1 -1
  48. data/lib/action_view/helpers/tags/time_zone_select.rb +3 -0
  49. data/lib/action_view/helpers/tags/week_field.rb +1 -1
  50. data/lib/action_view/helpers/tags/weekday_select.rb +3 -0
  51. data/lib/action_view/helpers/tags.rb +2 -0
  52. data/lib/action_view/helpers/text_helper.rb +156 -84
  53. data/lib/action_view/helpers/translation_helper.rb +3 -3
  54. data/lib/action_view/helpers/url_helper.rb +47 -18
  55. data/lib/action_view/helpers.rb +2 -0
  56. data/lib/action_view/layouts.rb +8 -6
  57. data/lib/action_view/log_subscriber.rb +49 -32
  58. data/lib/action_view/lookup_context.rb +29 -13
  59. data/lib/action_view/path_registry.rb +57 -0
  60. data/lib/action_view/path_set.rb +13 -14
  61. data/lib/action_view/railtie.rb +26 -3
  62. data/lib/action_view/record_identifier.rb +15 -8
  63. data/lib/action_view/renderer/abstract_renderer.rb +1 -1
  64. data/lib/action_view/renderer/collection_renderer.rb +10 -2
  65. data/lib/action_view/renderer/partial_renderer/collection_caching.rb +21 -3
  66. data/lib/action_view/renderer/partial_renderer.rb +2 -1
  67. data/lib/action_view/renderer/renderer.rb +2 -0
  68. data/lib/action_view/renderer/streaming_template_renderer.rb +3 -2
  69. data/lib/action_view/renderer/template_renderer.rb +3 -2
  70. data/lib/action_view/rendering.rb +22 -4
  71. data/lib/action_view/ripper_ast_parser.rb +6 -6
  72. data/lib/action_view/routing_url_for.rb +4 -4
  73. data/lib/action_view/template/error.rb +14 -1
  74. data/lib/action_view/template/handlers/builder.rb +4 -4
  75. data/lib/action_view/template/handlers/erb/erubi.rb +23 -27
  76. data/lib/action_view/template/handlers/erb.rb +73 -1
  77. data/lib/action_view/template/handlers.rb +1 -1
  78. data/lib/action_view/template/html.rb +1 -1
  79. data/lib/action_view/template/raw_file.rb +1 -1
  80. data/lib/action_view/template/renderable.rb +1 -1
  81. data/lib/action_view/template/resolver.rb +15 -5
  82. data/lib/action_view/template/text.rb +1 -1
  83. data/lib/action_view/template/types.rb +25 -34
  84. data/lib/action_view/template.rb +249 -54
  85. data/lib/action_view/template_path.rb +2 -0
  86. data/lib/action_view/test_case.rb +176 -21
  87. data/lib/action_view/unbound_template.rb +17 -7
  88. data/lib/action_view/version.rb +1 -1
  89. data/lib/action_view/view_paths.rb +15 -24
  90. data/lib/action_view.rb +4 -1
  91. metadata +27 -28
  92. data/lib/assets/compiled/rails-ujs.js +0 -746
@@ -1,14 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "cgi"
4
+ require "action_view/helpers/content_exfiltration_prevention_helper"
4
5
  require "action_view/helpers/url_helper"
5
6
  require "action_view/helpers/text_helper"
6
7
  require "active_support/core_ext/string/output_safety"
7
8
  require "active_support/core_ext/module/attribute_accessors"
8
9
 
9
10
  module ActionView
10
- # = Action View Form Tag Helpers
11
11
  module Helpers # :nodoc:
12
+ # = Action View Form Tag \Helpers
13
+ #
12
14
  # Provides a number of methods for creating form tags that don't rely on an Active Record object assigned to the template like
13
15
  # FormHelper does. Instead, you provide the names and values manually.
14
16
  #
@@ -19,6 +21,7 @@ module ActionView
19
21
 
20
22
  include UrlHelper
21
23
  include TextHelper
24
+ include ContentExfiltrationPreventionHelper
22
25
 
23
26
  mattr_accessor :embed_authenticity_token_in_remote_forms
24
27
  self.embed_authenticity_token_in_remote_forms = nil
@@ -88,11 +91,11 @@ module ActionView
88
91
  # attribute name.
89
92
  #
90
93
  # <%= label_tag :post, :title %>
91
- # <%= text_field_tag :post, :title, aria: { describedby: field_id(:post, :title, :error) } %>
94
+ # <%= text_field :post, :title, aria: { describedby: field_id(:post, :title, :error) } %>
92
95
  # <%= tag.span("is blank", id: field_id(:post, :title, :error) %>
93
96
  #
94
97
  # In the example above, the <tt><input type="text"></tt> element built by
95
- # the call to <tt>text_field_tag</tt> declares an
98
+ # the call to <tt>text_field</tt> declares an
96
99
  # <tt>aria-describedby</tt> attribute referencing the <tt><span></tt>
97
100
  # element, sharing a common <tt>id</tt> root (<tt>post_title</tt>, in this
98
101
  # case).
@@ -120,11 +123,11 @@ module ActionView
120
123
  # Return the value generated by the <tt>FormBuilder</tt> for the given
121
124
  # attribute name.
122
125
  #
123
- # <%= text_field_tag :post, :title, name: field_name(:post, :title, :subtitle) %>
124
- # <%# => <input type="text" name="post[title][subtitle]">
126
+ # <%= text_field :post, :title, name: field_name(:post, :title, :subtitle) %>
127
+ # <%# => <input type="text" name="post[title][subtitle]"> %>
125
128
  #
126
- # <%= text_field_tag :post, :tag, name: field_name(:post, :tag, multiple: true) %>
127
- # <%# => <input type="text" name="post[tag][]">
129
+ # <%= text_field :post, :tag, name: field_name(:post, :tag, multiple: true) %>
130
+ # <%# => <input type="text" name="post[tag][]"> %>
128
131
  #
129
132
  def field_name(object_name, method_name, *method_names, multiple: false, index: nil)
130
133
  names = method_names.map! { |name| "[#{name}]" }.join
@@ -420,9 +423,17 @@ module ActionView
420
423
  content_tag :textarea, content.to_s.html_safe, { "name" => name, "id" => sanitize_to_id(name) }.update(options)
421
424
  end
422
425
 
426
+ ##
427
+ # :call-seq:
428
+ # check_box_tag(name, options = {})
429
+ # check_box_tag(name, value, options = {})
430
+ # check_box_tag(name, value, checked, options = {})
431
+ #
423
432
  # Creates a check box form input tag.
424
433
  #
425
434
  # ==== Options
435
+ # * <tt>:value</tt> - The value of the input. Defaults to <tt>"1"</tt>.
436
+ # * <tt>:checked</tt> - If set to true, the checkbox will be checked by default.
426
437
  # * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
427
438
  # * Any other key creates standard HTML options for the tag.
428
439
  #
@@ -441,16 +452,27 @@ module ActionView
441
452
  #
442
453
  # check_box_tag 'eula', 'accepted', false, disabled: true
443
454
  # # => <input disabled="disabled" id="eula" name="eula" type="checkbox" value="accepted" />
444
- def check_box_tag(name, value = "1", checked = false, options = {})
455
+ def check_box_tag(name, *args)
456
+ if args.length >= 4
457
+ raise ArgumentError, "wrong number of arguments (given #{args.length + 1}, expected 1..4)"
458
+ end
459
+ options = args.extract_options!
460
+ value, checked = args.empty? ? ["1", false] : [*args, false]
445
461
  html_options = { "type" => "checkbox", "name" => name, "id" => sanitize_to_id(name), "value" => value }.update(options.stringify_keys)
446
462
  html_options["checked"] = "checked" if checked
447
463
  tag :input, html_options
448
464
  end
449
465
 
466
+ ##
467
+ # :call-seq:
468
+ # radio_button_tag(name, value, options = {})
469
+ # radio_button_tag(name, value, checked, options = {})
470
+ #
450
471
  # Creates a radio button; use groups of radio buttons named the same to allow users to
451
472
  # select from a group of options.
452
473
  #
453
474
  # ==== Options
475
+ # * <tt>:checked</tt> - If set to true, the radio button will be selected by default.
454
476
  # * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
455
477
  # * Any other key creates standard HTML options for the tag.
456
478
  #
@@ -466,7 +488,12 @@ module ActionView
466
488
  #
467
489
  # radio_button_tag 'color', "green", true, class: "color_input"
468
490
  # # => <input checked="checked" class="color_input" id="color_green" name="color" type="radio" value="green" />
469
- def radio_button_tag(name, value, checked = false, options = {})
491
+ def radio_button_tag(name, value, *args)
492
+ if args.length >= 3
493
+ raise ArgumentError, "wrong number of arguments (given #{args.length + 2}, expected 2..4)"
494
+ end
495
+ options = args.extract_options!
496
+ checked = args.empty? ? false : args.first
470
497
  html_options = { "type" => "radio", "name" => name, "id" => "#{sanitize_to_id(name)}_#{sanitize_to_id(value)}", "value" => value }.update(options.stringify_keys)
471
498
  html_options["checked"] = "checked" if checked
472
499
  tag :input, html_options
@@ -495,9 +522,9 @@ module ActionView
495
522
  # submit_tag "Edit", class: "edit_button"
496
523
  # # => <input class="edit_button" data-disable-with="Edit" name="commit" type="submit" value="Edit" />
497
524
  #
498
- # ==== Deprecated: Rails UJS attributes
525
+ # ==== Deprecated: \Rails UJS attributes
499
526
  #
500
- # Prior to Rails 7, Rails shipped with the JavaScript library called @rails/ujs on by default. Following Rails 7,
527
+ # Prior to \Rails 7, \Rails shipped with the JavaScript library called @rails/ujs on by default. Following \Rails 7,
501
528
  # this library is no longer on by default. This library integrated with the following options:
502
529
  #
503
530
  # * <tt>confirm: 'question?'</tt> - If present the unobtrusive JavaScript
@@ -555,9 +582,9 @@ module ActionView
555
582
  # # <strong>Ask me!</strong>
556
583
  # # </button>
557
584
  #
558
- # ==== Deprecated: Rails UJS attributes
585
+ # ==== Deprecated: \Rails UJS attributes
559
586
  #
560
- # Prior to Rails 7, Rails shipped with a JavaScript library called @rails/ujs on by default. Following Rails 7,
587
+ # Prior to \Rails 7, \Rails shipped with a JavaScript library called @rails/ujs on by default. Following \Rails 7,
561
588
  # this library is no longer on by default. This library integrated with the following options:
562
589
  #
563
590
  # * <tt>confirm: 'question?'</tt> - If present, the
@@ -770,6 +797,7 @@ module ActionView
770
797
  # * <tt>:min</tt> - The minimum acceptable value.
771
798
  # * <tt>:max</tt> - The maximum acceptable value.
772
799
  # * <tt>:step</tt> - The acceptable value granularity.
800
+ # * <tt>:include_seconds</tt> - Include seconds in the output timestamp format (true by default).
773
801
  def datetime_field_tag(name, value = nil, options = {})
774
802
  text_field_tag(name, value, options.merge(type: "datetime-local"))
775
803
  end
@@ -979,7 +1007,8 @@ module ActionView
979
1007
 
980
1008
  def form_tag_html(html_options)
981
1009
  extra_tags = extra_tags_for_form(html_options)
982
- tag(:form, html_options, true) + extra_tags
1010
+ html = tag(:form, html_options, true) + extra_tags
1011
+ prevent_content_exfiltration(html)
983
1012
  end
984
1013
 
985
1014
  def form_tag_with_body(html_options, content)
@@ -1009,9 +1038,14 @@ module ActionView
1009
1038
  end
1010
1039
 
1011
1040
  def convert_direct_upload_option_to_url(options)
1012
- if options.delete(:direct_upload) && respond_to?(:rails_direct_uploads_url)
1041
+ return options unless options.delete(:direct_upload)
1042
+
1043
+ if respond_to?(:rails_direct_uploads_url)
1013
1044
  options["data-direct-upload-url"] = rails_direct_uploads_url
1045
+ elsif respond_to?(:main_app) && main_app.respond_to?(:rails_direct_uploads_url)
1046
+ options["data-direct-upload-url"] = main_app.rails_direct_uploads_url
1014
1047
  end
1048
+
1015
1049
  options
1016
1050
  end
1017
1051
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  module ActionView
4
4
  module Helpers # :nodoc:
5
+ # = Action View JavaScript \Helpers
5
6
  module JavaScriptHelper
6
7
  JS_ESCAPE_MAP = {
7
8
  "\\" => "\\\\",
@@ -5,8 +5,9 @@ require "active_support/core_ext/string/output_safety"
5
5
  require "active_support/number_helper"
6
6
 
7
7
  module ActionView
8
- # = Action View Number Helpers
9
8
  module Helpers # :nodoc:
9
+ # = Action View Number \Helpers
10
+ #
10
11
  # Provides methods for converting numbers into formatted strings.
11
12
  # Methods are provided for phone numbers, currency, percentage,
12
13
  # precision, positional notation, file size, and pretty printing.
@@ -23,42 +24,14 @@ module ActionView
23
24
  end
24
25
  end
25
26
 
26
- # Formats a +number+ into a phone number (US by default e.g., (555)
27
- # 123-9876). You can customize the format in the +options+ hash.
28
- #
29
- # ==== Options
30
- #
31
- # * <tt>:area_code</tt> - Adds parentheses around the area code.
32
- # * <tt>:delimiter</tt> - Specifies the delimiter to use
33
- # (defaults to "-").
34
- # * <tt>:extension</tt> - Specifies an extension to add to the
35
- # end of the generated number.
36
- # * <tt>:country_code</tt> - Sets the country code for the phone
37
- # number.
38
- # * <tt>:pattern</tt> - Specifies how the number is divided into three
39
- # groups with the custom regexp to override the default format.
40
- # * <tt>:raise</tt> - If true, raises +InvalidNumberError+ when
41
- # the argument is invalid.
42
- #
43
- # ==== Examples
27
+ # Delegates to ActiveSupport::NumberHelper#number_to_phone.
44
28
  #
45
- # number_to_phone(5551234) # => 555-1234
46
- # number_to_phone("5551234") # => 555-1234
47
- # number_to_phone(1235551234) # => 123-555-1234
48
- # number_to_phone(1235551234, area_code: true) # => (123) 555-1234
49
- # number_to_phone(1235551234, delimiter: " ") # => 123 555 1234
50
- # number_to_phone(1235551234, area_code: true, extension: 555) # => (123) 555-1234 x 555
51
- # number_to_phone(1235551234, country_code: 1) # => +1-123-555-1234
52
- # number_to_phone("123a456") # => 123a456
53
- # number_to_phone("1234a567", raise: true) # => InvalidNumberError
29
+ # Additionally, supports a +:raise+ option that will cause
30
+ # InvalidNumberError to be raised if +number+ is not a valid number:
54
31
  #
55
- # number_to_phone(1235551234, country_code: 1, extension: 1343, delimiter: ".")
56
- # # => +1.123.555.1234 x 1343
32
+ # number_to_phone("12x34") # => "12x34"
33
+ # number_to_phone("12x34", raise: true) # => InvalidNumberError
57
34
  #
58
- # number_to_phone(75561234567, pattern: /(\d{1,4})(\d{4})(\d{4})$/, area_code: true)
59
- # # => "(755) 6123-4567"
60
- # number_to_phone(13312345678, pattern: /(\d{3})(\d{4})(\d{4})$/)
61
- # # => "133-1234-5678"
62
35
  def number_to_phone(number, options = {})
63
36
  return unless number
64
37
  options = options.symbolize_keys
@@ -67,338 +40,73 @@ module ActionView
67
40
  ERB::Util.html_escape(ActiveSupport::NumberHelper.number_to_phone(number, options))
68
41
  end
69
42
 
70
- # Formats a +number+ into a currency string (e.g., $13.65). You
71
- # can customize the format in the +options+ hash.
72
- #
73
- # The currency unit and number formatting of the current locale will be used
74
- # unless otherwise specified in the provided options. No currency conversion
75
- # is performed. If the user is given a way to change their locale, they will
76
- # also be able to change the relative value of the currency displayed with
77
- # this helper. If your application will ever support multiple locales, you
78
- # may want to specify a constant <tt>:locale</tt> option or consider
79
- # using a library capable of currency conversion.
80
- #
81
- # ==== Options
82
- #
83
- # * <tt>:locale</tt> - Sets the locale to be used for formatting
84
- # (defaults to current locale).
85
- # * <tt>:precision</tt> - Sets the level of precision (defaults
86
- # to 2).
87
- # * <tt>:unit</tt> - Sets the denomination of the currency
88
- # (defaults to "$").
89
- # * <tt>:separator</tt> - Sets the separator between the units
90
- # (defaults to ".").
91
- # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults
92
- # to ",").
93
- # * <tt>:format</tt> - Sets the format for non-negative numbers
94
- # (defaults to "%u%n"). Fields are <tt>%u</tt> for the
95
- # currency, and <tt>%n</tt> for the number.
96
- # * <tt>:negative_format</tt> - Sets the format for negative
97
- # numbers (defaults to prepending a hyphen to the formatted
98
- # number given by <tt>:format</tt>). Accepts the same fields
99
- # than <tt>:format</tt>, except <tt>%n</tt> is here the
100
- # absolute value of the number.
101
- # * <tt>:raise</tt> - If true, raises +InvalidNumberError+ when
102
- # the argument is invalid.
103
- # * <tt>:strip_insignificant_zeros</tt> - If +true+ removes
104
- # insignificant zeros after the decimal separator (defaults to
105
- # +false+).
106
- #
107
- # ==== Examples
43
+ # Delegates to ActiveSupport::NumberHelper#number_to_currency.
108
44
  #
109
- # number_to_currency(1234567890.50) # => $1,234,567,890.50
110
- # number_to_currency(1234567890.506) # => $1,234,567,890.51
111
- # number_to_currency(1234567890.506, precision: 3) # => $1,234,567,890.506
112
- # number_to_currency(1234567890.506, locale: :fr) # => 1 234 567 890,51 €
113
- # number_to_currency("123a456") # => $123a456
45
+ # Additionally, supports a +:raise+ option that will cause
46
+ # InvalidNumberError to be raised if +number+ is not a valid number:
114
47
  #
115
- # number_to_currency("123a456", raise: true) # => InvalidNumberError
48
+ # number_to_currency("12x34") # => "$12x34"
49
+ # number_to_currency("12x34", raise: true) # => InvalidNumberError
116
50
  #
117
- # number_to_currency(-0.456789, precision: 0)
118
- # # => "$0"
119
- # number_to_currency(-1234567890.50, negative_format: "(%u%n)")
120
- # # => ($1,234,567,890.50)
121
- # number_to_currency(1234567890.50, unit: "R$", separator: ",", delimiter: "")
122
- # # => R$1234567890,50
123
- # number_to_currency(1234567890.50, unit: "R$", separator: ",", delimiter: "", format: "%n %u")
124
- # # => 1234567890,50 R$
125
- # number_to_currency(1234567890.50, strip_insignificant_zeros: true)
126
- # # => "$1,234,567,890.5"
127
51
  def number_to_currency(number, options = {})
128
52
  delegate_number_helper_method(:number_to_currency, number, options)
129
53
  end
130
54
 
131
- # Formats a +number+ as a percentage string (e.g., 65%). You can
132
- # customize the format in the +options+ hash.
55
+ # Delegates to ActiveSupport::NumberHelper#number_to_percentage.
133
56
  #
134
- # ==== Options
57
+ # Additionally, supports a +:raise+ option that will cause
58
+ # InvalidNumberError to be raised if +number+ is not a valid number:
135
59
  #
136
- # * <tt>:locale</tt> - Sets the locale to be used for formatting
137
- # (defaults to current locale).
138
- # * <tt>:precision</tt> - Sets the precision of the number
139
- # (defaults to 3).
140
- # * <tt>:significant</tt> - If +true+, precision will be the number
141
- # of significant_digits. If +false+, the number of fractional
142
- # digits (defaults to +false+).
143
- # * <tt>:separator</tt> - Sets the separator between the
144
- # fractional and integer digits (defaults to ".").
145
- # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults
146
- # to "").
147
- # * <tt>:strip_insignificant_zeros</tt> - If +true+ removes
148
- # insignificant zeros after the decimal separator (defaults to
149
- # +false+).
150
- # * <tt>:format</tt> - Specifies the format of the percentage
151
- # string The number field is <tt>%n</tt> (defaults to "%n%").
152
- # * <tt>:raise</tt> - If true, raises +InvalidNumberError+ when
153
- # the argument is invalid.
60
+ # number_to_percentage("99x") # => "99x%"
61
+ # number_to_percentage("99x", raise: true) # => InvalidNumberError
154
62
  #
155
- # ==== Examples
156
- #
157
- # number_to_percentage(100) # => 100.000%
158
- # number_to_percentage("98") # => 98.000%
159
- # number_to_percentage(100, precision: 0) # => 100%
160
- # number_to_percentage(1000, delimiter: '.', separator: ',') # => 1.000,000%
161
- # number_to_percentage(302.24398923423, precision: 5) # => 302.24399%
162
- # number_to_percentage(1000, locale: :fr) # => 1 000,000%
163
- # number_to_percentage("98a") # => 98a%
164
- # number_to_percentage(100, format: "%n %") # => 100.000 %
165
- #
166
- # number_to_percentage("98a", raise: true) # => InvalidNumberError
167
63
  def number_to_percentage(number, options = {})
168
64
  delegate_number_helper_method(:number_to_percentage, number, options)
169
65
  end
170
66
 
171
- # Formats a +number+ with grouped thousands using +delimiter+
172
- # (e.g., 12,324). You can customize the format in the +options+
173
- # hash.
174
- #
175
- # ==== Options
176
- #
177
- # * <tt>:locale</tt> - Sets the locale to be used for formatting
178
- # (defaults to current locale).
179
- # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults
180
- # to ",").
181
- # * <tt>:separator</tt> - Sets the separator between the
182
- # fractional and integer digits (defaults to ".").
183
- # * <tt>:delimiter_pattern</tt> - Sets a custom regular expression used for
184
- # deriving the placement of delimiter. Helpful when using currency formats
185
- # like INR.
186
- # * <tt>:raise</tt> - If true, raises +InvalidNumberError+ when
187
- # the argument is invalid.
67
+ # Delegates to ActiveSupport::NumberHelper#number_to_delimited.
188
68
  #
189
- # ==== Examples
69
+ # Additionally, supports a +:raise+ option that will cause
70
+ # InvalidNumberError to be raised if +number+ is not a valid number:
190
71
  #
191
- # number_with_delimiter(12345678) # => 12,345,678
192
- # number_with_delimiter("123456") # => 123,456
193
- # number_with_delimiter(12345678.05) # => 12,345,678.05
194
- # number_with_delimiter(12345678, delimiter: ".") # => 12.345.678
195
- # number_with_delimiter(12345678, delimiter: ",") # => 12,345,678
196
- # number_with_delimiter(12345678.05, separator: " ") # => 12,345,678 05
197
- # number_with_delimiter(12345678.05, locale: :fr) # => 12 345 678,05
198
- # number_with_delimiter("112a") # => 112a
199
- # number_with_delimiter(98765432.98, delimiter: " ", separator: ",")
200
- # # => 98 765 432,98
72
+ # number_with_delimiter("12x34") # => "12x34"
73
+ # number_with_delimiter("12x34", raise: true) # => InvalidNumberError
201
74
  #
202
- # number_with_delimiter("123456.78",
203
- # delimiter_pattern: /(\d+?)(?=(\d\d)+(\d)(?!\d))/) # => "1,23,456.78"
204
- #
205
- # number_with_delimiter("112a", raise: true) # => raise InvalidNumberError
206
75
  def number_with_delimiter(number, options = {})
207
76
  delegate_number_helper_method(:number_to_delimited, number, options)
208
77
  end
209
78
 
210
- # Formats a +number+ with the specified level of
211
- # <tt>:precision</tt> (e.g., 112.32 has a precision of 2 if
212
- # +:significant+ is +false+, and 5 if +:significant+ is +true+).
213
- # You can customize the format in the +options+ hash.
214
- #
215
- # ==== Options
216
- #
217
- # * <tt>:locale</tt> - Sets the locale to be used for formatting
218
- # (defaults to current locale).
219
- # * <tt>:precision</tt> - Sets the precision of the number
220
- # (defaults to 3).
221
- # * <tt>:significant</tt> - If +true+, precision will be the number
222
- # of significant_digits. If +false+, the number of fractional
223
- # digits (defaults to +false+).
224
- # * <tt>:separator</tt> - Sets the separator between the
225
- # fractional and integer digits (defaults to ".").
226
- # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults
227
- # to "").
228
- # * <tt>:strip_insignificant_zeros</tt> - If +true+ removes
229
- # insignificant zeros after the decimal separator (defaults to
230
- # +false+).
231
- # * <tt>:raise</tt> - If true, raises +InvalidNumberError+ when
232
- # the argument is invalid.
79
+ # Delegates to ActiveSupport::NumberHelper#number_to_rounded.
233
80
  #
234
- # ==== Examples
81
+ # Additionally, supports a +:raise+ option that will cause
82
+ # InvalidNumberError to be raised if +number+ is not a valid number:
235
83
  #
236
- # number_with_precision(111.2345) # => 111.235
237
- # number_with_precision(111.2345, precision: 2) # => 111.23
238
- # number_with_precision(13, precision: 5) # => 13.00000
239
- # number_with_precision(389.32314, precision: 0) # => 389
240
- # number_with_precision(111.2345, significant: true) # => 111
241
- # number_with_precision(111.2345, precision: 1, significant: true) # => 100
242
- # number_with_precision(13, precision: 5, significant: true) # => 13.000
243
- # number_with_precision(111.234, locale: :fr) # => 111,234
84
+ # number_with_precision("12x34") # => "12x34"
85
+ # number_with_precision("12x34", raise: true) # => InvalidNumberError
244
86
  #
245
- # number_with_precision(13, precision: 5, significant: true, strip_insignificant_zeros: true)
246
- # # => 13
247
- #
248
- # number_with_precision(389.32314, precision: 4, significant: true) # => 389.3
249
- # number_with_precision(1111.2345, precision: 2, separator: ',', delimiter: '.')
250
- # # => 1.111,23
251
87
  def number_with_precision(number, options = {})
252
88
  delegate_number_helper_method(:number_to_rounded, number, options)
253
89
  end
254
90
 
255
- # Formats the bytes in +number+ into a more understandable
256
- # representation (e.g., giving it 1500 yields 1.46 KB). This
257
- # method is useful for reporting file sizes to users. You can
258
- # customize the format in the +options+ hash.
259
- #
260
- # See <tt>number_to_human</tt> if you want to pretty-print a
261
- # generic number.
91
+ # Delegates to ActiveSupport::NumberHelper#number_to_human_size.
262
92
  #
263
- # ==== Options
93
+ # Additionally, supports a +:raise+ option that will cause
94
+ # InvalidNumberError to be raised if +number+ is not a valid number:
264
95
  #
265
- # * <tt>:locale</tt> - Sets the locale to be used for formatting
266
- # (defaults to current locale).
267
- # * <tt>:precision</tt> - Sets the precision of the number
268
- # (defaults to 3).
269
- # * <tt>:significant</tt> - If +true+, precision will be the number
270
- # of significant_digits. If +false+, the number of fractional
271
- # digits (defaults to +true+)
272
- # * <tt>:separator</tt> - Sets the separator between the
273
- # fractional and integer digits (defaults to ".").
274
- # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults
275
- # to "").
276
- # * <tt>:strip_insignificant_zeros</tt> - If +true+ removes
277
- # insignificant zeros after the decimal separator (defaults to
278
- # +true+)
279
- # * <tt>:raise</tt> - If true, raises +InvalidNumberError+ when
280
- # the argument is invalid.
96
+ # number_to_human_size("12x34") # => "12x34"
97
+ # number_to_human_size("12x34", raise: true) # => InvalidNumberError
281
98
  #
282
- # ==== Examples
283
- #
284
- # number_to_human_size(123) # => 123 Bytes
285
- # number_to_human_size(1234) # => 1.21 KB
286
- # number_to_human_size(12345) # => 12.1 KB
287
- # number_to_human_size(1234567) # => 1.18 MB
288
- # number_to_human_size(1234567890) # => 1.15 GB
289
- # number_to_human_size(1234567890123) # => 1.12 TB
290
- # number_to_human_size(1234567890123456) # => 1.1 PB
291
- # number_to_human_size(1234567890123456789) # => 1.07 EB
292
- # number_to_human_size(1234567, precision: 2) # => 1.2 MB
293
- # number_to_human_size(483989, precision: 2) # => 470 KB
294
- # number_to_human_size(1234567, precision: 2, separator: ',') # => 1,2 MB
295
- # number_to_human_size(1234567890123, precision: 5) # => "1.1228 TB"
296
- # number_to_human_size(524288000, precision: 5) # => "500 MB"
297
99
  def number_to_human_size(number, options = {})
298
100
  delegate_number_helper_method(:number_to_human_size, number, options)
299
101
  end
300
102
 
301
- # Pretty prints (formats and approximates) a number in a way it
302
- # is more readable by humans (e.g.: 1200000000 becomes "1.2
303
- # Billion"). This is useful for numbers that can get very large
304
- # (and too hard to read).
305
- #
306
- # See <tt>number_to_human_size</tt> if you want to print a file
307
- # size.
308
- #
309
- # You can also define your own unit-quantifier names if you want
310
- # to use other decimal units (e.g.: 1500 becomes "1.5
311
- # kilometers", 0.150 becomes "150 milliliters", etc). You may
312
- # define a wide range of unit quantifiers, even fractional ones
313
- # (centi, deci, mili, etc).
314
- #
315
- # ==== Options
316
- #
317
- # * <tt>:locale</tt> - Sets the locale to be used for formatting
318
- # (defaults to current locale).
319
- # * <tt>:precision</tt> - Sets the precision of the number
320
- # (defaults to 3).
321
- # * <tt>:significant</tt> - If +true+, precision will be the number
322
- # of significant_digits. If +false+, the number of fractional
323
- # digits (defaults to +true+)
324
- # * <tt>:separator</tt> - Sets the separator between the
325
- # fractional and integer digits (defaults to ".").
326
- # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults
327
- # to "").
328
- # * <tt>:strip_insignificant_zeros</tt> - If +true+ removes
329
- # insignificant zeros after the decimal separator (defaults to
330
- # +true+)
331
- # * <tt>:units</tt> - A Hash of unit quantifier names. Or a
332
- # string containing an i18n scope where to find this hash. It
333
- # might have the following keys:
334
- # * *integers*: <tt>:unit</tt>, <tt>:ten</tt>,
335
- # <tt>:hundred</tt>, <tt>:thousand</tt>, <tt>:million</tt>,
336
- # <tt>:billion</tt>, <tt>:trillion</tt>,
337
- # <tt>:quadrillion</tt>
338
- # * *fractionals*: <tt>:deci</tt>, <tt>:centi</tt>,
339
- # <tt>:mili</tt>, <tt>:micro</tt>, <tt>:nano</tt>,
340
- # <tt>:pico</tt>, <tt>:femto</tt>
341
- # * <tt>:format</tt> - Sets the format of the output string
342
- # (defaults to "%n %u"). The field types are:
343
- # * %u - The quantifier (ex.: 'thousand')
344
- # * %n - The number
345
- # * <tt>:raise</tt> - If true, raises +InvalidNumberError+ when
346
- # the argument is invalid.
347
- #
348
- # ==== Examples
349
- #
350
- # number_to_human(123) # => "123"
351
- # number_to_human(1234) # => "1.23 Thousand"
352
- # number_to_human(12345) # => "12.3 Thousand"
353
- # number_to_human(1234567) # => "1.23 Million"
354
- # number_to_human(1234567890) # => "1.23 Billion"
355
- # number_to_human(1234567890123) # => "1.23 Trillion"
356
- # number_to_human(1234567890123456) # => "1.23 Quadrillion"
357
- # number_to_human(1234567890123456789) # => "1230 Quadrillion"
358
- # number_to_human(489939, precision: 2) # => "490 Thousand"
359
- # number_to_human(489939, precision: 4) # => "489.9 Thousand"
360
- # number_to_human(1234567, precision: 4,
361
- # significant: false) # => "1.2346 Million"
362
- # number_to_human(1234567, precision: 1,
363
- # separator: ',',
364
- # significant: false) # => "1,2 Million"
365
- #
366
- # number_to_human(500000000, precision: 5) # => "500 Million"
367
- # number_to_human(12345012345, significant: false) # => "12.345 Billion"
368
- #
369
- # Non-significant zeros after the decimal separator are stripped
370
- # out by default (set <tt>:strip_insignificant_zeros</tt> to
371
- # +false+ to change that):
372
- #
373
- # number_to_human(12.00001) # => "12"
374
- # number_to_human(12.00001, strip_insignificant_zeros: false) # => "12.0"
375
- #
376
- # ==== Custom Unit Quantifiers
377
- #
378
- # You can also use your own custom unit quantifiers:
379
- # number_to_human(500000, units: {unit: "ml", thousand: "lt"}) # => "500 lt"
380
- #
381
- # If in your I18n locale you have:
382
- # distance:
383
- # centi:
384
- # one: "centimeter"
385
- # other: "centimeters"
386
- # unit:
387
- # one: "meter"
388
- # other: "meters"
389
- # thousand:
390
- # one: "kilometer"
391
- # other: "kilometers"
392
- # billion: "gazillion-distance"
103
+ # Delegates to ActiveSupport::NumberHelper#number_to_human.
393
104
  #
394
- # Then you could do:
105
+ # Additionally, supports a +:raise+ option that will cause
106
+ # InvalidNumberError to be raised if +number+ is not a valid number:
395
107
  #
396
- # number_to_human(543934, units: :distance) # => "544 kilometers"
397
- # number_to_human(54393498, units: :distance) # => "54400 kilometers"
398
- # number_to_human(54393498000, units: :distance) # => "54.4 gazillion-distance"
399
- # number_to_human(343, units: :distance, precision: 1) # => "300 meters"
400
- # number_to_human(1, units: :distance) # => "1 meter"
401
- # number_to_human(0.34, units: :distance) # => "34 centimeters"
108
+ # number_to_human("12x34") # => "12x34"
109
+ # number_to_human("12x34", raise: true) # => InvalidNumberError
402
110
  #
403
111
  def number_to_human(number, options = {})
404
112
  delegate_number_helper_method(:number_to_human, number, options)
@@ -3,18 +3,18 @@
3
3
  require "active_support/core_ext/string/output_safety"
4
4
 
5
5
  module ActionView # :nodoc:
6
- # = Action View Raw Output Helper
7
6
  module Helpers # :nodoc:
7
+ # = Action View Raw Output \Helpers
8
8
  module OutputSafetyHelper
9
9
  # This method outputs without escaping a string. Since escaping tags is
10
- # now default, this can be used when you don't want Rails to automatically
10
+ # now default, this can be used when you don't want \Rails to automatically
11
11
  # escape tags. This is not recommended if the data is coming from the user's
12
12
  # input.
13
13
  #
14
14
  # For example:
15
15
  #
16
- # raw @user.name
17
- # # => 'Jimmy <alert>Tables</alert>'
16
+ # raw @user.name
17
+ # # => 'Jimmy <alert>Tables</alert>'
18
18
  def raw(stringish)
19
19
  stringish.to_s.html_safe
20
20
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module ActionView
4
4
  module Helpers # :nodoc:
5
- # = Action View Rendering
5
+ # = Action View \Rendering \Helpers
6
6
  #
7
7
  # Implements methods that allow rendering from a view context.
8
8
  # In order to use this module, all you need is to implement