actionview 4.2.11.1 → 7.0.2.4

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 (124) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +229 -215
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +9 -8
  5. data/lib/action_view/base.rb +116 -43
  6. data/lib/action_view/buffers.rb +20 -3
  7. data/lib/action_view/cache_expiry.rb +66 -0
  8. data/lib/action_view/context.rb +8 -12
  9. data/lib/action_view/dependency_tracker/erb_tracker.rb +154 -0
  10. data/lib/action_view/dependency_tracker/ripper_tracker.rb +59 -0
  11. data/lib/action_view/dependency_tracker.rb +21 -122
  12. data/lib/action_view/digestor.rb +92 -85
  13. data/lib/action_view/flows.rb +15 -16
  14. data/lib/action_view/gem_version.rb +6 -4
  15. data/lib/action_view/helpers/active_model_helper.rb +17 -12
  16. data/lib/action_view/helpers/asset_tag_helper.rb +356 -101
  17. data/lib/action_view/helpers/asset_url_helper.rb +180 -74
  18. data/lib/action_view/helpers/atom_feed_helper.rb +21 -19
  19. data/lib/action_view/helpers/cache_helper.rb +156 -43
  20. data/lib/action_view/helpers/capture_helper.rb +21 -14
  21. data/lib/action_view/helpers/controller_helper.rb +16 -5
  22. data/lib/action_view/helpers/csp_helper.rb +26 -0
  23. data/lib/action_view/helpers/csrf_helper.rb +8 -6
  24. data/lib/action_view/helpers/date_helper.rb +288 -132
  25. data/lib/action_view/helpers/debug_helper.rb +9 -6
  26. data/lib/action_view/helpers/form_helper.rb +956 -173
  27. data/lib/action_view/helpers/form_options_helper.rb +178 -97
  28. data/lib/action_view/helpers/form_tag_helper.rb +220 -101
  29. data/lib/action_view/helpers/javascript_helper.rb +33 -19
  30. data/lib/action_view/helpers/number_helper.rb +88 -63
  31. data/lib/action_view/helpers/output_safety_helper.rb +38 -6
  32. data/lib/action_view/helpers/rendering_helper.rb +21 -10
  33. data/lib/action_view/helpers/sanitize_helper.rb +31 -32
  34. data/lib/action_view/helpers/tag_helper.rb +332 -71
  35. data/lib/action_view/helpers/tags/base.rb +123 -99
  36. data/lib/action_view/helpers/tags/check_box.rb +21 -20
  37. data/lib/action_view/helpers/tags/checkable.rb +4 -2
  38. data/lib/action_view/helpers/tags/collection_check_boxes.rb +12 -34
  39. data/lib/action_view/helpers/tags/collection_helpers.rb +69 -36
  40. data/lib/action_view/helpers/tags/collection_radio_buttons.rb +6 -12
  41. data/lib/action_view/helpers/tags/collection_select.rb +5 -3
  42. data/lib/action_view/helpers/tags/color_field.rb +4 -3
  43. data/lib/action_view/helpers/tags/date_field.rb +3 -2
  44. data/lib/action_view/helpers/tags/date_select.rb +38 -37
  45. data/lib/action_view/helpers/tags/datetime_field.rb +4 -3
  46. data/lib/action_view/helpers/tags/datetime_local_field.rb +3 -2
  47. data/lib/action_view/helpers/tags/datetime_select.rb +2 -0
  48. data/lib/action_view/helpers/tags/email_field.rb +2 -0
  49. data/lib/action_view/helpers/tags/file_field.rb +18 -0
  50. data/lib/action_view/helpers/tags/grouped_collection_select.rb +4 -2
  51. data/lib/action_view/helpers/tags/hidden_field.rb +6 -0
  52. data/lib/action_view/helpers/tags/label.rb +7 -2
  53. data/lib/action_view/helpers/tags/month_field.rb +3 -2
  54. data/lib/action_view/helpers/tags/number_field.rb +2 -0
  55. data/lib/action_view/helpers/tags/password_field.rb +3 -1
  56. data/lib/action_view/helpers/tags/placeholderable.rb +3 -1
  57. data/lib/action_view/helpers/tags/radio_button.rb +7 -6
  58. data/lib/action_view/helpers/tags/range_field.rb +2 -0
  59. data/lib/action_view/helpers/tags/search_field.rb +14 -9
  60. data/lib/action_view/helpers/tags/select.rb +11 -10
  61. data/lib/action_view/helpers/tags/tel_field.rb +2 -0
  62. data/lib/action_view/helpers/tags/text_area.rb +4 -2
  63. data/lib/action_view/helpers/tags/text_field.rb +8 -8
  64. data/lib/action_view/helpers/tags/time_field.rb +12 -2
  65. data/lib/action_view/helpers/tags/time_select.rb +2 -0
  66. data/lib/action_view/helpers/tags/time_zone_select.rb +3 -1
  67. data/lib/action_view/helpers/tags/translator.rb +15 -16
  68. data/lib/action_view/helpers/tags/url_field.rb +2 -0
  69. data/lib/action_view/helpers/tags/week_field.rb +3 -2
  70. data/lib/action_view/helpers/tags/weekday_select.rb +28 -0
  71. data/lib/action_view/helpers/tags.rb +5 -2
  72. data/lib/action_view/helpers/text_helper.rb +80 -51
  73. data/lib/action_view/helpers/translation_helper.rb +120 -69
  74. data/lib/action_view/helpers/url_helper.rb +398 -171
  75. data/lib/action_view/helpers.rb +29 -27
  76. data/lib/action_view/layouts.rb +68 -63
  77. data/lib/action_view/log_subscriber.rb +77 -10
  78. data/lib/action_view/lookup_context.rb +137 -113
  79. data/lib/action_view/model_naming.rb +4 -2
  80. data/lib/action_view/path_set.rb +28 -32
  81. data/lib/action_view/railtie.rb +74 -13
  82. data/lib/action_view/record_identifier.rb +53 -26
  83. data/lib/action_view/render_parser.rb +188 -0
  84. data/lib/action_view/renderer/abstract_renderer.rb +152 -15
  85. data/lib/action_view/renderer/collection_renderer.rb +196 -0
  86. data/lib/action_view/renderer/object_renderer.rb +34 -0
  87. data/lib/action_view/renderer/partial_renderer/collection_caching.rb +102 -0
  88. data/lib/action_view/renderer/partial_renderer.rb +51 -333
  89. data/lib/action_view/renderer/renderer.rb +68 -11
  90. data/lib/action_view/renderer/streaming_template_renderer.rb +60 -56
  91. data/lib/action_view/renderer/template_renderer.rb +87 -74
  92. data/lib/action_view/rendering.rb +73 -47
  93. data/lib/action_view/ripper_ast_parser.rb +198 -0
  94. data/lib/action_view/routing_url_for.rb +35 -24
  95. data/lib/action_view/tasks/cache_digests.rake +25 -0
  96. data/lib/action_view/template/error.rb +151 -41
  97. data/lib/action_view/template/handlers/builder.rb +12 -13
  98. data/lib/action_view/template/handlers/erb/erubi.rb +89 -0
  99. data/lib/action_view/template/handlers/erb.rb +29 -89
  100. data/lib/action_view/template/handlers/html.rb +11 -0
  101. data/lib/action_view/template/handlers/raw.rb +4 -4
  102. data/lib/action_view/template/handlers.rb +14 -10
  103. data/lib/action_view/template/html.rb +12 -13
  104. data/lib/action_view/template/inline.rb +22 -0
  105. data/lib/action_view/template/raw_file.rb +25 -0
  106. data/lib/action_view/template/renderable.rb +24 -0
  107. data/lib/action_view/template/resolver.rb +139 -300
  108. data/lib/action_view/template/sources/file.rb +17 -0
  109. data/lib/action_view/template/sources.rb +13 -0
  110. data/lib/action_view/template/text.rb +10 -12
  111. data/lib/action_view/template/types.rb +28 -26
  112. data/lib/action_view/template.rb +123 -91
  113. data/lib/action_view/template_details.rb +66 -0
  114. data/lib/action_view/template_path.rb +64 -0
  115. data/lib/action_view/test_case.rb +70 -53
  116. data/lib/action_view/testing/resolvers.rb +25 -35
  117. data/lib/action_view/unbound_template.rb +57 -0
  118. data/lib/action_view/version.rb +3 -1
  119. data/lib/action_view/view_paths.rb +73 -58
  120. data/lib/action_view.rb +16 -11
  121. data/lib/assets/compiled/rails-ujs.js +746 -0
  122. metadata +52 -32
  123. data/lib/action_view/helpers/record_tag_helper.rb +0 -108
  124. data/lib/action_view/tasks/dependencies.rake +0 -23
@@ -1,10 +1,12 @@
1
- require 'zlib'
1
+ # frozen_string_literal: true
2
+
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
- # urls.
9
+ # URLs.
8
10
  #
9
11
  # image_path("rails.png")
10
12
  # # => "/assets/rails.png"
@@ -27,41 +29,48 @@ 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
- # # => <link href="http://assets.example.com/assets/application.css" media="screen" rel="stylesheet" />
34
+ # # => <link href="http://assets.example.com/assets/application.css" rel="stylesheet" />
33
35
  #
34
- # Browsers typically open at most two simultaneous connections to a single
35
- # host, which means your assets often have to wait for other assets to finish
36
- # downloading. You can alleviate this by using a <tt>%d</tt> wildcard in the
37
- # +asset_host+. For example, "assets%d.example.com". If that wildcard is
38
- # present Rails distributes asset requests among the corresponding four hosts
39
- # "assets0.example.com", ..., "assets3.example.com". With this trick browsers
40
- # will open eight simultaneous connections rather than two.
36
+ # Browsers open a limited number of simultaneous connections to a single
37
+ # host. The exact number varies by browser and version. This limit may cause
38
+ # some asset downloads to wait for previous assets to finish before they can
39
+ # begin. You can use the <tt>%d</tt> wildcard in the +asset_host+ to
40
+ # distribute the requests over four hosts. For example,
41
+ # <tt>assets%d.example.com</tt> will spread the asset requests over
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
- # # => <link href="http://assets2.example.com/assets/application.css" media="screen" rel="stylesheet" />
47
+ # # => <link href="http://assets2.example.com/assets/application.css" rel="stylesheet" />
48
+ #
49
+ # This may improve the asset loading performance of your application.
50
+ # It is also possible the combination of additional connection overhead
51
+ # (DNS, SSL) and the overall browser connection limits may result in this
52
+ # solution being slower. You should be sure to measure your actual
53
+ # performance across targeted browsers both before and after this change.
46
54
  #
47
- # To do this, you can either setup four actual hosts, or you can use wildcard
48
- # DNS to CNAME the wildcard to a single asset host. You can read more about
49
- # setting up your DNS CNAME records from your ISP.
55
+ # To implement the corresponding hosts you can either set up four actual
56
+ # hosts or use wildcard DNS to CNAME the wildcard to a single asset host.
57
+ # You can read more about setting up your DNS CNAME records from your ISP.
50
58
  #
51
59
  # Note: This is purely a browser performance optimization and is not meant
52
- # for server load balancing. See http://www.die.net/musings/page_load_time/
53
- # for background.
60
+ # for server load balancing. See https://www.die.net/musings/page_load_time/
61
+ # for background and https://www.browserscope.org/?category=network for
62
+ # connection limit data.
54
63
  #
55
64
  # Alternatively, you can exert more control over the asset host by setting
56
65
  # +asset_host+ to a proc like this:
57
66
  #
58
67
  # ActionController::Base.asset_host = Proc.new { |source|
59
- # "http://assets#{Digest::MD5.hexdigest(source).to_i(16) % 2 + 1}.example.com"
68
+ # "http://assets#{OpenSSL::Digest::SHA256.hexdigest(source).to_i(16) % 2 + 1}.example.com"
60
69
  # }
61
70
  # image_tag("rails.png")
62
- # # => <img alt="Rails" src="http://assets1.example.com/assets/rails.png" />
71
+ # # => <img src="http://assets1.example.com/assets/rails.png" />
63
72
  # stylesheet_link_tag("application")
64
- # # => <link href="http://assets2.example.com/assets/application.css" media="screen" rel="stylesheet" />
73
+ # # => <link href="http://assets2.example.com/assets/application.css" rel="stylesheet" />
65
74
  #
66
75
  # The example above generates "http://assets1.example.com" and
67
76
  # "http://assets2.example.com". This option is useful for example if
@@ -71,16 +80,16 @@ module ActionView
71
80
  # absolute path of the asset, for example "/assets/rails.png".
72
81
  #
73
82
  # ActionController::Base.asset_host = Proc.new { |source|
74
- # if source.ends_with?('.css')
83
+ # if source.end_with?('.css')
75
84
  # "http://stylesheets.example.com"
76
85
  # else
77
86
  # "http://assets.example.com"
78
87
  # end
79
88
  # }
80
89
  # image_tag("rails.png")
81
- # # => <img alt="Rails" src="http://assets.example.com/assets/rails.png" />
90
+ # # => <img src="http://assets.example.com/assets/rails.png" />
82
91
  # stylesheet_link_tag("application")
83
- # # => <link href="http://stylesheets.example.com/assets/application.css" media="screen" rel="stylesheet" />
92
+ # # => <link href="http://stylesheets.example.com/assets/application.css" rel="stylesheet" />
84
93
  #
85
94
  # Alternatively you may ask for a second parameter +request+. That one is
86
95
  # particularly useful for serving assets from an SSL-protected page. The
@@ -88,9 +97,10 @@ module ActionView
88
97
  # still sending assets for plain HTTP requests from asset hosts. If you don't
89
98
  # have SSL certificates for each of the asset hosts this technique allows you
90
99
  # to avoid warnings in the client about mixed media.
91
- # Note that the request parameter might not be supplied, e.g. when the assets
92
- # are precompiled via a Rake task. Make sure to use a Proc instead of a lambda,
93
- # since a Proc allows missing parameters and sets them to nil.
100
+ # Note that the +request+ parameter might not be supplied, e.g. when the assets
101
+ # are precompiled with the command <tt>bin/rails assets:precompile</tt>. Make sure to use a
102
+ # +Proc+ instead of a lambda, since a +Proc+ allows missing parameters and sets them
103
+ # to +nil+.
94
104
  #
95
105
  # config.action_controller.asset_host = Proc.new { |source, request|
96
106
  # if request && request.ssl?
@@ -110,34 +120,93 @@ module ActionView
110
120
  module AssetUrlHelper
111
121
  URI_REGEXP = %r{^[-a-z]+://|^(?:cid|data):|^//}i
112
122
 
113
- # Computes the path to asset in public directory. If :type
114
- # options is set, a file extension will be appended and scoped
115
- # to the corresponding public directory.
123
+ # This is the entry point for all assets.
124
+ # When using an asset pipeline gem (e.g. propshaft or sprockets-rails), the
125
+ # behavior is "enhanced". You can bypass the asset pipeline by passing in
126
+ # <tt>skip_pipeline: true</tt> to the options.
116
127
  #
117
128
  # All other asset *_path helpers delegate through this method.
118
129
  #
119
- # asset_path "application.js" # => /assets/application.js
120
- # asset_path "application", type: :javascript # => /assets/application.js
121
- # asset_path "application", type: :stylesheet # => /assets/application.css
122
- # asset_path "http://www.example.com/js/xmlhr.js" # => http://www.example.com/js/xmlhr.js
130
+ # === With the asset pipeline
131
+ #
132
+ # All options passed to +asset_path+ will be passed to +compute_asset_path+
133
+ # which is implemented by asset pipeline gems.
134
+ #
135
+ # asset_path("application.js") # => "/assets/application-60aa4fdc5cea14baf5400fba1abf4f2a46a5166bad4772b1effe341570f07de9.js"
136
+ # asset_path('application.js', host: 'example.com') # => "//example.com/assets/application.js"
137
+ # asset_path("application.js", host: 'example.com', protocol: 'https') # => "https://example.com/assets/application.js"
138
+ #
139
+ # === Without the asset pipeline (<tt>skip_pipeline: true</tt>)
140
+ #
141
+ # Accepts a <tt>type</tt> option that can specify the asset's extension. No error
142
+ # checking is done to verify the source passed into +asset_path+ is valid
143
+ # and that the file exists on disk.
144
+ #
145
+ # asset_path("application.js", skip_pipeline: true) # => "application.js"
146
+ # asset_path("filedoesnotexist.png", skip_pipeline: true) # => "filedoesnotexist.png"
147
+ # asset_path("application", type: :javascript, skip_pipeline: true) # => "/javascripts/application.js"
148
+ # asset_path("application", type: :stylesheet, skip_pipeline: true) # => "/stylesheets/application.css"
149
+ #
150
+ # === Options applying to all assets
151
+ #
152
+ # Below lists scenarios that apply to +asset_path+ whether or not you're
153
+ # using the asset pipeline.
154
+ #
155
+ # - All fully qualified URLs are returned immediately. This bypasses the
156
+ # asset pipeline and all other behavior described.
157
+ #
158
+ # asset_path("http://www.example.com/js/xmlhr.js") # => "http://www.example.com/js/xmlhr.js"
159
+ #
160
+ # - All assets that begin with a forward slash are assumed to be full
161
+ # URLs and will not be expanded. This will bypass the asset pipeline.
162
+ #
163
+ # asset_path("/foo.png") # => "/foo.png"
164
+ #
165
+ # - All blank strings will be returned immediately. This bypasses the
166
+ # asset pipeline and all other behavior described.
167
+ #
168
+ # asset_path("") # => ""
169
+ #
170
+ # - If <tt>config.relative_url_root</tt> is specified, all assets will have that
171
+ # root prepended.
172
+ #
173
+ # Rails.application.config.relative_url_root = "bar"
174
+ # asset_path("foo.js", skip_pipeline: true) # => "bar/foo.js"
175
+ #
176
+ # - A different asset host can be specified via <tt>config.action_controller.asset_host</tt>
177
+ # this is commonly used in conjunction with a CDN.
178
+ #
179
+ # Rails.application.config.action_controller.asset_host = "assets.example.com"
180
+ # asset_path("foo.js", skip_pipeline: true) # => "http://assets.example.com/foo.js"
181
+ #
182
+ # - An extension name can be specified manually with <tt>extname</tt>.
183
+ #
184
+ # asset_path("foo", skip_pipeline: true, extname: ".js") # => "/foo.js"
185
+ # asset_path("foo.css", skip_pipeline: true, extname: ".js") # => "/foo.css.js"
123
186
  def asset_path(source, options = {})
187
+ raise ArgumentError, "nil is not a valid asset source" if source.nil?
188
+
124
189
  source = source.to_s
125
- return "" unless source.present?
126
- return source if source =~ URI_REGEXP
190
+ return "" if source.blank?
191
+ return source if URI_REGEXP.match?(source)
127
192
 
128
- tail, source = source[/([\?#].+)$/], source.sub(/([\?#].+)$/, '')
193
+ tail, source = source[/([?#].+)$/], source.sub(/([?#].+)$/, "")
129
194
 
130
195
  if extname = compute_asset_extname(source, options)
131
196
  source = "#{source}#{extname}"
132
197
  end
133
198
 
134
199
  if source[0] != ?/
135
- source = compute_asset_path(source, options)
200
+ if options[:skip_pipeline]
201
+ source = public_compute_asset_path(source, options)
202
+ else
203
+ source = compute_asset_path(source, options)
204
+ end
136
205
  end
137
206
 
138
207
  relative_url_root = defined?(config.relative_url_root) && config.relative_url_root
139
208
  if relative_url_root
140
- source = File.join(relative_url_root, source) unless source.starts_with?("#{relative_url_root}/")
209
+ source = File.join(relative_url_root, source) unless source.start_with?("#{relative_url_root}/")
141
210
  end
142
211
 
143
212
  if host = compute_asset_host(source, options)
@@ -159,31 +228,35 @@ module ActionView
159
228
  # asset_url "application.js", host: "http://cdn.example.com" # => http://cdn.example.com/assets/application.js
160
229
  #
161
230
  def asset_url(source, options = {})
162
- path_to_asset(source, options.merge(:protocol => :request))
231
+ path_to_asset(source, options.merge(protocol: :request))
163
232
  end
164
233
  alias_method :url_to_asset, :asset_url # aliased to avoid conflicts with an asset_url named route
165
234
 
166
235
  ASSET_EXTENSIONS = {
167
- javascript: '.js',
168
- stylesheet: '.css'
236
+ javascript: ".js",
237
+ stylesheet: ".css"
169
238
  }
170
239
 
171
- # Compute extname to append to asset path. Returns nil if
240
+ # Compute extname to append to asset path. Returns +nil+ if
172
241
  # nothing should be added.
173
242
  def compute_asset_extname(source, options = {})
174
243
  return if options[:extname] == false
175
244
  extname = options[:extname] || ASSET_EXTENSIONS[options[:type]]
176
- extname if extname && File.extname(source) != extname
245
+ if extname && File.extname(source) != extname
246
+ extname
247
+ else
248
+ nil
249
+ end
177
250
  end
178
251
 
179
252
  # Maps asset types to public directory.
180
253
  ASSET_PUBLIC_DIRECTORIES = {
181
- audio: '/audios',
182
- font: '/fonts',
183
- image: '/images',
184
- javascript: '/javascripts',
185
- stylesheet: '/stylesheets',
186
- video: '/videos'
254
+ audio: "/audios",
255
+ font: "/fonts",
256
+ image: "/images",
257
+ javascript: "/javascripts",
258
+ stylesheet: "/stylesheets",
259
+ video: "/videos"
187
260
  }
188
261
 
189
262
  # Computes asset path to public directory. Plugins and
@@ -193,6 +266,7 @@ module ActionView
193
266
  dir = ASSET_PUBLIC_DIRECTORIES[options[:type]] || ""
194
267
  File.join(dir, source)
195
268
  end
269
+ alias :public_compute_asset_path :compute_asset_path
196
270
 
197
271
  # Pick an asset host for this source. Returns +nil+ if no host is set,
198
272
  # the host if no wildcard is set, the host interpolated with the
@@ -204,19 +278,21 @@ module ActionView
204
278
  host = options[:host]
205
279
  host ||= config.asset_host if defined? config.asset_host
206
280
 
207
- if host.respond_to?(:call)
208
- arity = host.respond_to?(:arity) ? host.arity : host.method(:call).arity
209
- args = [source]
210
- args << request if request && (arity > 1 || arity < 0)
211
- host = host.call(*args)
212
- elsif host =~ /%d/
213
- host = host % (Zlib.crc32(source) % 4)
281
+ if host
282
+ if host.respond_to?(:call)
283
+ arity = host.respond_to?(:arity) ? host.arity : host.method(:call).arity
284
+ args = [source]
285
+ args << request if request && (arity > 1 || arity < 0)
286
+ host = host.call(*args)
287
+ elsif host.include?("%d")
288
+ host = host % (Zlib.crc32(source) % 4)
289
+ end
214
290
  end
215
291
 
216
292
  host ||= request.base_url if request && options[:protocol] == :request
217
293
  return unless host
218
294
 
219
- if host =~ URI_REGEXP
295
+ if URI_REGEXP.match?(host)
220
296
  host
221
297
  else
222
298
  protocol = options[:protocol] || config.default_asset_host_protocol || (request ? :request : :relative)
@@ -242,14 +318,19 @@ module ActionView
242
318
  # javascript_path "http://www.example.com/js/xmlhr" # => http://www.example.com/js/xmlhr
243
319
  # javascript_path "http://www.example.com/js/xmlhr.js" # => http://www.example.com/js/xmlhr.js
244
320
  def javascript_path(source, options = {})
245
- path_to_asset(source, {type: :javascript}.merge!(options))
321
+ path_to_asset(source, { type: :javascript }.merge!(options))
246
322
  end
247
323
  alias_method :path_to_javascript, :javascript_path # aliased to avoid conflicts with a javascript_path named route
248
324
 
249
325
  # Computes the full URL to a JavaScript asset in the public javascripts directory.
250
326
  # This will use +javascript_path+ internally, so most of their behaviors will be the same.
327
+ # Since +javascript_url+ is based on +asset_url+ method you can set :host options. If :host
328
+ # options is set, it overwrites global +config.action_controller.asset_host+ setting.
329
+ #
330
+ # javascript_url "js/xmlhr.js", host: "http://stage.example.com" # => http://stage.example.com/assets/js/xmlhr.js
331
+ #
251
332
  def javascript_url(source, options = {})
252
- url_to_asset(source, {type: :javascript}.merge!(options))
333
+ url_to_asset(source, { type: :javascript }.merge!(options))
253
334
  end
254
335
  alias_method :url_to_javascript, :javascript_url # aliased to avoid conflicts with a javascript_url named route
255
336
 
@@ -264,14 +345,19 @@ module ActionView
264
345
  # stylesheet_path "http://www.example.com/css/style" # => http://www.example.com/css/style
265
346
  # stylesheet_path "http://www.example.com/css/style.css" # => http://www.example.com/css/style.css
266
347
  def stylesheet_path(source, options = {})
267
- path_to_asset(source, {type: :stylesheet}.merge!(options))
348
+ path_to_asset(source, { type: :stylesheet }.merge!(options))
268
349
  end
269
350
  alias_method :path_to_stylesheet, :stylesheet_path # aliased to avoid conflicts with a stylesheet_path named route
270
351
 
271
352
  # Computes the full URL to a stylesheet asset in the public stylesheets directory.
272
353
  # This will use +stylesheet_path+ internally, so most of their behaviors will be the same.
354
+ # Since +stylesheet_url+ is based on +asset_url+ method you can set :host options. If :host
355
+ # options is set, it overwrites global +config.action_controller.asset_host+ setting.
356
+ #
357
+ # stylesheet_url "css/style.css", host: "http://stage.example.com" # => http://stage.example.com/assets/css/style.css
358
+ #
273
359
  def stylesheet_url(source, options = {})
274
- url_to_asset(source, {type: :stylesheet}.merge!(options))
360
+ url_to_asset(source, { type: :stylesheet }.merge!(options))
275
361
  end
276
362
  alias_method :url_to_stylesheet, :stylesheet_url # aliased to avoid conflicts with a stylesheet_url named route
277
363
 
@@ -289,14 +375,19 @@ module ActionView
289
375
  # The alias +path_to_image+ is provided to avoid that. Rails uses the alias internally, and
290
376
  # plugin authors are encouraged to do so.
291
377
  def image_path(source, options = {})
292
- path_to_asset(source, {type: :image}.merge!(options))
378
+ path_to_asset(source, { type: :image }.merge!(options))
293
379
  end
294
380
  alias_method :path_to_image, :image_path # aliased to avoid conflicts with an image_path named route
295
381
 
296
382
  # Computes the full URL to an image asset.
297
383
  # This will use +image_path+ internally, so most of their behaviors will be the same.
384
+ # Since +image_url+ is based on +asset_url+ method you can set :host options. If :host
385
+ # options is set, it overwrites global +config.action_controller.asset_host+ setting.
386
+ #
387
+ # image_url "edit.png", host: "http://stage.example.com" # => http://stage.example.com/assets/edit.png
388
+ #
298
389
  def image_url(source, options = {})
299
- url_to_asset(source, {type: :image}.merge!(options))
390
+ url_to_asset(source, { type: :image }.merge!(options))
300
391
  end
301
392
  alias_method :url_to_image, :image_url # aliased to avoid conflicts with an image_url named route
302
393
 
@@ -310,16 +401,21 @@ module ActionView
310
401
  # video_path("/trailers/hd.avi") # => /trailers/hd.avi
311
402
  # video_path("http://www.example.com/vid/hd.avi") # => http://www.example.com/vid/hd.avi
312
403
  def video_path(source, options = {})
313
- path_to_asset(source, {type: :video}.merge!(options))
404
+ path_to_asset(source, { type: :video }.merge!(options))
314
405
  end
315
406
  alias_method :path_to_video, :video_path # aliased to avoid conflicts with a video_path named route
316
407
 
317
408
  # Computes the full URL to a video asset in the public videos directory.
318
409
  # This will use +video_path+ internally, so most of their behaviors will be the same.
410
+ # Since +video_url+ is based on +asset_url+ method you can set :host options. If :host
411
+ # options is set, it overwrites global +config.action_controller.asset_host+ setting.
412
+ #
413
+ # video_url "hd.avi", host: "http://stage.example.com" # => http://stage.example.com/videos/hd.avi
414
+ #
319
415
  def video_url(source, options = {})
320
- url_to_asset(source, {type: :video}.merge!(options))
416
+ url_to_asset(source, { type: :video }.merge!(options))
321
417
  end
322
- alias_method :url_to_video, :video_url # aliased to avoid conflicts with an video_url named route
418
+ alias_method :url_to_video, :video_url # aliased to avoid conflicts with a video_url named route
323
419
 
324
420
  # Computes the path to an audio asset in the public audios directory.
325
421
  # Full paths from the document root will be passed through.
@@ -331,14 +427,19 @@ module ActionView
331
427
  # audio_path("/sounds/horse.wav") # => /sounds/horse.wav
332
428
  # audio_path("http://www.example.com/sounds/horse.wav") # => http://www.example.com/sounds/horse.wav
333
429
  def audio_path(source, options = {})
334
- path_to_asset(source, {type: :audio}.merge!(options))
430
+ path_to_asset(source, { type: :audio }.merge!(options))
335
431
  end
336
432
  alias_method :path_to_audio, :audio_path # aliased to avoid conflicts with an audio_path named route
337
433
 
338
434
  # Computes the full URL to an audio asset in the public audios directory.
339
435
  # This will use +audio_path+ internally, so most of their behaviors will be the same.
436
+ # Since +audio_url+ is based on +asset_url+ method you can set :host options. If :host
437
+ # options is set, it overwrites global +config.action_controller.asset_host+ setting.
438
+ #
439
+ # audio_url "horse.wav", host: "http://stage.example.com" # => http://stage.example.com/audios/horse.wav
440
+ #
340
441
  def audio_url(source, options = {})
341
- url_to_asset(source, {type: :audio}.merge!(options))
442
+ url_to_asset(source, { type: :audio }.merge!(options))
342
443
  end
343
444
  alias_method :url_to_audio, :audio_url # aliased to avoid conflicts with an audio_url named route
344
445
 
@@ -351,16 +452,21 @@ module ActionView
351
452
  # font_path("/dir/font.ttf") # => /dir/font.ttf
352
453
  # font_path("http://www.example.com/dir/font.ttf") # => http://www.example.com/dir/font.ttf
353
454
  def font_path(source, options = {})
354
- path_to_asset(source, {type: :font}.merge!(options))
455
+ path_to_asset(source, { type: :font }.merge!(options))
355
456
  end
356
- alias_method :path_to_font, :font_path # aliased to avoid conflicts with an font_path named route
457
+ alias_method :path_to_font, :font_path # aliased to avoid conflicts with a font_path named route
357
458
 
358
459
  # Computes the full URL to a font asset.
359
460
  # This will use +font_path+ internally, so most of their behaviors will be the same.
461
+ # Since +font_url+ is based on +asset_url+ method you can set :host options. If :host
462
+ # options is set, it overwrites global +config.action_controller.asset_host+ setting.
463
+ #
464
+ # font_url "font.ttf", host: "http://stage.example.com" # => http://stage.example.com/fonts/font.ttf
465
+ #
360
466
  def font_url(source, options = {})
361
- url_to_asset(source, {type: :font}.merge!(options))
467
+ url_to_asset(source, { type: :font }.merge!(options))
362
468
  end
363
- alias_method :url_to_font, :font_url # aliased to avoid conflicts with an font_url named route
469
+ alias_method :url_to_font, :font_url # aliased to avoid conflicts with a font_url named route
364
470
  end
365
471
  end
366
472
  end
@@ -1,8 +1,10 @@
1
- require 'set'
1
+ # frozen_string_literal: true
2
+
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).
@@ -16,7 +18,7 @@ module ActionView
16
18
  # end
17
19
  #
18
20
  # app/controllers/posts_controller.rb:
19
- # class PostsController < ApplicationController::Base
21
+ # class PostsController < ApplicationController
20
22
  # # GET /posts.html
21
23
  # # GET /posts.atom
22
24
  # def index
@@ -51,7 +53,7 @@ module ActionView
51
53
  # * <tt>:language</tt>: Defaults to "en-US".
52
54
  # * <tt>:root_url</tt>: The HTML alternative that this feed is doubling for. Defaults to / on the current host.
53
55
  # * <tt>:url</tt>: The URL for this feed. Defaults to the current URL.
54
- # * <tt>:id</tt>: The id for this feed. Defaults to "tag:#{request.host},#{options[:schema_date]}:#{request.fullpath.split(".")[0]}"
56
+ # * <tt>:id</tt>: The id for this feed. Defaults to "tag:localhost,2005:/posts", in this case.
55
57
  # * <tt>:schema_date</tt>: The date at which the tag scheme for the feed was first used. A good default is the year you
56
58
  # created the feed. See http://feedvalidator.org/docs/error/InvalidTAG.html for more information. If not specified,
57
59
  # 2005 is used (as an "I don't care" value).
@@ -103,7 +105,7 @@ module ActionView
103
105
  xml = options.delete(:xml) || eval("xml", block.binding)
104
106
  xml.instruct!
105
107
  if options[:instruct]
106
- options[:instruct].each do |target,attrs|
108
+ options[:instruct].each do |target, attrs|
107
109
  if attrs.respond_to?(:keys)
108
110
  xml.instruct!(target, attrs)
109
111
  elsif attrs.respond_to?(:each)
@@ -112,19 +114,19 @@ module ActionView
112
114
  end
113
115
  end
114
116
 
115
- feed_opts = {"xml:lang" => options[:language] || "en-US", "xmlns" => 'http://www.w3.org/2005/Atom'}
116
- feed_opts.merge!(options).reject!{|k,v| !k.to_s.match(/^xml/)}
117
+ feed_opts = { "xml:lang" => options[:language] || "en-US", "xmlns" => "http://www.w3.org/2005/Atom" }
118
+ feed_opts.merge!(options).select! { |k, _| k.start_with?("xml") }
117
119
 
118
120
  xml.feed(feed_opts) do
119
121
  xml.id(options[:id] || "tag:#{request.host},#{options[:schema_date]}:#{request.fullpath.split(".")[0]}")
120
- xml.link(:rel => 'alternate', :type => 'text/html', :href => options[:root_url] || (request.protocol + request.host_with_port))
121
- xml.link(:rel => 'self', :type => 'application/atom+xml', :href => options[:url] || request.url)
122
+ xml.link(rel: "alternate", type: "text/html", href: options[:root_url] || (request.protocol + request.host_with_port))
123
+ xml.link(rel: "self", type: "application/atom+xml", href: options[:url] || request.url)
122
124
 
123
125
  yield AtomFeedBuilder.new(xml, self, options)
124
126
  end
125
127
  end
126
128
 
127
- class AtomBuilder #:nodoc:
129
+ class AtomBuilder # :nodoc:
128
130
  XHTML_TAG_NAMES = %w(content rights title subtitle summary).to_set
129
131
 
130
132
  def initialize(xml)
@@ -132,13 +134,13 @@ module ActionView
132
134
  end
133
135
 
134
136
  private
135
- # Delegate to xml builder, first wrapping the element in a xhtml
137
+ # Delegate to xml builder, first wrapping the element in an xhtml
136
138
  # namespaced div element if the method and arguments indicate
137
139
  # that an xhtml_block? is desired.
138
140
  def method_missing(method, *arguments, &block)
139
141
  if xhtml_block?(method, arguments)
140
142
  @xml.__send__(method, *arguments) do
141
- @xml.div(:xmlns => 'http://www.w3.org/1999/xhtml') do |xhtml|
143
+ @xml.div(xmlns: "http://www.w3.org/1999/xhtml") do |xhtml|
142
144
  block.call(xhtml)
143
145
  end
144
146
  end
@@ -153,17 +155,17 @@ module ActionView
153
155
  def xhtml_block?(method, arguments)
154
156
  if XHTML_TAG_NAMES.include?(method.to_s)
155
157
  last = arguments.last
156
- last.is_a?(Hash) && last[:type].to_s == 'xhtml'
158
+ last.is_a?(Hash) && last[:type].to_s == "xhtml"
157
159
  end
158
160
  end
159
161
  end
160
162
 
161
- class AtomFeedBuilder < AtomBuilder #:nodoc:
163
+ class AtomFeedBuilder < AtomBuilder # :nodoc:
162
164
  def initialize(xml, view, feed_options = {})
163
165
  @xml, @view, @feed_options = xml, view, feed_options
164
166
  end
165
167
 
166
- # Accepts a Date or Time object and inserts it in the proper format. If nil is passed, current time in UTC is used.
168
+ # Accepts a Date or Time object and inserts it in the proper format. If +nil+ is passed, current time in UTC is used.
167
169
  def updated(date_or_time = nil)
168
170
  @xml.updated((date_or_time || Time.now.utc).xmlschema)
169
171
  end
@@ -174,7 +176,7 @@ module ActionView
174
176
  #
175
177
  # * <tt>:published</tt>: Time first published. Defaults to the created_at attribute on the record if one such exists.
176
178
  # * <tt>:updated</tt>: Time of update. Defaults to the updated_at attribute on the record if one such exists.
177
- # * <tt>:url</tt>: The URL for this entry. Defaults to the polymorphic_url for the record.
179
+ # * <tt>:url</tt>: The URL for this entry or +false+ or +nil+ for not having a link tag. Defaults to the +polymorphic_url+ for the record.
178
180
  # * <tt>:id</tt>: The ID for this entry. Defaults to "tag:#{@view.request.host},#{@feed_options[:schema_date]}:#{record.class}/#{record.id}"
179
181
  # * <tt>:type</tt>: The TYPE for this entry. Defaults to "text/html".
180
182
  def entry(record, options = {})
@@ -189,15 +191,15 @@ module ActionView
189
191
  @xml.updated((options[:updated] || record.updated_at).xmlschema)
190
192
  end
191
193
 
192
- type = options.fetch(:type, 'text/html')
194
+ type = options.fetch(:type, "text/html")
193
195
 
194
- @xml.link(:rel => 'alternate', :type => type, :href => options[:url] || @view.polymorphic_url(record))
196
+ url = options.fetch(:url) { @view.polymorphic_url(record) }
197
+ @xml.link(rel: "alternate", type: type, href: url) if url
195
198
 
196
199
  yield AtomBuilder.new(@xml)
197
200
  end
198
201
  end
199
202
  end
200
-
201
203
  end
202
204
  end
203
205
  end