actionview 6.1.7.2 → 7.0.5

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 (79) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +265 -261
  3. data/MIT-LICENSE +1 -0
  4. data/lib/action_view/base.rb +4 -7
  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 +5 -5
  13. data/lib/action_view/helpers/active_model_helper.rb +2 -2
  14. data/lib/action_view/helpers/asset_tag_helper.rb +95 -39
  15. data/lib/action_view/helpers/asset_url_helper.rb +16 -16
  16. data/lib/action_view/helpers/atom_feed_helper.rb +3 -4
  17. data/lib/action_view/helpers/cache_helper.rb +52 -3
  18. data/lib/action_view/helpers/capture_helper.rb +4 -4
  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 +2 -2
  22. data/lib/action_view/helpers/date_helper.rb +111 -43
  23. data/lib/action_view/helpers/debug_helper.rb +3 -1
  24. data/lib/action_view/helpers/form_helper.rb +211 -85
  25. data/lib/action_view/helpers/form_options_helper.rb +70 -33
  26. data/lib/action_view/helpers/form_tag_helper.rb +150 -53
  27. data/lib/action_view/helpers/javascript_helper.rb +3 -5
  28. data/lib/action_view/helpers/number_helper.rb +17 -16
  29. data/lib/action_view/helpers/output_safety_helper.rb +4 -4
  30. data/lib/action_view/helpers/rendering_helper.rb +5 -6
  31. data/lib/action_view/helpers/sanitize_helper.rb +3 -3
  32. data/lib/action_view/helpers/tag_helper.rb +37 -8
  33. data/lib/action_view/helpers/tags/base.rb +5 -25
  34. data/lib/action_view/helpers/tags/check_box.rb +1 -1
  35. data/lib/action_view/helpers/tags/collection_select.rb +1 -1
  36. data/lib/action_view/helpers/tags/file_field.rb +16 -0
  37. data/lib/action_view/helpers/tags/select.rb +1 -1
  38. data/lib/action_view/helpers/tags/time_field.rb +10 -1
  39. data/lib/action_view/helpers/tags/weekday_select.rb +28 -0
  40. data/lib/action_view/helpers/tags.rb +3 -2
  41. data/lib/action_view/helpers/text_helper.rb +25 -14
  42. data/lib/action_view/helpers/translation_helper.rb +12 -43
  43. data/lib/action_view/helpers/url_helper.rb +194 -123
  44. data/lib/action_view/helpers.rb +25 -25
  45. data/lib/action_view/layouts.rb +7 -4
  46. data/lib/action_view/lookup_context.rb +33 -52
  47. data/lib/action_view/model_naming.rb +2 -2
  48. data/lib/action_view/path_set.rb +16 -22
  49. data/lib/action_view/railtie.rb +19 -7
  50. data/lib/action_view/record_identifier.rb +1 -1
  51. data/lib/action_view/render_parser.rb +188 -0
  52. data/lib/action_view/renderer/abstract_renderer.rb +2 -2
  53. data/lib/action_view/renderer/partial_renderer.rb +1 -35
  54. data/lib/action_view/renderer/renderer.rb +4 -4
  55. data/lib/action_view/renderer/streaming_template_renderer.rb +3 -3
  56. data/lib/action_view/renderer/template_renderer.rb +6 -2
  57. data/lib/action_view/rendering.rb +3 -3
  58. data/lib/action_view/ripper_ast_parser.rb +198 -0
  59. data/lib/action_view/routing_url_for.rb +8 -5
  60. data/lib/action_view/template/error.rb +108 -13
  61. data/lib/action_view/template/handlers/erb.rb +6 -0
  62. data/lib/action_view/template/handlers.rb +3 -3
  63. data/lib/action_view/template/html.rb +3 -3
  64. data/lib/action_view/template/inline.rb +3 -3
  65. data/lib/action_view/template/raw_file.rb +3 -3
  66. data/lib/action_view/template/resolver.rb +89 -314
  67. data/lib/action_view/template/text.rb +3 -3
  68. data/lib/action_view/template/types.rb +14 -12
  69. data/lib/action_view/template.rb +18 -2
  70. data/lib/action_view/template_details.rb +66 -0
  71. data/lib/action_view/template_path.rb +64 -0
  72. data/lib/action_view/test_case.rb +7 -3
  73. data/lib/action_view/testing/resolvers.rb +11 -12
  74. data/lib/action_view/unbound_template.rb +33 -7
  75. data/lib/action_view/version.rb +1 -1
  76. data/lib/action_view/view_paths.rb +4 -4
  77. data/lib/action_view.rb +2 -3
  78. data/lib/assets/compiled/rails-ujs.js +36 -5
  79. metadata +23 -16
@@ -2,21 +2,21 @@
2
2
 
3
3
  require "cgi"
4
4
  require "erb"
5
- require "action_view/helpers/form_helper"
6
5
  require "active_support/core_ext/string/output_safety"
7
6
  require "active_support/core_ext/array/extract_options"
8
7
  require "active_support/core_ext/array/wrap"
8
+ require "action_view/helpers/text_helper"
9
9
 
10
10
  module ActionView
11
11
  # = Action View Form Option Helpers
12
- module Helpers #:nodoc:
12
+ module Helpers # :nodoc:
13
13
  # Provides a number of methods for turning different kinds of containers into a set of option tags.
14
14
  #
15
15
  # The <tt>collection_select</tt>, <tt>select</tt> and <tt>time_zone_select</tt> methods take an <tt>options</tt> parameter, a hash:
16
16
  #
17
17
  # * <tt>:include_blank</tt> - set to true or a prompt string if the first option element of the select element is a blank. Useful if there is not a default value required for the select element.
18
18
  #
19
- # select("post", "category", Post::CATEGORIES, { include_blank: true })
19
+ # select(:post, :category, Post::CATEGORIES, { include_blank: true })
20
20
  #
21
21
  # could become:
22
22
  #
@@ -30,7 +30,7 @@ module ActionView
30
30
  #
31
31
  # Example with <tt>@post.person_id => 2</tt>:
32
32
  #
33
- # select("post", "person_id", Person.all.collect { |p| [ p.name, p.id ] }, { include_blank: 'None' })
33
+ # select(:post, :person_id, Person.all.collect { |p| [ p.name, p.id ] }, { include_blank: "None" })
34
34
  #
35
35
  # could become:
36
36
  #
@@ -43,7 +43,7 @@ module ActionView
43
43
  #
44
44
  # * <tt>:prompt</tt> - set to true or a prompt string. When the select element doesn't have a value yet, this prepends an option with a generic prompt -- "Please select" -- or the given prompt string.
45
45
  #
46
- # select("post", "person_id", Person.all.collect { |p| [ p.name, p.id ] }, { prompt: 'Select Person' })
46
+ # select(:post, :person_id, Person.all.collect { |p| [ p.name, p.id ] }, { prompt: "Select Person" })
47
47
  #
48
48
  # could become:
49
49
  #
@@ -54,10 +54,10 @@ module ActionView
54
54
  # <option value="3">Rafael</option>
55
55
  # </select>
56
56
  #
57
- # * <tt>:index</tt> - like the other form helpers, +select+ can accept an <tt>:index</tt> option to manually set the ID used in the resulting output. Unlike other helpers, +select+ expects this
57
+ # * <tt>:index</tt> - like the other form helpers, <tt>select</tt> can accept an <tt>:index</tt> option to manually set the ID used in the resulting output. Unlike other helpers, <tt>select</tt> expects this
58
58
  # option to be in the +html_options+ parameter.
59
59
  #
60
- # select("album[]", "genre", %w[rap rock country], {}, { index: nil })
60
+ # select("album[]", :genre, %w[ rap rock country ], {}, { index: nil })
61
61
  #
62
62
  # becomes:
63
63
  #
@@ -69,7 +69,7 @@ module ActionView
69
69
  #
70
70
  # * <tt>:disabled</tt> - can be a single value or an array of values that will be disabled options in the final output.
71
71
  #
72
- # select("post", "category", Post::CATEGORIES, { disabled: 'restricted' })
72
+ # select(:post, :category, Post::CATEGORIES, { disabled: "restricted" })
73
73
  #
74
74
  # could become:
75
75
  #
@@ -90,7 +90,6 @@ module ActionView
90
90
  # <option value="3">Jokes</option>
91
91
  # <option value="4">Poems</option>
92
92
  # </select>
93
- #
94
93
  module FormOptionsHelper
95
94
  # ERB::Util can mask some helpers like textilize. Make sure to include them.
96
95
  include TextHelper
@@ -100,25 +99,22 @@ module ActionView
100
99
  #
101
100
  # There are two possible formats for the +choices+ parameter, corresponding to other helpers' output:
102
101
  #
103
- # * A flat collection (see +options_for_select+).
104
- #
105
- # * A nested collection (see +grouped_options_for_select+).
102
+ # * A flat collection (see <tt>options_for_select</tt>).
103
+ # * A nested collection (see <tt>grouped_options_for_select</tt>).
106
104
  #
107
- # For example:
105
+ # Example with <tt>@post.person_id => 2</tt>:
108
106
  #
109
- # select("post", "person_id", Person.all.collect { |p| [ p.name, p.id ] }, { include_blank: true })
107
+ # select :post, :person_id, Person.all.collect { |p| [ p.name, p.id ] }, { include_blank: true })
110
108
  #
111
109
  # would become:
112
110
  #
113
111
  # <select name="post[person_id]" id="post_person_id">
114
112
  # <option value="" label=" "></option>
115
- # <option value="1" selected="selected">David</option>
116
- # <option value="2">Eileen</option>
113
+ # <option value="1">David</option>
114
+ # <option value="2" selected="selected">Eileen</option>
117
115
  # <option value="3">Rafael</option>
118
116
  # </select>
119
117
  #
120
- # assuming the associated person has ID 1.
121
- #
122
118
  # This can be used to provide a default set of options in the standard way: before rendering the create form, a
123
119
  # new model instance is assigned the default options and bound to @model_name. Usually this model is not saved
124
120
  # to the database. Instead, a second model object is created when the create request is received.
@@ -132,9 +128,9 @@ module ActionView
132
128
  # A block can be passed to +select+ to customize how the options tags will be rendered. This
133
129
  # is useful when the options tag has complex attributes.
134
130
  #
135
- # select(report, "campaign_ids") do
131
+ # select(report, :campaign_ids) do
136
132
  # available_campaigns.each do |c|
137
- # content_tag(:option, c.name, value: c.id, data: { tags: c.tags.to_json })
133
+ # tag.option(c.name, value: c.id, data: { tags: c.tags.to_json })
138
134
  # end
139
135
  # end
140
136
  #
@@ -159,7 +155,6 @@ module ActionView
159
155
  #
160
156
  # In case if you don't want the helper to generate this hidden field you can specify
161
157
  # <tt>include_hidden: false</tt> option.
162
- #
163
158
  def select(object, method, choices = nil, options = {}, html_options = {}, &block)
164
159
  Tags::Select.new(object, method, self, choices, options, html_options, &block).render
165
160
  end
@@ -183,6 +178,7 @@ module ActionView
183
178
  #
184
179
  # class Author < ActiveRecord::Base
185
180
  # has_many :posts
181
+ #
186
182
  # def name_with_initial
187
183
  # "#{first_name.first}. #{last_name}"
188
184
  # end
@@ -227,19 +223,19 @@ module ActionView
227
223
  #
228
224
  # Example object structure for use with this method:
229
225
  #
226
+ # # attributes: id, name
230
227
  # class Continent < ActiveRecord::Base
231
228
  # has_many :countries
232
- # # attribs: id, name
233
229
  # end
234
230
  #
231
+ # # attributes: id, name, continent_id
235
232
  # class Country < ActiveRecord::Base
236
233
  # belongs_to :continent
237
- # # attribs: id, name, continent_id
238
234
  # end
239
235
  #
236
+ # # attributes: id, name, country_id
240
237
  # class City < ActiveRecord::Base
241
238
  # belongs_to :country
242
- # # attribs: id, name, country_id
243
239
  # end
244
240
  #
245
241
  # Sample usage:
@@ -258,7 +254,6 @@ module ActionView
258
254
  # <option value="2">Ireland</option>
259
255
  # </optgroup>
260
256
  # </select>
261
- #
262
257
  def grouped_collection_select(object, method, collection, group_method, group_label_method, option_key_method, option_value_method, options = {}, html_options = {})
263
258
  Tags::GroupedCollectionSelect.new(object, method, self, collection, group_method, group_label_method, option_key_method, option_value_method, options, html_options).render
264
259
  end
@@ -282,21 +277,27 @@ module ActionView
282
277
  # Finally, this method supports a <tt>:default</tt> option, which selects
283
278
  # a default ActiveSupport::TimeZone if the object's time zone is +nil+.
284
279
  #
285
- # time_zone_select("user", "time_zone", nil, include_blank: true)
280
+ # time_zone_select(:user, :time_zone, nil, include_blank: true)
286
281
  #
287
- # time_zone_select("user", "time_zone", nil, default: "Pacific Time (US & Canada)")
282
+ # time_zone_select(:user, :time_zone, nil, default: "Pacific Time (US & Canada)")
288
283
  #
289
- # time_zone_select("user", 'time_zone', ActiveSupport::TimeZone.us_zones, default: "Pacific Time (US & Canada)")
284
+ # time_zone_select(:user, :time_zone, ActiveSupport::TimeZone.us_zones, default: "Pacific Time (US & Canada)")
290
285
  #
291
- # time_zone_select("user", 'time_zone', [ ActiveSupport::TimeZone['Alaska'], ActiveSupport::TimeZone['Hawaii'] ])
286
+ # time_zone_select(:user, :time_zone, [ ActiveSupport::TimeZone["Alaska"], ActiveSupport::TimeZone["Hawaii"] ])
292
287
  #
293
- # time_zone_select("user", 'time_zone', /Australia/)
288
+ # time_zone_select(:user, :time_zone, /Australia/)
294
289
  #
295
- # time_zone_select("user", "time_zone", ActiveSupport::TimeZone.all.sort, model: ActiveSupport::TimeZone)
290
+ # time_zone_select(:user, :time_zone, ActiveSupport::TimeZone.all.sort, model: ActiveSupport::TimeZone)
296
291
  def time_zone_select(object, method, priority_zones = nil, options = {}, html_options = {})
297
292
  Tags::TimeZoneSelect.new(object, method, self, priority_zones, options, html_options).render
298
293
  end
299
294
 
295
+ # Returns select and option tags for the given object and method, using
296
+ # <tt>weekday_options_for_select</tt> to generate the list of option tags.
297
+ def weekday_select(object, method, options = {}, html_options = {}, &block)
298
+ Tags::WeekdaySelect.new(object, method, self, options, html_options, &block).render
299
+ end
300
+
300
301
  # Accepts a container (hash, array, enumerable, your type) and returns a string of option tags. Given a container
301
302
  # where the elements respond to first and last (such as a two-element array), the "lasts" serve as option values and
302
303
  # the "firsts" as option text. Hashes are turned into this form automatically, so the keys become "firsts" and values
@@ -499,6 +500,8 @@ module ActionView
499
500
  # <tt><optgroup></tt> label while the second value must be an array of options. The second value can be a
500
501
  # nested array of text-value pairs. See <tt>options_for_select</tt> for more info.
501
502
  # Ex. ["North America",[["United States","US"],["Canada","CA"]]]
503
+ # An optional third value can be provided as HTML attributes for the <tt>optgroup</tt>.
504
+ # Ex. ["North America",[["United States","US"],["Canada","CA"]], { disabled: "disabled" }]
502
505
  # * +selected_key+ - A value equal to the +value+ attribute for one of the <tt><option></tt> tags,
503
506
  # which will have the +selected+ attribute set. Note: It is possible for this value to match multiple options
504
507
  # as you might have the same option in multiple groups. Each will then get <tt>selected="selected"</tt>.
@@ -593,6 +596,25 @@ module ActionView
593
596
  zone_options.safe_concat options_for_select(convert_zones[zones], selected)
594
597
  end
595
598
 
599
+ # Returns a string of option tags for the days of the week.
600
+ #
601
+ # Options:
602
+ # * <tt>:index_as_value</tt> - Defaults to false, set to true to use the indexes from
603
+ # <tt>I18n.translate("date.day_names")</tt> as the values. By default, Sunday is always 0.
604
+ # * <tt>:day_format</tt> - The I18n key of the array to use for the weekday options.
605
+ # Defaults to +:day_names+, set to +:abbr_day_names+ for abbreviations.
606
+ # * <tt>:beginning_of_week</tt> - Defaults to Date.beginning_of_week.
607
+ #
608
+ # NOTE: Only the option tags are returned, you have to wrap this call in
609
+ # a regular HTML select tag.
610
+ def weekday_options_for_select(selected = nil, index_as_value: false, day_format: :day_names, beginning_of_week: Date.beginning_of_week)
611
+ day_names = I18n.translate("date.#{day_format}")
612
+ day_names = day_names.map.with_index.to_a if index_as_value
613
+ day_names = day_names.rotate(Date::DAYS_INTO_WEEK.fetch(beginning_of_week))
614
+
615
+ options_for_select(day_names, selected)
616
+ end
617
+
596
618
  # Returns radio button tags for the collection of existing return values
597
619
  # of +method+ for +object+'s class. The value returned from calling
598
620
  # +method+ on the instance +object+ will be selected. If calling +method+
@@ -606,11 +628,14 @@ module ActionView
606
628
  # retrieve the value/text.
607
629
  #
608
630
  # Example object structure for use with this method:
631
+ #
609
632
  # class Post < ActiveRecord::Base
610
633
  # belongs_to :author
611
634
  # end
635
+ #
612
636
  # class Author < ActiveRecord::Base
613
637
  # has_many :posts
638
+ #
614
639
  # def name_with_initial
615
640
  # "#{first_name.first}. #{last_name}"
616
641
  # end
@@ -793,9 +818,9 @@ module ActionView
793
818
 
794
819
  def extract_values_from_collection(collection, value_method, selected)
795
820
  if selected.is_a?(Proc)
796
- collection.map do |element|
821
+ collection.filter_map do |element|
797
822
  element.public_send(value_method) if selected.call(element)
798
- end.compact
823
+ end
799
824
  else
800
825
  selected
801
826
  end
@@ -859,6 +884,18 @@ module ActionView
859
884
  @template.time_zone_select(@object_name, method, priority_zones, objectify_options(options), @default_html_options.merge(html_options))
860
885
  end
861
886
 
887
+ # Wraps ActionView::Helpers::FormOptionsHelper#weekday_select for form builders:
888
+ #
889
+ # <%= form_for @user do |f| %>
890
+ # <%= f.weekday_select :weekday, include_blank: true %>
891
+ # <%= f.submit %>
892
+ # <% end %>
893
+ #
894
+ # Please refer to the documentation of the base helper for details.
895
+ def weekday_select(method, options = {}, html_options = {})
896
+ @template.weekday_select(@object_name, method, objectify_options(options), @default_html_options.merge(html_options))
897
+ end
898
+
862
899
  # Wraps ActionView::Helpers::FormOptionsHelper#collection_check_boxes for form builders:
863
900
  #
864
901
  # <%= form_for @post do |f| %>