actionview 5.1.7 → 5.2.0.beta1

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 (107) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +27 -275
  3. data/README.rdoc +1 -1
  4. data/lib/action_view.rb +3 -2
  5. data/lib/action_view/base.rb +8 -10
  6. data/lib/action_view/buffers.rb +2 -0
  7. data/lib/action_view/context.rb +2 -2
  8. data/lib/action_view/dependency_tracker.rb +2 -0
  9. data/lib/action_view/digestor.rb +6 -12
  10. data/lib/action_view/flows.rb +2 -0
  11. data/lib/action_view/gem_version.rb +5 -3
  12. data/lib/action_view/helpers.rb +2 -0
  13. data/lib/action_view/helpers/active_model_helper.rb +9 -3
  14. data/lib/action_view/helpers/asset_tag_helper.rb +79 -22
  15. data/lib/action_view/helpers/asset_url_helper.rb +13 -11
  16. data/lib/action_view/helpers/atom_feed_helper.rb +3 -1
  17. data/lib/action_view/helpers/cache_helper.rb +24 -14
  18. data/lib/action_view/helpers/capture_helper.rb +9 -7
  19. data/lib/action_view/helpers/controller_helper.rb +3 -1
  20. data/lib/action_view/helpers/csrf_helper.rb +4 -2
  21. data/lib/action_view/helpers/date_helper.rb +5 -3
  22. data/lib/action_view/helpers/debug_helper.rb +3 -1
  23. data/lib/action_view/helpers/form_helper.rb +43 -60
  24. data/lib/action_view/helpers/form_options_helper.rb +9 -7
  25. data/lib/action_view/helpers/form_tag_helper.rb +20 -11
  26. data/lib/action_view/helpers/javascript_helper.rb +5 -3
  27. data/lib/action_view/helpers/number_helper.rb +2 -0
  28. data/lib/action_view/helpers/output_safety_helper.rb +2 -0
  29. data/lib/action_view/helpers/record_tag_helper.rb +3 -1
  30. data/lib/action_view/helpers/rendering_helper.rb +4 -1
  31. data/lib/action_view/helpers/sanitize_helper.rb +3 -1
  32. data/lib/action_view/helpers/tag_helper.rb +2 -2
  33. data/lib/action_view/helpers/tags.rb +3 -1
  34. data/lib/action_view/helpers/tags/base.rb +12 -10
  35. data/lib/action_view/helpers/tags/check_box.rb +3 -1
  36. data/lib/action_view/helpers/tags/checkable.rb +4 -2
  37. data/lib/action_view/helpers/tags/collection_check_boxes.rb +2 -0
  38. data/lib/action_view/helpers/tags/collection_helpers.rb +2 -0
  39. data/lib/action_view/helpers/tags/collection_radio_buttons.rb +2 -0
  40. data/lib/action_view/helpers/tags/collection_select.rb +3 -1
  41. data/lib/action_view/helpers/tags/color_field.rb +3 -1
  42. data/lib/action_view/helpers/tags/date_field.rb +2 -0
  43. data/lib/action_view/helpers/tags/date_select.rb +3 -1
  44. data/lib/action_view/helpers/tags/datetime_field.rb +3 -1
  45. data/lib/action_view/helpers/tags/datetime_local_field.rb +2 -0
  46. data/lib/action_view/helpers/tags/datetime_select.rb +2 -0
  47. data/lib/action_view/helpers/tags/email_field.rb +2 -0
  48. data/lib/action_view/helpers/tags/file_field.rb +2 -0
  49. data/lib/action_view/helpers/tags/grouped_collection_select.rb +3 -1
  50. data/lib/action_view/helpers/tags/hidden_field.rb +2 -0
  51. data/lib/action_view/helpers/tags/label.rb +2 -4
  52. data/lib/action_view/helpers/tags/month_field.rb +2 -0
  53. data/lib/action_view/helpers/tags/number_field.rb +2 -0
  54. data/lib/action_view/helpers/tags/password_field.rb +2 -0
  55. data/lib/action_view/helpers/tags/placeholderable.rb +2 -0
  56. data/lib/action_view/helpers/tags/radio_button.rb +3 -1
  57. data/lib/action_view/helpers/tags/range_field.rb +2 -0
  58. data/lib/action_view/helpers/tags/search_field.rb +2 -0
  59. data/lib/action_view/helpers/tags/select.rb +5 -3
  60. data/lib/action_view/helpers/tags/tel_field.rb +2 -0
  61. data/lib/action_view/helpers/tags/text_area.rb +3 -1
  62. data/lib/action_view/helpers/tags/text_field.rb +3 -1
  63. data/lib/action_view/helpers/tags/time_field.rb +2 -0
  64. data/lib/action_view/helpers/tags/time_select.rb +2 -0
  65. data/lib/action_view/helpers/tags/time_zone_select.rb +3 -1
  66. data/lib/action_view/helpers/tags/translator.rb +2 -0
  67. data/lib/action_view/helpers/tags/url_field.rb +2 -0
  68. data/lib/action_view/helpers/tags/week_field.rb +2 -0
  69. data/lib/action_view/helpers/text_helper.rb +4 -2
  70. data/lib/action_view/helpers/translation_helper.rb +5 -4
  71. data/lib/action_view/helpers/url_helper.rb +24 -5
  72. data/lib/action_view/layouts.rb +7 -5
  73. data/lib/action_view/log_subscriber.rb +5 -3
  74. data/lib/action_view/lookup_context.rb +4 -4
  75. data/lib/action_view/model_naming.rb +2 -0
  76. data/lib/action_view/path_set.rb +2 -0
  77. data/lib/action_view/railtie.rb +11 -2
  78. data/lib/action_view/record_identifier.rb +2 -0
  79. data/lib/action_view/renderer/abstract_renderer.rb +2 -0
  80. data/lib/action_view/renderer/partial_renderer.rb +13 -11
  81. data/lib/action_view/renderer/partial_renderer/collection_caching.rb +4 -2
  82. data/lib/action_view/renderer/renderer.rb +2 -0
  83. data/lib/action_view/renderer/streaming_template_renderer.rb +3 -1
  84. data/lib/action_view/renderer/template_renderer.rb +2 -0
  85. data/lib/action_view/rendering.rb +3 -5
  86. data/lib/action_view/routing_url_for.rb +2 -0
  87. data/lib/action_view/tasks/cache_digests.rake +2 -0
  88. data/lib/action_view/template.rb +6 -4
  89. data/lib/action_view/template/error.rb +2 -3
  90. data/lib/action_view/template/handlers.rb +3 -1
  91. data/lib/action_view/template/handlers/builder.rb +3 -4
  92. data/lib/action_view/template/handlers/erb.rb +5 -9
  93. data/lib/action_view/template/handlers/erb/erubi.rb +2 -0
  94. data/lib/action_view/template/handlers/html.rb +2 -0
  95. data/lib/action_view/template/handlers/raw.rb +2 -0
  96. data/lib/action_view/template/html.rb +3 -1
  97. data/lib/action_view/template/resolver.rb +7 -6
  98. data/lib/action_view/template/text.rb +3 -1
  99. data/lib/action_view/template/types.rb +3 -1
  100. data/lib/action_view/test_case.rb +21 -5
  101. data/lib/action_view/testing/resolvers.rb +3 -1
  102. data/lib/action_view/version.rb +2 -0
  103. data/lib/action_view/view_paths.rb +3 -3
  104. data/lib/assets/compiled/rails-ujs.js +3 -3
  105. metadata +14 -15
  106. data/lib/action_view/template/handlers/erb/deprecated_erubis.rb +0 -9
  107. data/lib/action_view/template/handlers/erb/erubis.rb +0 -81
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "concurrent/map"
2
4
  require "action_view/path_set"
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "concurrent/map"
2
4
  require "action_view/dependency_tracker"
3
5
  require "monitor"
@@ -44,7 +46,10 @@ module ActionView
44
46
  def tree(name, finder, partial = false, seen = {})
45
47
  logical_name = name.gsub(%r|/_|, "/")
46
48
 
47
- if template = find_template(finder, logical_name, [], partial, [])
49
+ options = {}
50
+ options[:formats] = [finder.rendered_format] if finder.rendered_format
51
+
52
+ if template = finder.disable_cache { finder.find_all(logical_name, [], partial, [], options).first }
48
53
  finder.rendered_format ||= template.formats.first
49
54
 
50
55
  if node = seen[template.identifier] # handle cycles in the tree
@@ -66,17 +71,6 @@ module ActionView
66
71
  seen[name] ||= Missing.new(name, logical_name, nil)
67
72
  end
68
73
  end
69
-
70
- private
71
- def find_template(finder, *args)
72
- finder.disable_cache do
73
- if format = finder.rendered_format
74
- finder.find_all(*args, formats: [format]).first || finder.find_all(*args).first
75
- else
76
- finder.find_all(*args).first
77
- end
78
- end
79
- end
80
74
  end
81
75
 
82
76
  class Node
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/string/output_safety"
2
4
 
3
5
  module ActionView
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionView
2
4
  # Returns the version of the currently loaded Action View as a <tt>Gem::Version</tt>
3
5
  def self.gem_version
@@ -6,9 +8,9 @@ module ActionView
6
8
 
7
9
  module VERSION
8
10
  MAJOR = 5
9
- MINOR = 1
10
- TINY = 7
11
- PRE = nil
11
+ MINOR = 2
12
+ TINY = 0
13
+ PRE = "beta1"
12
14
 
13
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
14
16
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/benchmarkable"
2
4
 
3
5
  module ActionView #:nodoc:
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/module/attribute_accessors"
2
4
  require "active_support/core_ext/enumerable"
3
5
 
4
6
  module ActionView
5
7
  # = Active Model Helpers
6
- module Helpers
8
+ module Helpers #:nodoc:
7
9
  module ActiveModelHelper
8
10
  end
9
11
 
@@ -15,8 +17,8 @@ module ActionView
15
17
  end
16
18
  end
17
19
 
18
- def content_tag(*)
19
- error_wrapping(super)
20
+ def content_tag(type, options, *)
21
+ select_markup_helper?(type) ? super : error_wrapping(super)
20
22
  end
21
23
 
22
24
  def tag(type, options, *)
@@ -41,6 +43,10 @@ module ActionView
41
43
  object.respond_to?(:errors) && object.errors.respond_to?(:[]) && error_message.present?
42
44
  end
43
45
 
46
+ def select_markup_helper?(type)
47
+ ["optgroup", "option"].include?(type)
48
+ end
49
+
44
50
  def tag_generate_errors?(options)
45
51
  options["type"] != "hidden"
46
52
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/array/extract_options"
2
4
  require "active_support/core_ext/hash/keys"
3
5
  require "action_view/helpers/asset_url_helper"
@@ -11,7 +13,7 @@ module ActionView
11
13
  # the assets exist before linking to them:
12
14
  #
13
15
  # image_tag("rails.png")
14
- # # => <img alt="Rails" src="/assets/rails.png" />
16
+ # # => <img src="/assets/rails.png" />
15
17
  # stylesheet_link_tag("application")
16
18
  # # => <link href="/assets/application.css?body=1" media="screen" rel="stylesheet" />
17
19
  module AssetTagHelper
@@ -35,6 +37,9 @@ module ActionView
35
37
  # When the Asset Pipeline is enabled, you can pass the name of your manifest as
36
38
  # source, and include other JavaScript or CoffeeScript files inside the manifest.
37
39
  #
40
+ # If the server supports Early Hints header links for these assets will be
41
+ # automatically pushed.
42
+ #
38
43
  # ==== Options
39
44
  #
40
45
  # When the last parameter is a hash you can add HTML attributes using that
@@ -75,12 +80,20 @@ module ActionView
75
80
  def javascript_include_tag(*sources)
76
81
  options = sources.extract_options!.stringify_keys
77
82
  path_options = options.extract!("protocol", "extname", "host", "skip_pipeline").symbolize_keys
78
- sources.uniq.map { |source|
83
+ early_hints_links = []
84
+
85
+ sources_tags = sources.uniq.map { |source|
86
+ href = path_to_javascript(source, path_options)
87
+ early_hints_links << "<#{href}>; rel=preload; as=script"
79
88
  tag_options = {
80
- "src" => path_to_javascript(source, path_options)
89
+ "src" => href
81
90
  }.merge!(options)
82
91
  content_tag("script".freeze, "", tag_options)
83
92
  }.join("\n").html_safe
93
+
94
+ request.send_early_hints("Link" => early_hints_links.join("\n")) if respond_to?(:request)
95
+
96
+ sources_tags
84
97
  end
85
98
 
86
99
  # Returns a stylesheet link tag for the sources specified as arguments. If
@@ -90,6 +103,9 @@ module ActionView
90
103
  # to "screen", so you must explicitly set it to "all" for the stylesheet(s) to
91
104
  # apply to all media types.
92
105
  #
106
+ # If the server supports Early Hints header links for these assets will be
107
+ # automatically pushed.
108
+ #
93
109
  # stylesheet_link_tag "style"
94
110
  # # => <link href="/assets/style.css" media="screen" rel="stylesheet" />
95
111
  #
@@ -111,20 +127,28 @@ module ActionView
111
127
  def stylesheet_link_tag(*sources)
112
128
  options = sources.extract_options!.stringify_keys
113
129
  path_options = options.extract!("protocol", "host", "skip_pipeline").symbolize_keys
114
- sources.uniq.map { |source|
130
+ early_hints_links = []
131
+
132
+ sources_tags = sources.uniq.map { |source|
133
+ href = path_to_stylesheet(source, path_options)
134
+ early_hints_links << "<#{href}>; rel=preload; as=stylesheet"
115
135
  tag_options = {
116
136
  "rel" => "stylesheet",
117
137
  "media" => "screen",
118
- "href" => path_to_stylesheet(source, path_options)
138
+ "href" => href
119
139
  }.merge!(options)
120
140
  tag(:link, tag_options)
121
141
  }.join("\n").html_safe
142
+
143
+ request.send_early_hints("Link" => early_hints_links.join("\n")) if respond_to?(:request)
144
+
145
+ sources_tags
122
146
  end
123
147
 
124
148
  # Returns a link tag that browsers and feed readers can use to auto-detect
125
- # an RSS or Atom feed. The +type+ can either be <tt>:rss</tt> (default) or
126
- # <tt>:atom</tt>. Control the link options in url_for format using the
127
- # +url_options+. You can modify the LINK tag itself in +tag_options+.
149
+ # an RSS, Atom, or JSON feed. The +type+ can be <tt>:rss</tt> (default),
150
+ # <tt>:atom</tt>, or <tt>:json</tt>. Control the link options in url_for format
151
+ # using the +url_options+. You can modify the LINK tag itself in +tag_options+.
128
152
  #
129
153
  # ==== Options
130
154
  #
@@ -138,6 +162,8 @@ module ActionView
138
162
  # # => <link rel="alternate" type="application/rss+xml" title="RSS" href="http://www.currenthost.com/controller/action" />
139
163
  # auto_discovery_link_tag(:atom)
140
164
  # # => <link rel="alternate" type="application/atom+xml" title="ATOM" href="http://www.currenthost.com/controller/action" />
165
+ # auto_discovery_link_tag(:json)
166
+ # # => <link rel="alternate" type="application/json" title="JSON" href="http://www.currenthost.com/controller/action" />
141
167
  # auto_discovery_link_tag(:rss, {action: "feed"})
142
168
  # # => <link rel="alternate" type="application/rss+xml" title="RSS" href="http://www.currenthost.com/controller/feed" />
143
169
  # auto_discovery_link_tag(:rss, {action: "feed"}, {title: "My RSS"})
@@ -147,8 +173,8 @@ module ActionView
147
173
  # auto_discovery_link_tag(:rss, "http://www.example.com/feed.rss", {title: "Example RSS"})
148
174
  # # => <link rel="alternate" type="application/rss+xml" title="Example RSS" href="http://www.example.com/feed.rss" />
149
175
  def auto_discovery_link_tag(type = :rss, url_options = {}, tag_options = {})
150
- if !(type == :rss || type == :atom) && tag_options[:type].blank?
151
- raise ArgumentError.new("You should pass :type tag_option key explicitly, because you have passed #{type} type other than :rss or :atom.")
176
+ if !(type == :rss || type == :atom || type == :json) && tag_options[:type].blank?
177
+ raise ArgumentError.new("You should pass :type tag_option key explicitly, because you have passed #{type} type other than :rss, :atom, or :json.")
152
178
  end
153
179
 
154
180
  tag(
@@ -196,43 +222,62 @@ module ActionView
196
222
  end
197
223
 
198
224
  # Returns an HTML image tag for the +source+. The +source+ can be a full
199
- # path or a file.
225
+ # path, a file or an Active Storage attachment.
200
226
  #
201
227
  # ==== Options
202
228
  #
203
229
  # You can add HTML attributes using the +options+. The +options+ supports
204
- # two additional keys for convenience and conformance:
230
+ # additional keys for convenience and conformance:
205
231
  #
206
- # * <tt>:alt</tt> - If no alt text is given, the file name part of the
207
- # +source+ is used (capitalized and without the extension)
208
232
  # * <tt>:size</tt> - Supplied as "{Width}x{Height}" or "{Number}", so "30x45" becomes
209
233
  # width="30" and height="45", and "50" becomes width="50" and height="50".
210
234
  # <tt>:size</tt> will be ignored if the value is not in the correct format.
235
+ # * <tt>:srcset</tt> - If supplied as a hash or array of <tt>[source, descriptor]</tt>
236
+ # pairs, each image path will be expanded before the list is formatted as a string.
211
237
  #
212
238
  # ==== Examples
213
239
  #
240
+ # Assets (images that are part of your app):
241
+ #
214
242
  # image_tag("icon")
215
- # # => <img alt="Icon" src="/assets/icon" />
243
+ # # => <img src="/assets/icon" />
216
244
  # image_tag("icon.png")
217
- # # => <img alt="Icon" src="/assets/icon.png" />
245
+ # # => <img src="/assets/icon.png" />
218
246
  # image_tag("icon.png", size: "16x10", alt: "Edit Entry")
219
247
  # # => <img src="/assets/icon.png" width="16" height="10" alt="Edit Entry" />
220
248
  # image_tag("/icons/icon.gif", size: "16")
221
- # # => <img src="/icons/icon.gif" width="16" height="16" alt="Icon" />
249
+ # # => <img src="/icons/icon.gif" width="16" height="16" />
222
250
  # image_tag("/icons/icon.gif", height: '32', width: '32')
223
- # # => <img alt="Icon" height="32" src="/icons/icon.gif" width="32" />
251
+ # # => <img height="32" src="/icons/icon.gif" width="32" />
224
252
  # image_tag("/icons/icon.gif", class: "menu_icon")
225
- # # => <img alt="Icon" class="menu_icon" src="/icons/icon.gif" />
253
+ # # => <img class="menu_icon" src="/icons/icon.gif" />
226
254
  # image_tag("/icons/icon.gif", data: { title: 'Rails Application' })
227
255
  # # => <img data-title="Rails Application" src="/icons/icon.gif" />
256
+ # image_tag("icon.png", srcset: { "icon_2x.png" => "2x", "icon_4x.png" => "4x" })
257
+ # # => <img src="/assets/icon.png" srcset="/assets/icon_2x.png 2x, /assets/icon_4x.png 4x">
258
+ # image_tag("pic.jpg", srcset: [["pic_1024.jpg", "1024w"], ["pic_1980.jpg", "1980w"]], sizes: "100vw")
259
+ # # => <img src="/assets/pic.jpg" srcset="/assets/pic_1024.jpg 1024w, /assets/pic_1980.jpg 1980w" sizes="100vw">
260
+ #
261
+ # Active Storage (images that are uploaded by the users of your app):
262
+ #
263
+ # image_tag(user.avatar)
264
+ # # => <img src="/rails/active_storage/blobs/.../tiger.jpg" />
265
+ # image_tag(user.avatar.variant(resize: "100x100"))
266
+ # # => <img src="/rails/active_storage/variants/.../tiger.jpg" />
267
+ # image_tag(user.avatar.variant(resize: "100x100"), size: '100')
268
+ # # => <img width="100" height="100" src="/rails/active_storage/variants/.../tiger.jpg" />
228
269
  def image_tag(source, options = {})
229
270
  options = options.symbolize_keys
230
271
  check_for_image_tag_errors(options)
272
+ skip_pipeline = options.delete(:skip_pipeline)
231
273
 
232
- src = options[:src] = path_to_image(source, skip_pipeline: options.delete(:skip_pipeline))
274
+ options[:src] = resolve_image_source(source, skip_pipeline)
233
275
 
234
- unless src.start_with?("cid:") || src.start_with?("data:") || src.blank?
235
- options[:alt] = options.fetch(:alt) { image_alt(src) }
276
+ if options[:srcset] && !options[:srcset].is_a?(String)
277
+ options[:srcset] = options[:srcset].map do |src_path, size|
278
+ src_path = path_to_image(src_path, skip_pipeline: skip_pipeline)
279
+ "#{src_path} #{size}"
280
+ end.join(", ")
236
281
  end
237
282
 
238
283
  options[:width], options[:height] = extract_dimensions(options.delete(:size)) if options[:size]
@@ -257,6 +302,8 @@ module ActionView
257
302
  # image_alt('underscored_file_name.png')
258
303
  # # => Underscored file name
259
304
  def image_alt(src)
305
+ ActiveSupport::Deprecation.warn("image_alt is deprecated and will be removed from Rails 6.0. You must explicitly set alt text on images.")
306
+
260
307
  File.basename(src, ".*".freeze).sub(/-[[:xdigit:]]{32,64}\z/, "".freeze).tr("-_".freeze, " ".freeze).capitalize
261
308
  end
262
309
 
@@ -346,6 +393,16 @@ module ActionView
346
393
  end
347
394
  end
348
395
 
396
+ def resolve_image_source(source, skip_pipeline)
397
+ if source.is_a?(Symbol) || source.is_a?(String)
398
+ path_to_image(source, skip_pipeline: skip_pipeline)
399
+ else
400
+ polymorphic_url(source)
401
+ end
402
+ rescue NoMethodError => e
403
+ raise ArgumentError, "Can't resolve image into URL: #{e}"
404
+ end
405
+
349
406
  def extract_dimensions(size)
350
407
  size = size.to_s
351
408
  if /\A\d+x\d+\z/.match?(size)
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "zlib"
2
4
 
3
5
  module ActionView
4
6
  # = Action View Asset URL Helpers
5
- module Helpers
7
+ module Helpers #:nodoc:
6
8
  # This module provides methods for generating asset paths and
7
9
  # urls.
8
10
  #
@@ -27,7 +29,7 @@ module ActionView
27
29
  # Helpers take that into account:
28
30
  #
29
31
  # image_tag("rails.png")
30
- # # => <img alt="Rails" src="http://assets.example.com/assets/rails.png" />
32
+ # # => <img src="http://assets.example.com/assets/rails.png" />
31
33
  # stylesheet_link_tag("application")
32
34
  # # => <link href="http://assets.example.com/assets/application.css" media="screen" rel="stylesheet" />
33
35
  #
@@ -40,7 +42,7 @@ module ActionView
40
42
  # "assets0.example.com", ..., "assets3.example.com".
41
43
  #
42
44
  # image_tag("rails.png")
43
- # # => <img alt="Rails" src="http://assets0.example.com/assets/rails.png" />
45
+ # # => <img src="http://assets0.example.com/assets/rails.png" />
44
46
  # stylesheet_link_tag("application")
45
47
  # # => <link href="http://assets2.example.com/assets/application.css" media="screen" rel="stylesheet" />
46
48
  #
@@ -66,7 +68,7 @@ module ActionView
66
68
  # "http://assets#{Digest::MD5.hexdigest(source).to_i(16) % 2 + 1}.example.com"
67
69
  # }
68
70
  # image_tag("rails.png")
69
- # # => <img alt="Rails" src="http://assets1.example.com/assets/rails.png" />
71
+ # # => <img src="http://assets1.example.com/assets/rails.png" />
70
72
  # stylesheet_link_tag("application")
71
73
  # # => <link href="http://assets2.example.com/assets/application.css" media="screen" rel="stylesheet" />
72
74
  #
@@ -85,7 +87,7 @@ module ActionView
85
87
  # end
86
88
  # }
87
89
  # image_tag("rails.png")
88
- # # => <img alt="Rails" src="http://assets.example.com/assets/rails.png" />
90
+ # # => <img src="http://assets.example.com/assets/rails.png" />
89
91
  # stylesheet_link_tag("application")
90
92
  # # => <link href="http://stylesheets.example.com/assets/application.css" media="screen" rel="stylesheet" />
91
93
  #
@@ -322,7 +324,7 @@ module ActionView
322
324
  # Since +javascript_url+ is based on +asset_url+ method you can set :host options. If :host
323
325
  # options is set, it overwrites global +config.action_controller.asset_host+ setting.
324
326
  #
325
- # javascript_url "js/xmlhr.js", host: "http://stage.example.com" # => http://stage.example.com/assets/dir/xmlhr.js
327
+ # javascript_url "js/xmlhr.js", host: "http://stage.example.com" # => http://stage.example.com/assets/js/xmlhr.js
326
328
  #
327
329
  def javascript_url(source, options = {})
328
330
  url_to_asset(source, { type: :javascript }.merge!(options))
@@ -349,7 +351,7 @@ module ActionView
349
351
  # Since +stylesheet_url+ is based on +asset_url+ method you can set :host options. If :host
350
352
  # options is set, it overwrites global +config.action_controller.asset_host+ setting.
351
353
  #
352
- # stylesheet_url "css/style.css", host: "http://stage.example.com" # => http://stage.example.com/css/style.css
354
+ # stylesheet_url "css/style.css", host: "http://stage.example.com" # => http://stage.example.com/assets/css/style.css
353
355
  #
354
356
  def stylesheet_url(source, options = {})
355
357
  url_to_asset(source, { type: :stylesheet }.merge!(options))
@@ -379,7 +381,7 @@ module ActionView
379
381
  # Since +image_url+ is based on +asset_url+ method you can set :host options. If :host
380
382
  # options is set, it overwrites global +config.action_controller.asset_host+ setting.
381
383
  #
382
- # image_url "edit.png", host: "http://stage.example.com" # => http://stage.example.com/edit.png
384
+ # image_url "edit.png", host: "http://stage.example.com" # => http://stage.example.com/assets/edit.png
383
385
  #
384
386
  def image_url(source, options = {})
385
387
  url_to_asset(source, { type: :image }.merge!(options))
@@ -405,7 +407,7 @@ module ActionView
405
407
  # Since +video_url+ is based on +asset_url+ method you can set :host options. If :host
406
408
  # options is set, it overwrites global +config.action_controller.asset_host+ setting.
407
409
  #
408
- # video_url "hd.avi", host: "http://stage.example.com" # => http://stage.example.com/hd.avi
410
+ # video_url "hd.avi", host: "http://stage.example.com" # => http://stage.example.com/videos/hd.avi
409
411
  #
410
412
  def video_url(source, options = {})
411
413
  url_to_asset(source, { type: :video }.merge!(options))
@@ -431,7 +433,7 @@ module ActionView
431
433
  # Since +audio_url+ is based on +asset_url+ method you can set :host options. If :host
432
434
  # options is set, it overwrites global +config.action_controller.asset_host+ setting.
433
435
  #
434
- # audio_url "horse.wav", host: "http://stage.example.com" # => http://stage.example.com/horse.wav
436
+ # audio_url "horse.wav", host: "http://stage.example.com" # => http://stage.example.com/audios/horse.wav
435
437
  #
436
438
  def audio_url(source, options = {})
437
439
  url_to_asset(source, { type: :audio }.merge!(options))
@@ -456,7 +458,7 @@ module ActionView
456
458
  # Since +font_url+ is based on +asset_url+ method you can set :host options. If :host
457
459
  # options is set, it overwrites global +config.action_controller.asset_host+ setting.
458
460
  #
459
- # font_url "font.ttf", host: "http://stage.example.com" # => http://stage.example.com/font.ttf
461
+ # font_url "font.ttf", host: "http://stage.example.com" # => http://stage.example.com/fonts/font.ttf
460
462
  #
461
463
  def font_url(source, options = {})
462
464
  url_to_asset(source, { type: :font }.merge!(options))
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "set"
2
4
 
3
5
  module ActionView
4
6
  # = Action View Atom Feed Helpers
5
- module Helpers
7
+ module Helpers #:nodoc:
6
8
  module AtomFeedHelper
7
9
  # Adds easy defaults to writing Atom feeds with the Builder template engine (this does not work on ERB or any other
8
10
  # template languages).
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionView
2
4
  # = Action View Cache Helper
3
- module Helpers
5
+ module Helpers #:nodoc:
4
6
  module CacheHelper
5
7
  # This helper exposes a method for caching fragments of a view
6
8
  # rather than an entire action or page. This technique is useful
@@ -8,10 +10,9 @@ module ActionView
8
10
  # fragments, and so on. This method takes a block that contains
9
11
  # the content you wish to cache.
10
12
  #
11
- # The best way to use this is by doing key-based cache expiration
12
- # on top of a cache store like Memcached that'll automatically
13
- # kick out old entries. For more on key-based expiration, see:
14
- # http://signalvnoise.com/posts/3113-how-key-based-cache-expiration-works
13
+ # The best way to use this is by doing recyclable key-based cache expiration
14
+ # on top of a cache store like Memcached or Redis that'll automatically
15
+ # kick out old entries.
15
16
  #
16
17
  # When using this method, you list the cache dependency as the name of the cache, like so:
17
18
  #
@@ -23,10 +24,14 @@ module ActionView
23
24
  # This approach will assume that when a new topic is added, you'll touch
24
25
  # the project. The cache key generated from this call will be something like:
25
26
  #
26
- # views/projects/123-20120806214154/7a1156131a6928cb0026877f8b749ac9
27
- # ^class ^id ^updated_at ^template tree digest
27
+ # views/template/action.html.erb:7a1156131a6928cb0026877f8b749ac9/projects/123
28
+ # ^template path ^template tree digest ^class ^id
28
29
  #
29
- # The cache is thus automatically bumped whenever the project updated_at is touched.
30
+ # This cache key is stable, but it's combined with a cache version derived from the project
31
+ # record. When the project updated_at is touched, the #cache_version changes, even
32
+ # if the key stays stable. This means that unlike a traditional key-based cache expiration
33
+ # approach, you won't be generating cache trash, unused keys, simply because the dependent
34
+ # record is updated.
30
35
  #
31
36
  # If your template cache depends on multiple sources (try to avoid this to keep things simple),
32
37
  # you can name all these dependencies as part of an array:
@@ -106,9 +111,9 @@ module ActionView
106
111
  # <%= render_categorizable_events @person.events %>
107
112
  #
108
113
  # This marks every template in the directory as a dependency. To find those
109
- # templates, the wildcard path must be absolutely defined from app/views or paths
114
+ # templates, the wildcard path must be absolutely defined from <tt>app/views</tt> or paths
110
115
  # otherwise added with +prepend_view_path+ or +append_view_path+.
111
- # This way the wildcard for `app/views/recordings/events` would be `recordings/events/*` etc.
116
+ # This way the wildcard for <tt>app/views/recordings/events</tt> would be <tt>recordings/events/*</tt> etc.
112
117
  #
113
118
  # The pattern used to match explicit dependencies is <tt>/# Template Dependency: (\S+)/</tt>,
114
119
  # so it's important that you type it out just so.
@@ -128,14 +133,14 @@ module ActionView
128
133
  #
129
134
  # === Collection Caching
130
135
  #
131
- # When rendering a collection of objects that each use the same partial, a `cached`
136
+ # When rendering a collection of objects that each use the same partial, a <tt>:cached</tt>
132
137
  # option can be passed.
133
138
  #
134
139
  # For collections rendered such:
135
140
  #
136
141
  # <%= render partial: 'projects/project', collection: @projects, cached: true %>
137
142
  #
138
- # The `cached: true` will make Action View's rendering read several templates
143
+ # The <tt>cached: true</tt> will make Action View's rendering read several templates
139
144
  # from cache at once instead of one call per template.
140
145
  #
141
146
  # Templates in the collection not already cached are written to cache.
@@ -215,10 +220,15 @@ module ActionView
215
220
 
216
221
  def fragment_name_with_digest(name, virtual_path)
217
222
  virtual_path ||= @virtual_path
223
+
218
224
  if virtual_path
219
225
  name = controller.url_for(name).split("://").last if name.is_a?(Hash)
220
- digest = Digestor.digest name: virtual_path, finder: lookup_context, dependencies: view_cache_dependencies
221
- [ name, digest ]
226
+
227
+ if digest = Digestor.digest(name: virtual_path, finder: lookup_context, dependencies: view_cache_dependencies).presence
228
+ [ "#{virtual_path}:#{digest}", name ]
229
+ else
230
+ [ virtual_path, name ]
231
+ end
222
232
  else
223
233
  name
224
234
  end