actionview 6.1.7.2 → 7.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +268 -254
  3. data/MIT-LICENSE +1 -0
  4. data/README.rdoc +2 -2
  5. data/lib/action_view/base.rb +4 -7
  6. data/lib/action_view/buffers.rb +2 -2
  7. data/lib/action_view/cache_expiry.rb +46 -32
  8. data/lib/action_view/dependency_tracker/erb_tracker.rb +154 -0
  9. data/lib/action_view/dependency_tracker/ripper_tracker.rb +59 -0
  10. data/lib/action_view/dependency_tracker.rb +6 -147
  11. data/lib/action_view/digestor.rb +7 -4
  12. data/lib/action_view/flows.rb +4 -4
  13. data/lib/action_view/gem_version.rb +5 -5
  14. data/lib/action_view/helpers/active_model_helper.rb +2 -2
  15. data/lib/action_view/helpers/asset_tag_helper.rb +95 -39
  16. data/lib/action_view/helpers/asset_url_helper.rb +16 -16
  17. data/lib/action_view/helpers/atom_feed_helper.rb +3 -4
  18. data/lib/action_view/helpers/cache_helper.rb +52 -3
  19. data/lib/action_view/helpers/capture_helper.rb +4 -4
  20. data/lib/action_view/helpers/controller_helper.rb +2 -2
  21. data/lib/action_view/helpers/csp_helper.rb +1 -1
  22. data/lib/action_view/helpers/csrf_helper.rb +2 -2
  23. data/lib/action_view/helpers/date_helper.rb +111 -43
  24. data/lib/action_view/helpers/debug_helper.rb +3 -1
  25. data/lib/action_view/helpers/form_helper.rb +211 -85
  26. data/lib/action_view/helpers/form_options_helper.rb +70 -33
  27. data/lib/action_view/helpers/form_tag_helper.rb +150 -53
  28. data/lib/action_view/helpers/javascript_helper.rb +3 -5
  29. data/lib/action_view/helpers/number_helper.rb +17 -16
  30. data/lib/action_view/helpers/output_safety_helper.rb +4 -4
  31. data/lib/action_view/helpers/rendering_helper.rb +5 -6
  32. data/lib/action_view/helpers/sanitize_helper.rb +3 -3
  33. data/lib/action_view/helpers/tag_helper.rb +37 -8
  34. data/lib/action_view/helpers/tags/base.rb +5 -25
  35. data/lib/action_view/helpers/tags/check_box.rb +1 -1
  36. data/lib/action_view/helpers/tags/collection_select.rb +1 -1
  37. data/lib/action_view/helpers/tags/file_field.rb +16 -0
  38. data/lib/action_view/helpers/tags/select.rb +1 -1
  39. data/lib/action_view/helpers/tags/time_field.rb +10 -1
  40. data/lib/action_view/helpers/tags/weekday_select.rb +28 -0
  41. data/lib/action_view/helpers/tags.rb +3 -2
  42. data/lib/action_view/helpers/text_helper.rb +25 -14
  43. data/lib/action_view/helpers/translation_helper.rb +12 -43
  44. data/lib/action_view/helpers/url_helper.rb +194 -123
  45. data/lib/action_view/helpers.rb +25 -25
  46. data/lib/action_view/layouts.rb +7 -4
  47. data/lib/action_view/lookup_context.rb +33 -52
  48. data/lib/action_view/model_naming.rb +2 -2
  49. data/lib/action_view/path_set.rb +16 -22
  50. data/lib/action_view/railtie.rb +19 -7
  51. data/lib/action_view/record_identifier.rb +1 -1
  52. data/lib/action_view/render_parser.rb +188 -0
  53. data/lib/action_view/renderer/abstract_renderer.rb +2 -2
  54. data/lib/action_view/renderer/partial_renderer.rb +1 -35
  55. data/lib/action_view/renderer/renderer.rb +4 -4
  56. data/lib/action_view/renderer/streaming_template_renderer.rb +3 -3
  57. data/lib/action_view/renderer/template_renderer.rb +6 -2
  58. data/lib/action_view/rendering.rb +3 -3
  59. data/lib/action_view/ripper_ast_parser.rb +198 -0
  60. data/lib/action_view/routing_url_for.rb +8 -5
  61. data/lib/action_view/template/error.rb +108 -13
  62. data/lib/action_view/template/handlers/erb.rb +6 -0
  63. data/lib/action_view/template/handlers.rb +3 -3
  64. data/lib/action_view/template/html.rb +3 -3
  65. data/lib/action_view/template/inline.rb +3 -3
  66. data/lib/action_view/template/raw_file.rb +3 -3
  67. data/lib/action_view/template/resolver.rb +89 -314
  68. data/lib/action_view/template/text.rb +3 -3
  69. data/lib/action_view/template/types.rb +14 -12
  70. data/lib/action_view/template.rb +18 -2
  71. data/lib/action_view/template_details.rb +66 -0
  72. data/lib/action_view/template_path.rb +64 -0
  73. data/lib/action_view/test_case.rb +7 -3
  74. data/lib/action_view/testing/resolvers.rb +11 -12
  75. data/lib/action_view/unbound_template.rb +33 -7
  76. data/lib/action_view/version.rb +1 -1
  77. data/lib/action_view/view_paths.rb +4 -4
  78. data/lib/action_view.rb +2 -3
  79. data/lib/assets/compiled/rails-ujs.js +36 -5
  80. 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| %>