actionview 6.0.0.beta3 → 6.0.0.rc1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +40 -4
- data/README.rdoc +3 -1
- data/lib/action_view.rb +2 -1
- data/lib/action_view/base.rb +4 -4
- data/lib/action_view/cache_expiry.rb +49 -0
- data/lib/action_view/digestor.rb +0 -6
- data/lib/action_view/gem_version.rb +1 -1
- data/lib/action_view/helpers/form_helper.rb +2 -2
- data/lib/action_view/helpers/form_tag_helper.rb +1 -1
- data/lib/action_view/helpers/output_safety_helper.rb +1 -1
- data/lib/action_view/helpers/tags/base.rb +1 -1
- data/lib/action_view/helpers/translation_helper.rb +2 -2
- data/lib/action_view/helpers/url_helper.rb +1 -1
- data/lib/action_view/lookup_context.rb +11 -4
- data/lib/action_view/path_set.rb +5 -10
- data/lib/action_view/railtie.rb +1 -1
- data/lib/action_view/renderer/partial_renderer/collection_caching.rb +20 -13
- data/lib/action_view/renderer/streaming_template_renderer.rb +1 -1
- data/lib/action_view/renderer/template_renderer.rb +9 -3
- data/lib/action_view/rendering.rb +3 -2
- data/lib/action_view/template.rb +43 -50
- data/lib/action_view/template/error.rb +21 -1
- data/lib/action_view/template/handlers.rb +3 -3
- data/lib/action_view/template/handlers/erb/erubi.rb +2 -2
- data/lib/action_view/template/raw_file.rb +28 -0
- data/lib/action_view/template/resolver.rb +73 -117
- data/lib/action_view/template/sources.rb +13 -0
- data/lib/action_view/template/sources/file.rb +17 -0
- data/lib/action_view/testing/resolvers.rb +9 -10
- data/lib/action_view/unbound_template.rb +32 -0
- data/lib/assets/compiled/rails-ujs.js +14 -8
- metadata +16 -12
- data/lib/action_view/file_template.rb +0 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d46b0e667c524b53bbcfd7291119c3078c1bcef2f379077610f11efa75cb7bcd
|
4
|
+
data.tar.gz: 3952ce8b418d28245b3ba4a0126435958facc728363abd50deb0e6b110556b65
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dfc23eddf6eeb31093fa017f53ebc46c5a115d1d0edbc3ab40747eb243d4516e99c74d5c6d497bcb9731a62ab224ecde5f62352b50f57ab384a9595ac6d2ae53
|
7
|
+
data.tar.gz: d8abfa6ea6c991820b67fb389c629f6b49d09610c1d0821e009084e475649b6aef7a861c620960ef58b9efa0d4a0709b9606690f6b19557910c0fd3946130f5f
|
data/CHANGELOG.md
CHANGED
@@ -1,22 +1,58 @@
|
|
1
|
+
## Rails 6.0.0.rc1 (April 24, 2019) ##
|
2
|
+
|
3
|
+
* Fix partial caching skips same item issue
|
4
|
+
|
5
|
+
If we render cached collection partials with repeated items, those repeated items
|
6
|
+
will get skipped. For example, if you have 5 identical items in your collection, Rails
|
7
|
+
only renders the first one when `cached` is set to true. But it should render all
|
8
|
+
5 items instead.
|
9
|
+
|
10
|
+
Fixes #35114.
|
11
|
+
|
12
|
+
*Stan Lo*
|
13
|
+
|
14
|
+
* Only clear ActionView cache in development on file changes
|
15
|
+
|
16
|
+
To speed up development mode, view caches are only cleared when files in
|
17
|
+
the view paths have changed. Applications which have implemented custom
|
18
|
+
`ActionView::Resolver` subclasses may need to add their own cache clearing.
|
19
|
+
|
20
|
+
*John Hawthorn*
|
21
|
+
|
22
|
+
* Fix `ActionView::FixtureResolver` so that it handles template variants correctly.
|
23
|
+
|
24
|
+
*Edward Rudd*
|
25
|
+
|
26
|
+
|
1
27
|
## Rails 6.0.0.beta3 (March 11, 2019) ##
|
2
28
|
|
3
|
-
*
|
29
|
+
* Only accept formats from registered mime types
|
30
|
+
|
31
|
+
A lack of filtering on mime types could allow an attacker to read
|
32
|
+
arbitrary files on the target server or to perform a denial of service
|
33
|
+
attack.
|
34
|
+
|
35
|
+
Fixes CVE-2019-5418
|
36
|
+
Fixes CVE-2019-5419
|
37
|
+
|
38
|
+
*John Hawthorn*, *Eileen M. Uchitelle*, *Aaron Patterson*
|
4
39
|
|
5
40
|
|
6
41
|
## Rails 6.0.0.beta2 (February 25, 2019) ##
|
7
42
|
|
8
|
-
* ActionView::Template.finalize_compiled_template_methods is deprecated with
|
43
|
+
* `ActionView::Template.finalize_compiled_template_methods` is deprecated with
|
9
44
|
no replacement.
|
10
45
|
|
11
46
|
*tenderlove*
|
12
47
|
|
13
|
-
* config.action_view.finalize_compiled_template_methods is deprecated with
|
48
|
+
* `config.action_view.finalize_compiled_template_methods` is deprecated with
|
14
49
|
no replacement.
|
15
50
|
|
16
51
|
*tenderlove*
|
17
52
|
|
18
53
|
* Ensure unique DOM IDs for collection inputs with float values.
|
19
|
-
|
54
|
+
|
55
|
+
Fixes #34974.
|
20
56
|
|
21
57
|
*Mark Edmondson*
|
22
58
|
|
data/README.rdoc
CHANGED
@@ -5,6 +5,8 @@ view helpers that assist when building HTML forms, Atom feeds and more.
|
|
5
5
|
Template formats that Action View handles are ERB (embedded Ruby, typically
|
6
6
|
used to inline short Ruby snippets inside HTML), and XML Builder.
|
7
7
|
|
8
|
+
You can read more about Action View in the {Action View Overview}[https://edgeguides.rubyonrails.org/action_view_overview.html] guide.
|
9
|
+
|
8
10
|
== Download and installation
|
9
11
|
|
10
12
|
The latest version of Action View can be installed with RubyGems:
|
@@ -27,7 +29,7 @@ Action View is released under the MIT license:
|
|
27
29
|
|
28
30
|
API documentation is at
|
29
31
|
|
30
|
-
*
|
32
|
+
* https://api.rubyonrails.org
|
31
33
|
|
32
34
|
Bug reports for the Ruby on Rails project can be filed here:
|
33
35
|
|
data/lib/action_view.rb
CHANGED
@@ -44,7 +44,7 @@ module ActionView
|
|
44
44
|
autoload :Rendering
|
45
45
|
autoload :RoutingUrlFor
|
46
46
|
autoload :Template
|
47
|
-
autoload :
|
47
|
+
autoload :UnboundTemplate
|
48
48
|
autoload :ViewPaths
|
49
49
|
|
50
50
|
autoload_under "renderer" do
|
@@ -81,6 +81,7 @@ module ActionView
|
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
84
|
+
autoload :CacheExpiry
|
84
85
|
autoload :TestCase
|
85
86
|
|
86
87
|
def self.eager_load!
|
data/lib/action_view/base.rb
CHANGED
@@ -242,7 +242,7 @@ module ActionView #:nodoc:
|
|
242
242
|
@_config = ActiveSupport::InheritableOptions.new
|
243
243
|
|
244
244
|
unless formats == NULL
|
245
|
-
ActiveSupport::Deprecation.warn <<~eowarn
|
245
|
+
ActiveSupport::Deprecation.warn <<~eowarn.squish
|
246
246
|
Passing formats to ActionView::Base.new is deprecated
|
247
247
|
eowarn
|
248
248
|
end
|
@@ -251,7 +251,7 @@ module ActionView #:nodoc:
|
|
251
251
|
when ActionView::LookupContext
|
252
252
|
@lookup_context = lookup_context
|
253
253
|
else
|
254
|
-
ActiveSupport::Deprecation.warn <<~eowarn
|
254
|
+
ActiveSupport::Deprecation.warn <<~eowarn.squish
|
255
255
|
ActionView::Base instances should be constructed with a lookup context,
|
256
256
|
assignments, and a controller.
|
257
257
|
eowarn
|
@@ -267,7 +267,7 @@ module ActionView #:nodoc:
|
|
267
267
|
_prepare_context
|
268
268
|
end
|
269
269
|
|
270
|
-
def
|
270
|
+
def _run(method, template, locals, buffer, &block)
|
271
271
|
_old_output_buffer, _old_virtual_path, _old_template = @output_buffer, @virtual_path, @current_template
|
272
272
|
@current_template = template
|
273
273
|
@output_buffer = buffer
|
@@ -278,7 +278,7 @@ module ActionView #:nodoc:
|
|
278
278
|
|
279
279
|
def compiled_method_container
|
280
280
|
if self.class == ActionView::Base
|
281
|
-
ActiveSupport::Deprecation.warn <<~eowarn
|
281
|
+
ActiveSupport::Deprecation.warn <<~eowarn.squish
|
282
282
|
ActionView::Base instances must implement `compiled_method_container`
|
283
283
|
or use the class method `with_empty_template_cache` for constructing
|
284
284
|
an ActionView::Base instances that has an empty cache.
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionView
|
4
|
+
class CacheExpiry
|
5
|
+
class Executor
|
6
|
+
def initialize(watcher:)
|
7
|
+
@cache_expiry = CacheExpiry.new(watcher: watcher)
|
8
|
+
end
|
9
|
+
|
10
|
+
def before(target)
|
11
|
+
@cache_expiry.clear_cache_if_necessary
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(watcher:)
|
16
|
+
@watched_dirs = nil
|
17
|
+
@watcher_class = watcher
|
18
|
+
@watcher = nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def clear_cache_if_necessary
|
22
|
+
watched_dirs = dirs_to_watch
|
23
|
+
if watched_dirs != @watched_dirs
|
24
|
+
@watched_dirs = watched_dirs
|
25
|
+
@watcher = @watcher_class.new([], watched_dirs) do
|
26
|
+
clear_cache
|
27
|
+
end
|
28
|
+
@watcher.execute
|
29
|
+
else
|
30
|
+
@watcher.execute_if_updated
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def clear_cache
|
35
|
+
ActionView::LookupContext::DetailsKey.clear
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def dirs_to_watch
|
41
|
+
fs_paths = all_view_paths.grep(FileSystemResolver)
|
42
|
+
fs_paths.map(&:path).sort.uniq
|
43
|
+
end
|
44
|
+
|
45
|
+
def all_view_paths
|
46
|
+
ActionView::ViewPaths.all_view_paths.flat_map(&:paths)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/action_view/digestor.rb
CHANGED
@@ -739,7 +739,7 @@ module ActionView
|
|
739
739
|
# def labelled_form_with(**options, &block)
|
740
740
|
# form_with(**options.merge(builder: LabellingFormBuilder), &block)
|
741
741
|
# end
|
742
|
-
def form_with(model: nil, scope: nil, url: nil, format: nil, **options)
|
742
|
+
def form_with(model: nil, scope: nil, url: nil, format: nil, **options, &block)
|
743
743
|
options[:allow_method_names_outside_object] = true
|
744
744
|
options[:skip_default_ids] = !form_with_generates_ids
|
745
745
|
|
@@ -752,7 +752,7 @@ module ActionView
|
|
752
752
|
|
753
753
|
if block_given?
|
754
754
|
builder = instantiate_builder(scope, model, options)
|
755
|
-
output = capture(builder, &
|
755
|
+
output = capture(builder, &block)
|
756
756
|
options[:multipart] ||= builder.multipart?
|
757
757
|
|
758
758
|
html_options = html_options_for_form_with(url, model, options)
|
@@ -24,7 +24,7 @@ module ActionView
|
|
24
24
|
|
25
25
|
mattr_accessor :default_enforce_utf8, default: true
|
26
26
|
|
27
|
-
# Starts a form tag that points the action to a
|
27
|
+
# Starts a form tag that points the action to a URL configured with <tt>url_for_options</tt> just like
|
28
28
|
# ActionController::Base#url_for. The method for the form defaults to POST.
|
29
29
|
#
|
30
30
|
# ==== Options
|
@@ -38,7 +38,7 @@ module ActionView #:nodoc:
|
|
38
38
|
|
39
39
|
# Converts the array to a comma-separated sentence where the last element is
|
40
40
|
# joined by the connector word. This is the html_safe-aware version of
|
41
|
-
# ActiveSupport's {Array#to_sentence}[
|
41
|
+
# ActiveSupport's {Array#to_sentence}[https://api.rubyonrails.org/classes/Array.html#method-i-to_sentence].
|
42
42
|
#
|
43
43
|
def to_sentence(array, options = {})
|
44
44
|
options.assert_valid_keys(:words_connector, :two_words_connector, :last_word_connector, :locale)
|
@@ -138,7 +138,7 @@ module ActionView
|
|
138
138
|
end
|
139
139
|
|
140
140
|
def sanitized_value(value)
|
141
|
-
value.to_s.gsub(/[\s\.]/, "_").gsub(/[^-[[:word:]]]/, "").
|
141
|
+
value.to_s.gsub(/[\s\.]/, "_").gsub(/[^-[[:word:]]]/, "").downcase
|
142
142
|
end
|
143
143
|
|
144
144
|
def select_content_tag(option_tags, options, html_options)
|
@@ -114,7 +114,7 @@ module ActionView
|
|
114
114
|
|
115
115
|
# Delegates to <tt>I18n.localize</tt> with no additional functionality.
|
116
116
|
#
|
117
|
-
# See
|
117
|
+
# See https://www.rubydoc.info/github/svenfuchs/i18n/master/I18n/Backend/Base:localize
|
118
118
|
# for more information.
|
119
119
|
def localize(*args)
|
120
120
|
I18n.localize(*args)
|
@@ -138,7 +138,7 @@ module ActionView
|
|
138
138
|
end
|
139
139
|
|
140
140
|
def html_safe_translation_key?(key)
|
141
|
-
/(
|
141
|
+
/(?:_|\b)html\z/.match?(key.to_s)
|
142
142
|
end
|
143
143
|
end
|
144
144
|
end
|
@@ -553,7 +553,7 @@ module ActionView
|
|
553
553
|
url_string = URI.parser.unescape(url_for(options)).force_encoding(Encoding::BINARY)
|
554
554
|
|
555
555
|
# We ignore any extra parameters in the request_uri if the
|
556
|
-
# submitted
|
556
|
+
# submitted URL doesn't have any either. This lets the function
|
557
557
|
# work with things like ?order=asc
|
558
558
|
# the behaviour can be disabled with check_parameters: true
|
559
559
|
request_uri = url_string.index("?") || check_parameters ? request.fullpath : request.path
|
@@ -130,9 +130,8 @@ module ActionView
|
|
130
130
|
end
|
131
131
|
alias :find_template :find
|
132
132
|
|
133
|
-
|
134
|
-
|
135
|
-
end
|
133
|
+
alias :find_file :find
|
134
|
+
deprecate :find_file
|
136
135
|
|
137
136
|
def find_all(name, prefixes = [], partial = false, keys = [], options = {})
|
138
137
|
@view_paths.find_all(*args_for_lookup(name, prefixes, partial, keys, options))
|
@@ -154,7 +153,7 @@ module ActionView
|
|
154
153
|
view_paths = build_view_paths((@view_paths.paths + self.class.fallbacks).uniq)
|
155
154
|
|
156
155
|
if block_given?
|
157
|
-
ActiveSupport::Deprecation.warn <<~eowarn
|
156
|
+
ActiveSupport::Deprecation.warn <<~eowarn.squish
|
158
157
|
Calling `with_fallbacks` with a block is deprecated. Call methods on
|
159
158
|
the lookup context returned by `with_fallbacks` instead.
|
160
159
|
eowarn
|
@@ -280,7 +279,15 @@ module ActionView
|
|
280
279
|
# add :html as fallback to :js.
|
281
280
|
def formats=(values)
|
282
281
|
if values
|
282
|
+
values = values.dup
|
283
283
|
values.concat(default_formats) if values.delete "*/*"
|
284
|
+
values.uniq!
|
285
|
+
|
286
|
+
invalid_values = (values - Template::Types.symbols)
|
287
|
+
unless invalid_values.empty?
|
288
|
+
raise ArgumentError, "Invalid formats: #{invalid_values.map(&:inspect).join(", ")}"
|
289
|
+
end
|
290
|
+
|
284
291
|
if values == [:js]
|
285
292
|
values << :html
|
286
293
|
@html_fallback_for_js = true
|
data/lib/action_view/path_set.rb
CHANGED
@@ -48,12 +48,11 @@ module ActionView #:nodoc:
|
|
48
48
|
find_all(*args).first || raise(MissingTemplate.new(self, *args))
|
49
49
|
end
|
50
50
|
|
51
|
-
|
52
|
-
|
53
|
-
end
|
51
|
+
alias :find_file :find
|
52
|
+
deprecate :find_file
|
54
53
|
|
55
54
|
def find_all(path, prefixes = [], *args)
|
56
|
-
_find_all path, prefixes, args
|
55
|
+
_find_all path, prefixes, args
|
57
56
|
end
|
58
57
|
|
59
58
|
def exists?(path, prefixes, *args)
|
@@ -71,15 +70,11 @@ module ActionView #:nodoc:
|
|
71
70
|
|
72
71
|
private
|
73
72
|
|
74
|
-
def _find_all(path, prefixes, args
|
73
|
+
def _find_all(path, prefixes, args)
|
75
74
|
prefixes = [prefixes] if String === prefixes
|
76
75
|
prefixes.each do |prefix|
|
77
76
|
paths.each do |resolver|
|
78
|
-
|
79
|
-
templates = resolver.find_all_anywhere(path, prefix, *args)
|
80
|
-
else
|
81
|
-
templates = resolver.find_all(path, prefix, *args)
|
82
|
-
end
|
77
|
+
templates = resolver.find_all(path, prefix, *args)
|
83
78
|
return templates unless templates.empty?
|
84
79
|
end
|
85
80
|
end
|
data/lib/action_view/railtie.rb
CHANGED
@@ -81,7 +81,7 @@ module ActionView
|
|
81
81
|
initializer "action_view.per_request_digest_cache" do |app|
|
82
82
|
ActiveSupport.on_load(:action_view) do
|
83
83
|
unless ActionView::Resolver.caching?
|
84
|
-
app.executor.to_run ActionView::
|
84
|
+
app.executor.to_run ActionView::CacheExpiry::Executor.new(watcher: app.config.file_watcher)
|
85
85
|
end
|
86
86
|
end
|
87
87
|
end
|
@@ -17,13 +17,13 @@ module ActionView
|
|
17
17
|
# Result is a hash with the key represents the
|
18
18
|
# key used for cache lookup and the value is the item
|
19
19
|
# on which the partial is being rendered
|
20
|
-
keyed_collection = collection_by_cache_keys(view, template)
|
20
|
+
keyed_collection, ordered_keys = collection_by_cache_keys(view, template)
|
21
21
|
|
22
22
|
# Pull all partials from cache
|
23
23
|
# Result is a hash, key matches the entry in
|
24
24
|
# `keyed_collection` where the cache was retrieved and the
|
25
25
|
# value is the value that was present in the cache
|
26
|
-
cached_partials
|
26
|
+
cached_partials = collection_cache.read_multi(*keyed_collection.keys)
|
27
27
|
instrumentation_payload[:cache_hits] = cached_partials.size
|
28
28
|
|
29
29
|
# Extract the items for the keys that are not found
|
@@ -40,11 +40,15 @@ module ActionView
|
|
40
40
|
rendered_partials = @collection.empty? ? [] : yield
|
41
41
|
|
42
42
|
index = 0
|
43
|
-
fetch_or_cache_partial(cached_partials, template, order_by: keyed_collection.each_key) do
|
43
|
+
keyed_partials = fetch_or_cache_partial(cached_partials, template, order_by: keyed_collection.each_key) do
|
44
44
|
# This block is called once
|
45
45
|
# for every cache miss while preserving order.
|
46
46
|
rendered_partials[index].tap { index += 1 }
|
47
47
|
end
|
48
|
+
|
49
|
+
ordered_keys.map do |key|
|
50
|
+
keyed_partials[key]
|
51
|
+
end
|
48
52
|
end
|
49
53
|
|
50
54
|
def callable_cache_key?
|
@@ -56,8 +60,10 @@ module ActionView
|
|
56
60
|
|
57
61
|
digest_path = view.digest_path_from_template(template)
|
58
62
|
|
59
|
-
@collection.each_with_object({}) do |item, hash|
|
60
|
-
|
63
|
+
@collection.each_with_object([{}, []]) do |item, (hash, ordered_keys)|
|
64
|
+
key = expanded_cache_key(seed.call(item), view, template, digest_path)
|
65
|
+
ordered_keys << key
|
66
|
+
hash[key] = item
|
61
67
|
end
|
62
68
|
end
|
63
69
|
|
@@ -82,15 +88,16 @@ module ActionView
|
|
82
88
|
# If the partial is not already cached it will also be
|
83
89
|
# written back to the underlying cache store.
|
84
90
|
def fetch_or_cache_partial(cached_partials, template, order_by:)
|
85
|
-
order_by.
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
91
|
+
order_by.each_with_object({}) do |cache_key, hash|
|
92
|
+
hash[cache_key] =
|
93
|
+
if content = cached_partials[cache_key]
|
94
|
+
build_rendered_template(content, template)
|
95
|
+
else
|
96
|
+
yield.tap do |rendered_partial|
|
97
|
+
collection_cache.write(cache_key, rendered_partial.body)
|
98
|
+
end
|
99
|
+
end
|
92
100
|
end
|
93
|
-
end
|
94
101
|
end
|
95
102
|
end
|
96
103
|
end
|