actionview 5.0.0.beta3 → 5.0.0.beta4
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 +35 -1
- data/lib/action_view/digestor.rb +70 -77
- data/lib/action_view/flows.rb +4 -5
- data/lib/action_view/gem_version.rb +1 -1
- data/lib/action_view/helpers/atom_feed_helper.rb +1 -1
- data/lib/action_view/helpers/date_helper.rb +19 -3
- data/lib/action_view/helpers/form_helper.rb +4 -2
- data/lib/action_view/helpers/form_options_helper.rb +5 -4
- data/lib/action_view/helpers/form_tag_helper.rb +4 -0
- data/lib/action_view/helpers/number_helper.rb +8 -1
- data/lib/action_view/helpers/output_safety_helper.rb +30 -0
- data/lib/action_view/helpers/sanitize_helper.rb +1 -1
- data/lib/action_view/helpers/url_helper.rb +11 -11
- data/lib/action_view/log_subscriber.rb +18 -0
- data/lib/action_view/lookup_context.rb +31 -2
- data/lib/action_view/railtie.rb +3 -5
- data/lib/action_view/renderer/abstract_renderer.rb +1 -1
- data/lib/action_view/renderer/partial_renderer.rb +1 -1
- data/lib/action_view/tasks/{dependencies.rake → cache_digests.rake} +2 -2
- data/lib/action_view/template/resolver.rb +16 -4
- data/lib/action_view/template/types.rb +0 -1
- data/lib/action_view/view_paths.rb +1 -3
- metadata +11 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 768e4964d149a5bc14eead72995ad8ef3536470d
|
4
|
+
data.tar.gz: de1dce7d080bfd7e4c1662dadafac393438dcede
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6554825ae4f6172d0dc2ed7392de0a2384230558c4bf3e9e16caceda7c9f11010ff3f5d3335761af6997201743345931417dc3b472a884ee348da3a44f63521c
|
7
|
+
data.tar.gz: a43c2274df7c6ef07f3d21f7e04fe1c3eb301beb890cf30382ba5bbccd020493655fe2d999dc04d336d15ebab3711f2f206f9d518b2a4e832e13a341d43aed51
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,37 @@
|
|
1
|
+
## Rails 5.0.0.beta4 (April 27, 2016) ##
|
2
|
+
|
3
|
+
* `date_select` helper `:with_css_classes` option now accepts a hash of strings
|
4
|
+
for `:year`, `:month`, `:day`, `:hour`, `:minute`, `:second` that will extend
|
5
|
+
the select type with the given css class value.
|
6
|
+
|
7
|
+
```erb
|
8
|
+
<%= f.date_select :birthday, with_css_classes: { month: "my-month", year: "my-year" } %>
|
9
|
+
```
|
10
|
+
|
11
|
+
```html
|
12
|
+
<select id="user_birthday_3i" name="user[birthday(3i)]">…</select>
|
13
|
+
<select id="user_birthday_2i" name="user[birthday(2i)]" class="my-month">…</select>
|
14
|
+
<select id="user_birthday_1i" name="user[birthday(1i)]" class="my-year">…</select>
|
15
|
+
```
|
16
|
+
|
17
|
+
*Matthias Neumayr*
|
18
|
+
|
19
|
+
* Add `to_sentence` helper that is a HTML-safe aware version of `Array#to_sentence`.
|
20
|
+
|
21
|
+
*Neil Matatall*
|
22
|
+
|
23
|
+
* Deprecate `datetime_field` and `datetime_field_tag` helpers.
|
24
|
+
Datetime input type was removed from HTML specification.
|
25
|
+
One can use `datetime_local_field` and `datetime_local_field_tag` instead.
|
26
|
+
|
27
|
+
*Wojciech Wnętrzak*
|
28
|
+
|
29
|
+
* Added log "Rendering ...", when starting to render a template to log that
|
30
|
+
we have started rendering something. This helps to easily identify the origin
|
31
|
+
of queries in the log whether they came from controller or views.
|
32
|
+
|
33
|
+
*Vipul A M and Prem Sichanugrist*
|
34
|
+
|
1
35
|
## Rails 5.0.0.beta3 (February 24, 2016) ##
|
2
36
|
|
3
37
|
* Collection rendering can cache and fetch multiple partials at once.
|
@@ -38,7 +72,7 @@
|
|
38
72
|
|
39
73
|
* Create a new `ActiveSupport::SafeBuffer` instance when `content_for` is flushed.
|
40
74
|
|
41
|
-
Fixes #19890
|
75
|
+
Fixes #19890.
|
42
76
|
|
43
77
|
*Yoong Kang Lim*
|
44
78
|
|
data/lib/action_view/digestor.rb
CHANGED
@@ -4,7 +4,7 @@ require 'monitor'
|
|
4
4
|
|
5
5
|
module ActionView
|
6
6
|
class Digestor
|
7
|
-
@@
|
7
|
+
@@digest_mutex = Mutex.new
|
8
8
|
|
9
9
|
class PerRequestDigestCacheExpiry < Struct.new(:app) # :nodoc:
|
10
10
|
def call(env)
|
@@ -20,111 +20,104 @@ module ActionView
|
|
20
20
|
# * <tt>finder</tt> - An instance of <tt>ActionView::LookupContext</tt>
|
21
21
|
# * <tt>dependencies</tt> - An array of dependent views
|
22
22
|
# * <tt>partial</tt> - Specifies whether the template is a partial
|
23
|
-
def digest(name:, finder:,
|
24
|
-
|
25
|
-
|
26
|
-
cache_key = ([ name ].compact + Array.wrap(options[:dependencies])).join('.')
|
23
|
+
def digest(name:, finder:, dependencies: [])
|
24
|
+
dependencies ||= []
|
25
|
+
cache_key = ([ name ].compact + dependencies).join('.')
|
27
26
|
|
28
27
|
# this is a correctly done double-checked locking idiom
|
29
28
|
# (Concurrent::Map's lookups have volatile semantics)
|
30
|
-
finder.digest_cache[cache_key] || @@
|
29
|
+
finder.digest_cache[cache_key] || @@digest_mutex.synchronize do
|
31
30
|
finder.digest_cache.fetch(cache_key) do # re-check under lock
|
32
|
-
|
31
|
+
partial = name.include?("/_")
|
32
|
+
root = tree(name, finder, partial)
|
33
|
+
dependencies.each do |injected_dep|
|
34
|
+
root.children << Injected.new(injected_dep, nil, nil)
|
35
|
+
end
|
36
|
+
finder.digest_cache[cache_key] = root.digest(finder)
|
33
37
|
end
|
34
38
|
end
|
35
39
|
end
|
36
40
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
# Prevent re-entry or else recursive templates will blow the stack.
|
41
|
-
# There is no need to worry about other threads seeing the +false+ value,
|
42
|
-
# as they will then have to wait for this thread to let go of the @@digest_monitor lock.
|
43
|
-
pre_stored = finder.digest_cache.put_if_absent(cache_key, false).nil? # put_if_absent returns nil on insertion
|
44
|
-
PartialDigestor
|
45
|
-
else
|
46
|
-
Digestor
|
47
|
-
end
|
48
|
-
|
49
|
-
finder.digest_cache[cache_key] = stored_digest = klass.new(name, finder, options).digest
|
50
|
-
ensure
|
51
|
-
# something went wrong or ActionView::Resolver.caching? is false, make sure not to corrupt the @@cache
|
52
|
-
finder.digest_cache.delete_pair(cache_key, false) if pre_stored && !stored_digest
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
attr_reader :name, :finder, :options
|
41
|
+
def logger
|
42
|
+
ActionView::Base.logger || NullLogger
|
43
|
+
end
|
57
44
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
end
|
45
|
+
# Create a dependency tree for template named +name+.
|
46
|
+
def tree(name, finder, partial = false, seen = {})
|
47
|
+
logical_name = name.gsub(%r|/_|, "/")
|
62
48
|
|
63
|
-
|
64
|
-
|
65
|
-
logger.debug " Cache digest for #{template.inspect}: #{digest}"
|
66
|
-
end
|
67
|
-
rescue ActionView::MissingTemplate
|
68
|
-
logger.error " Couldn't find template for digesting: #{name}"
|
69
|
-
''
|
70
|
-
end
|
49
|
+
if finder.disable_cache { finder.exists?(logical_name, [], partial) }
|
50
|
+
template = finder.disable_cache { finder.find(logical_name, [], partial) }
|
71
51
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
[]
|
77
|
-
end
|
52
|
+
if node = seen[template.identifier] # handle cycles in the tree
|
53
|
+
node
|
54
|
+
else
|
55
|
+
node = seen[template.identifier] = Node.create(name, logical_name, template, partial)
|
78
56
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
57
|
+
deps = DependencyTracker.find_dependencies(name, template, finder.view_paths)
|
58
|
+
deps.uniq { |n| n.gsub(%r|/_|, "/") }.each do |dep_file|
|
59
|
+
node.children << tree(dep_file, finder, true, seen)
|
60
|
+
end
|
61
|
+
node
|
62
|
+
end
|
63
|
+
else
|
64
|
+
logger.error " '#{name}' file doesn't exist, so no dependencies"
|
65
|
+
logger.error " Couldn't find template for digesting: #{name}"
|
66
|
+
seen[name] ||= Missing.new(name, logical_name, nil)
|
67
|
+
end
|
83
68
|
end
|
84
69
|
end
|
85
70
|
|
86
|
-
|
87
|
-
|
88
|
-
def self.debug(_); end
|
89
|
-
def self.error(_); end
|
90
|
-
end
|
71
|
+
class Node
|
72
|
+
attr_reader :name, :logical_name, :template, :children
|
91
73
|
|
92
|
-
def
|
93
|
-
|
74
|
+
def self.create(name, logical_name, template, partial)
|
75
|
+
klass = partial ? Partial : Node
|
76
|
+
klass.new(name, logical_name, template, [])
|
94
77
|
end
|
95
78
|
|
96
|
-
def logical_name
|
97
|
-
name
|
79
|
+
def initialize(name, logical_name, template, children = [])
|
80
|
+
@name = name
|
81
|
+
@logical_name = logical_name
|
82
|
+
@template = template
|
83
|
+
@children = children
|
98
84
|
end
|
99
85
|
|
100
|
-
def
|
101
|
-
|
86
|
+
def digest(finder, stack = [])
|
87
|
+
Digest::MD5.hexdigest("#{template.source}-#{dependency_digest(finder, stack)}")
|
102
88
|
end
|
103
89
|
|
104
|
-
def
|
105
|
-
|
90
|
+
def dependency_digest(finder, stack)
|
91
|
+
children.map do |node|
|
92
|
+
if stack.include?(node)
|
93
|
+
false
|
94
|
+
else
|
95
|
+
finder.digest_cache[node.name] ||= begin
|
96
|
+
stack.push node
|
97
|
+
node.digest(finder, stack).tap { stack.pop }
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end.join("-")
|
106
101
|
end
|
107
102
|
|
108
|
-
def
|
109
|
-
|
103
|
+
def to_dep_map
|
104
|
+
children.any? ? { name => children.map(&:to_dep_map) } : name
|
110
105
|
end
|
106
|
+
end
|
111
107
|
|
112
|
-
|
113
|
-
template_digests = dependencies.collect do |template_name|
|
114
|
-
Digestor.digest(name: template_name, finder: finder, partial: true)
|
115
|
-
end
|
108
|
+
class Partial < Node; end
|
116
109
|
|
117
|
-
|
118
|
-
end
|
110
|
+
class Missing < Node
|
111
|
+
def digest(finder, _ = []) '' end
|
112
|
+
end
|
119
113
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
end
|
114
|
+
class Injected < Node
|
115
|
+
def digest(finder, _ = []) name end
|
116
|
+
end
|
124
117
|
|
125
|
-
|
126
|
-
|
127
|
-
|
118
|
+
class NullLogger
|
119
|
+
def self.debug(_); end
|
120
|
+
def self.error(_); end
|
128
121
|
end
|
129
122
|
end
|
130
123
|
end
|
data/lib/action_view/flows.rb
CHANGED
@@ -37,9 +37,8 @@ module ActionView
|
|
37
37
|
end
|
38
38
|
|
39
39
|
# Try to get stored content. If the content
|
40
|
-
# is not available and we
|
41
|
-
#
|
42
|
-
# key and yield.
|
40
|
+
# is not available and we're inside the layout fiber,
|
41
|
+
# then it will begin waiting for the given key and yield.
|
43
42
|
def get(key)
|
44
43
|
return super if @content.key?(key)
|
45
44
|
|
@@ -60,8 +59,8 @@ module ActionView
|
|
60
59
|
end
|
61
60
|
|
62
61
|
# Appends the contents for the given key. This is called
|
63
|
-
# by
|
64
|
-
# the key it
|
62
|
+
# by providing and resuming back to the fiber,
|
63
|
+
# if that's the key it's waiting for.
|
65
64
|
def append!(key, value)
|
66
65
|
super
|
67
66
|
@fiber.resume if @waiting_for == key
|
@@ -132,7 +132,7 @@ module ActionView
|
|
132
132
|
end
|
133
133
|
|
134
134
|
private
|
135
|
-
# Delegate to xml builder, first wrapping the element in
|
135
|
+
# Delegate to xml builder, first wrapping the element in an xhtml
|
136
136
|
# namespaced div element if the method and arguments indicate
|
137
137
|
# that an xhtml_block? is desired.
|
138
138
|
def method_missing(method, *arguments, &block)
|
@@ -226,8 +226,10 @@ module ActionView
|
|
226
226
|
# for <tt>:year</tt>, <tt>:month</tt>, <tt>:day</tt>, <tt>:hour</tt>, <tt>:minute</tt> and <tt>:second</tt>.
|
227
227
|
# Setting this option prepends a select option with a generic prompt (Day, Month, Year, Hour, Minute, Seconds)
|
228
228
|
# or the given prompt string.
|
229
|
-
# * <tt>:with_css_classes</tt>
|
230
|
-
# automatically set classes 'year', 'month', 'day', 'hour', 'minute' and 'second'
|
229
|
+
# * <tt>:with_css_classes</tt> - Set to true or a hash of strings. Use true if you want to assign generic styles for
|
230
|
+
# select tags. This automatically set classes 'year', 'month', 'day', 'hour', 'minute' and 'second'. A hash of
|
231
|
+
# strings for <tt>:year</tt>, <tt>:month</tt>, <tt>:day</tt>, <tt>:hour</tt>, <tt>:minute</tt>, <tt>:second</tt>
|
232
|
+
# will extend the select type with the given value. Use +html_options+ to modify every select tag in the set.
|
231
233
|
# * <tt>:use_hidden</tt> - Set to true if you only want to generate hidden input tags.
|
232
234
|
#
|
233
235
|
# If anything is passed in the +html_options+ hash it will be applied to every select tag in the set.
|
@@ -994,7 +996,7 @@ module ActionView
|
|
994
996
|
:name => input_name_from_type(type)
|
995
997
|
}.merge!(@html_options)
|
996
998
|
select_options[:disabled] = 'disabled' if @options[:disabled]
|
997
|
-
select_options[:class] =
|
999
|
+
select_options[:class] = css_class_attribute(type, select_options[:class], @options[:with_css_classes]) if @options[:with_css_classes]
|
998
1000
|
|
999
1001
|
select_html = "\n"
|
1000
1002
|
select_html << content_tag("option".freeze, '', :value => '') + "\n" if @options[:include_blank]
|
@@ -1004,6 +1006,20 @@ module ActionView
|
|
1004
1006
|
(content_tag("select".freeze, select_html.html_safe, select_options) + "\n").html_safe
|
1005
1007
|
end
|
1006
1008
|
|
1009
|
+
# Builds the css class value for the select element
|
1010
|
+
# css_class_attribute(:year, 'date optional', { year: 'my-year' })
|
1011
|
+
# => "date optional my-year"
|
1012
|
+
def css_class_attribute(type, html_options_class, options) # :nodoc:
|
1013
|
+
css_class = case options
|
1014
|
+
when Hash
|
1015
|
+
options[type.to_sym]
|
1016
|
+
else
|
1017
|
+
type
|
1018
|
+
end
|
1019
|
+
|
1020
|
+
[html_options_class, css_class].compact.join(' ')
|
1021
|
+
end
|
1022
|
+
|
1007
1023
|
# Builds a prompt option tag with supplied options or from default options.
|
1008
1024
|
# prompt_option_tag(:month, prompt: 'Select month')
|
1009
1025
|
# => "<option value="">Select month</option>"
|
@@ -1118,6 +1118,10 @@ module ActionView
|
|
1118
1118
|
# # => <input id="user_born_on" name="user[born_on]" type="datetime" min="2014-05-20T00:00:00.000+0000" />
|
1119
1119
|
#
|
1120
1120
|
def datetime_field(object_name, method, options = {})
|
1121
|
+
ActiveSupport::Deprecation.warn(<<-MESSAGE.squish)
|
1122
|
+
datetime_field is deprecated and will be removed in Rails 5.1.
|
1123
|
+
Use datetime_local_field instead.
|
1124
|
+
MESSAGE
|
1121
1125
|
Tags::DatetimeField.new(object_name, method, self, options).render
|
1122
1126
|
end
|
1123
1127
|
|
@@ -1922,8 +1926,6 @@ module ActionView
|
|
1922
1926
|
@object_name.to_s.humanize
|
1923
1927
|
end
|
1924
1928
|
|
1925
|
-
model = model.downcase
|
1926
|
-
|
1927
1929
|
defaults = []
|
1928
1930
|
defaults << :"helpers.submit.#{object_name}.#{key}"
|
1929
1931
|
defaults << :"helpers.submit.#{key}"
|
@@ -268,10 +268,11 @@ module ActionView
|
|
268
268
|
# for more information.)
|
269
269
|
#
|
270
270
|
# You can also supply an array of ActiveSupport::TimeZone objects
|
271
|
-
# as +priority_zones
|
272
|
-
# (long) list.
|
273
|
-
#
|
274
|
-
#
|
271
|
+
# as +priority_zones+ so that they will be listed above the rest of the
|
272
|
+
# (long) list. You can use ActiveSupport::TimeZone.us_zones for a list
|
273
|
+
# of US time zones, ActiveSupport::TimeZone.country_zones(country_code)
|
274
|
+
# for another country's time zones, or a Regexp to select the zones of
|
275
|
+
# your choice.
|
275
276
|
#
|
276
277
|
# Finally, this method supports a <tt>:default</tt> option, which selects
|
277
278
|
# a default ActiveSupport::TimeZone if the object's time zone is +nil+.
|
@@ -691,6 +691,10 @@ module ActionView
|
|
691
691
|
# * <tt>:step</tt> - The acceptable value granularity.
|
692
692
|
# * Otherwise accepts the same options as text_field_tag.
|
693
693
|
def datetime_field_tag(name, value = nil, options = {})
|
694
|
+
ActiveSupport::Deprecation.warn(<<-MESSAGE.squish)
|
695
|
+
datetime_field_tag is deprecated and will be removed in Rails 5.1.
|
696
|
+
Use datetime_local_field_tag instead.
|
697
|
+
MESSAGE
|
694
698
|
text_field_tag(name, value, options.merge(type: :datetime))
|
695
699
|
end
|
696
700
|
|
@@ -23,7 +23,7 @@ module ActionView
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
-
# Formats a +number+ into a
|
26
|
+
# Formats a +number+ into a phone number (US by default e.g., (555)
|
27
27
|
# 123-9876). You can customize the format in the +options+ hash.
|
28
28
|
#
|
29
29
|
# ==== Options
|
@@ -35,6 +35,8 @@ module ActionView
|
|
35
35
|
# end of the generated number.
|
36
36
|
# * <tt>:country_code</tt> - Sets the country code for the phone
|
37
37
|
# number.
|
38
|
+
# * <tt>:pattern</tt> - Specifies how the number is divided into three
|
39
|
+
# groups with the custom regexp to override the default format.
|
38
40
|
# * <tt>:raise</tt> - If true, raises +InvalidNumberError+ when
|
39
41
|
# the argument is invalid.
|
40
42
|
#
|
@@ -52,6 +54,11 @@ module ActionView
|
|
52
54
|
#
|
53
55
|
# number_to_phone(1235551234, country_code: 1, extension: 1343, delimiter: ".")
|
54
56
|
# # => +1.123.555.1234 x 1343
|
57
|
+
#
|
58
|
+
# number_to_phone(75561234567, pattern: /(\d{1,4})(\d{4})(\d{4})$/, area_code: true)
|
59
|
+
# # => "(755) 6123-4567"
|
60
|
+
# number_to_phone(13312345678, pattern: /(\d{3})(\d{4})(\d{4})$/))
|
61
|
+
# # => "133-1234-5678"
|
55
62
|
def number_to_phone(number, options = {})
|
56
63
|
return unless number
|
57
64
|
options = options.symbolize_keys
|
@@ -33,6 +33,36 @@ module ActionView #:nodoc:
|
|
33
33
|
|
34
34
|
array.flatten.map! { |i| ERB::Util.unwrapped_html_escape(i) }.join(sep).html_safe
|
35
35
|
end
|
36
|
+
|
37
|
+
# Converts the array to a comma-separated sentence where the last element is
|
38
|
+
# joined by the connector word. This is the html_safe-aware version of
|
39
|
+
# ActiveSupport's {Array#to_sentence}[http://api.rubyonrails.org/classes/Array.html#method-i-to_sentence].
|
40
|
+
#
|
41
|
+
def to_sentence(array, options = {})
|
42
|
+
options.assert_valid_keys(:words_connector, :two_words_connector, :last_word_connector, :locale)
|
43
|
+
|
44
|
+
default_connectors = {
|
45
|
+
:words_connector => ', ',
|
46
|
+
:two_words_connector => ' and ',
|
47
|
+
:last_word_connector => ', and '
|
48
|
+
}
|
49
|
+
if defined?(I18n)
|
50
|
+
i18n_connectors = I18n.translate(:'support.array', locale: options[:locale], default: {})
|
51
|
+
default_connectors.merge!(i18n_connectors)
|
52
|
+
end
|
53
|
+
options = default_connectors.merge!(options)
|
54
|
+
|
55
|
+
case array.length
|
56
|
+
when 0
|
57
|
+
''.html_safe
|
58
|
+
when 1
|
59
|
+
ERB::Util.html_escape(array[0])
|
60
|
+
when 2
|
61
|
+
safe_join([array[0], array[1]], options[:two_words_connector])
|
62
|
+
else
|
63
|
+
safe_join([safe_join(array[0...-1], options[:words_connector]), options[:last_word_connector], array[-1]])
|
64
|
+
end
|
65
|
+
end
|
36
66
|
end
|
37
67
|
end
|
38
68
|
end
|
@@ -120,7 +120,7 @@ module ActionView
|
|
120
120
|
attr_writer :full_sanitizer, :link_sanitizer, :white_list_sanitizer
|
121
121
|
|
122
122
|
# Vendors the full, link and white list sanitizers.
|
123
|
-
# Provided strictly for compatibility and can be removed in Rails 5.
|
123
|
+
# Provided strictly for compatibility and can be removed in Rails 5.1.
|
124
124
|
def sanitizer_vendor
|
125
125
|
Rails::Html::Sanitizer
|
126
126
|
end
|
@@ -302,7 +302,7 @@ module ActionView
|
|
302
302
|
params = html_options.delete('params')
|
303
303
|
|
304
304
|
method = html_options.delete('method').to_s
|
305
|
-
method_tag = BUTTON_TAG_METHOD_VERBS.include?(method) ? method_tag(method) : ''.html_safe
|
305
|
+
method_tag = BUTTON_TAG_METHOD_VERBS.include?(method) ? method_tag(method) : ''.freeze.html_safe
|
306
306
|
|
307
307
|
form_method = method == 'get' ? 'get' : 'post'
|
308
308
|
form_options = html_options.delete('form') || {}
|
@@ -315,7 +315,7 @@ module ActionView
|
|
315
315
|
request_method = method.empty? ? 'post' : method
|
316
316
|
token_tag(nil, form_options: { action: url, method: request_method })
|
317
317
|
else
|
318
|
-
''
|
318
|
+
''.freeze
|
319
319
|
end
|
320
320
|
|
321
321
|
html_options = convert_options_to_data_attributes(options, html_options)
|
@@ -481,7 +481,7 @@ module ActionView
|
|
481
481
|
option = html_options.delete(item).presence || next
|
482
482
|
"#{item.dasherize}=#{ERB::Util.url_encode(option)}"
|
483
483
|
}.compact
|
484
|
-
extras = extras.empty? ? '' : '?' + extras.join('&')
|
484
|
+
extras = extras.empty? ? ''.freeze : '?' + extras.join('&')
|
485
485
|
|
486
486
|
encoded_email_address = ERB::Util.url_encode(email_address).gsub("%40", "@")
|
487
487
|
html_options["href"] = "mailto:#{encoded_email_address}#{extras}"
|
@@ -559,29 +559,29 @@ module ActionView
|
|
559
559
|
def convert_options_to_data_attributes(options, html_options)
|
560
560
|
if html_options
|
561
561
|
html_options = html_options.stringify_keys
|
562
|
-
html_options['data-remote'] = 'true' if link_to_remote_options?(options) || link_to_remote_options?(html_options)
|
562
|
+
html_options['data-remote'] = 'true'.freeze if link_to_remote_options?(options) || link_to_remote_options?(html_options)
|
563
563
|
|
564
|
-
method = html_options.delete('method')
|
564
|
+
method = html_options.delete('method'.freeze)
|
565
565
|
|
566
566
|
add_method_to_attributes!(html_options, method) if method
|
567
567
|
|
568
568
|
html_options
|
569
569
|
else
|
570
|
-
link_to_remote_options?(options) ? {'data-remote' => 'true'} : {}
|
570
|
+
link_to_remote_options?(options) ? {'data-remote' => 'true'.freeze} : {}
|
571
571
|
end
|
572
572
|
end
|
573
573
|
|
574
574
|
def link_to_remote_options?(options)
|
575
575
|
if options.is_a?(Hash)
|
576
|
-
options.delete('remote') || options.delete(:remote)
|
576
|
+
options.delete('remote'.freeze) || options.delete(:remote)
|
577
577
|
end
|
578
578
|
end
|
579
579
|
|
580
580
|
def add_method_to_attributes!(html_options, method)
|
581
|
-
if method && method.to_s.downcase != "get" && html_options["rel"] !~ /nofollow/
|
582
|
-
html_options["rel"] = "#{html_options["rel"]} nofollow".lstrip
|
581
|
+
if method && method.to_s.downcase != "get".freeze && html_options["rel".freeze] !~ /nofollow/
|
582
|
+
html_options["rel".freeze] = "#{html_options["rel".freeze]} nofollow".lstrip
|
583
583
|
end
|
584
|
-
html_options["data-method"] = method
|
584
|
+
html_options["data-method".freeze] = method
|
585
585
|
end
|
586
586
|
|
587
587
|
def token_tag(token=nil, form_options: {})
|
@@ -589,7 +589,7 @@ module ActionView
|
|
589
589
|
token ||= form_authenticity_token(form_options: form_options)
|
590
590
|
tag(:input, type: "hidden", name: request_forgery_protection_token.to_s, value: token)
|
591
591
|
else
|
592
|
-
''
|
592
|
+
''.freeze
|
593
593
|
end
|
594
594
|
end
|
595
595
|
|
@@ -30,6 +30,14 @@ module ActionView
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
+
def start(name, id, payload)
|
34
|
+
if name == "render_template.action_view"
|
35
|
+
log_rendering_start(payload)
|
36
|
+
end
|
37
|
+
|
38
|
+
super
|
39
|
+
end
|
40
|
+
|
33
41
|
def logger
|
34
42
|
ActionView::Base.logger
|
35
43
|
end
|
@@ -54,6 +62,16 @@ module ActionView
|
|
54
62
|
"[#{payload[:count]} times]"
|
55
63
|
end
|
56
64
|
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def log_rendering_start(payload)
|
69
|
+
info do
|
70
|
+
message = " Rendering #{from_rails_root(payload[:identifier])}"
|
71
|
+
message << " within #{from_rails_root(payload[:layout])}" if payload[:layout]
|
72
|
+
message
|
73
|
+
end
|
74
|
+
end
|
57
75
|
end
|
58
76
|
end
|
59
77
|
|
@@ -70,8 +70,6 @@ module ActionView
|
|
70
70
|
@details_keys.clear
|
71
71
|
end
|
72
72
|
|
73
|
-
def self.empty?; @details_keys.empty?; end
|
74
|
-
|
75
73
|
def self.digest_caches
|
76
74
|
@details_keys.values.map(&:digest_cache)
|
77
75
|
end
|
@@ -138,6 +136,11 @@ module ActionView
|
|
138
136
|
end
|
139
137
|
alias :template_exists? :exists?
|
140
138
|
|
139
|
+
def any?(name, prefixes = [], partial = false)
|
140
|
+
@view_paths.exists?(*args_for_any(name, prefixes, partial))
|
141
|
+
end
|
142
|
+
alias :any_templates? :any?
|
143
|
+
|
141
144
|
# Adds fallbacks to the view paths. Useful in cases when you are rendering
|
142
145
|
# a :file.
|
143
146
|
def with_fallbacks
|
@@ -174,6 +177,32 @@ module ActionView
|
|
174
177
|
[user_details, details_key]
|
175
178
|
end
|
176
179
|
|
180
|
+
def args_for_any(name, prefixes, partial) # :nodoc:
|
181
|
+
name, prefixes = normalize_name(name, prefixes)
|
182
|
+
details, details_key = detail_args_for_any
|
183
|
+
[name, prefixes, partial || false, details, details_key]
|
184
|
+
end
|
185
|
+
|
186
|
+
def detail_args_for_any # :nodoc:
|
187
|
+
@detail_args_for_any ||= begin
|
188
|
+
details = {}
|
189
|
+
|
190
|
+
registered_details.each do |k|
|
191
|
+
if k == :variants
|
192
|
+
details[k] = :any
|
193
|
+
else
|
194
|
+
details[k] = Accessors::DEFAULT_PROCS[k].call
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
if @cache
|
199
|
+
[details, DetailsKey.get(details)]
|
200
|
+
else
|
201
|
+
[details, nil]
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
177
206
|
# Support legacy foo.erb names even though we now ignore .erb
|
178
207
|
# as well as incorrectly putting part of the path in the template
|
179
208
|
# name instead of the prefix.
|
data/lib/action_view/railtie.rb
CHANGED
@@ -37,10 +37,8 @@ module ActionView
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
-
initializer "action_view.collection_caching" do |app|
|
41
|
-
|
42
|
-
PartialRenderer.collection_cache = app.config.action_controller.cache_store
|
43
|
-
end
|
40
|
+
initializer "action_view.collection_caching", after: "action_controller.set_configs" do |app|
|
41
|
+
PartialRenderer.collection_cache = app.config.action_controller.cache_store
|
44
42
|
end
|
45
43
|
|
46
44
|
initializer "action_view.per_request_digest_cache" do |app|
|
@@ -59,7 +57,7 @@ module ActionView
|
|
59
57
|
|
60
58
|
rake_tasks do |app|
|
61
59
|
unless app.config.api_only
|
62
|
-
load "action_view/tasks/
|
60
|
+
load "action_view/tasks/cache_digests.rake"
|
63
61
|
end
|
64
62
|
end
|
65
63
|
end
|
@@ -15,7 +15,7 @@ module ActionView
|
|
15
15
|
# that new object is called in turn. This abstracts the setup and rendering
|
16
16
|
# into a separate classes for partials and templates.
|
17
17
|
class AbstractRenderer #:nodoc:
|
18
|
-
delegate :find_template, :find_file, :template_exists?, :with_fallbacks, :with_layout_format, :formats, :to => :@lookup_context
|
18
|
+
delegate :find_template, :find_file, :template_exists?, :any_templates?, :with_fallbacks, :with_layout_format, :formats, :to => :@lookup_context
|
19
19
|
|
20
20
|
def initialize(lookup_context)
|
21
21
|
@lookup_context = lookup_context
|
@@ -521,7 +521,7 @@ module ActionView
|
|
521
521
|
def retrieve_variable(path, as)
|
522
522
|
variable = as || begin
|
523
523
|
base = path[-1] == "/".freeze ? "".freeze : File.basename(path)
|
524
|
-
raise_invalid_identifier(path) unless base =~ /\A_?(
|
524
|
+
raise_invalid_identifier(path) unless base =~ /\A_?(.*?)(?:\.\w+)*\z/
|
525
525
|
$1.to_sym
|
526
526
|
end
|
527
527
|
if @collection
|
@@ -2,13 +2,13 @@ namespace :cache_digests do
|
|
2
2
|
desc 'Lookup nested dependencies for TEMPLATE (like messages/show or comments/_comment.html)'
|
3
3
|
task :nested_dependencies => :environment do
|
4
4
|
abort 'You must provide TEMPLATE for the task to run' unless ENV['TEMPLATE'].present?
|
5
|
-
puts JSON.pretty_generate ActionView::Digestor.
|
5
|
+
puts JSON.pretty_generate ActionView::Digestor.tree(CacheDigests.template_name, CacheDigests.finder).children.map(&:to_dep_map)
|
6
6
|
end
|
7
7
|
|
8
8
|
desc 'Lookup first-level dependencies for TEMPLATE (like messages/show or comments/_comment.html)'
|
9
9
|
task :dependencies => :environment do
|
10
10
|
abort 'You must provide TEMPLATE for the task to run' unless ENV['TEMPLATE'].present?
|
11
|
-
puts JSON.pretty_generate ActionView::Digestor.
|
11
|
+
puts JSON.pretty_generate ActionView::Digestor.tree(CacheDigests.template_name, CacheDigests.finder).children.map(&:name)
|
12
12
|
end
|
13
13
|
|
14
14
|
class CacheDigests
|
@@ -55,6 +55,10 @@ module ActionView
|
|
55
55
|
@query_cache = SmallCache.new
|
56
56
|
end
|
57
57
|
|
58
|
+
def inspect
|
59
|
+
"#<#{self.class.name}:0x#{(object_id << 1).to_s(16)} keys=#{@data.size} queries=#{@query_cache.size}>"
|
60
|
+
end
|
61
|
+
|
58
62
|
# Cache the templates returned by the block
|
59
63
|
def cache(key, name, prefix, partial, locals)
|
60
64
|
if Resolver.caching?
|
@@ -222,7 +226,7 @@ module ActionView
|
|
222
226
|
end
|
223
227
|
|
224
228
|
def find_template_paths(query)
|
225
|
-
Dir[query].reject do |filename|
|
229
|
+
Dir[query].uniq.reject do |filename|
|
226
230
|
File.directory?(filename) ||
|
227
231
|
# deals with case-insensitive file systems.
|
228
232
|
!File.fnmatch(query, filename, File::FNM_EXTGLOB)
|
@@ -245,8 +249,12 @@ module ActionView
|
|
245
249
|
partial = escape_entry(path.partial? ? "_#{path.name}" : path.name)
|
246
250
|
query.gsub!(/:action/, partial)
|
247
251
|
|
248
|
-
details.each do |ext,
|
249
|
-
|
252
|
+
details.each do |ext, candidates|
|
253
|
+
if ext == :variants && candidates == :any
|
254
|
+
query.gsub!(/:#{ext}/, "*")
|
255
|
+
else
|
256
|
+
query.gsub!(/:#{ext}/, "{#{candidates.compact.uniq.join(',')}}")
|
257
|
+
end
|
250
258
|
end
|
251
259
|
|
252
260
|
File.expand_path(query, @path)
|
@@ -340,7 +348,11 @@ module ActionView
|
|
340
348
|
query = escape_entry(File.join(@path, path))
|
341
349
|
|
342
350
|
exts = EXTENSIONS.map do |ext, prefix|
|
343
|
-
|
351
|
+
if ext == :variants && details[ext] == :any
|
352
|
+
"{#{prefix}*,}"
|
353
|
+
else
|
354
|
+
"{#{details[ext].compact.uniq.map { |e| "#{prefix}#{e}," }.join}}"
|
355
|
+
end
|
344
356
|
end.join
|
345
357
|
|
346
358
|
query + exts
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'action_view/base'
|
2
|
-
|
3
1
|
module ActionView
|
4
2
|
module ViewPaths
|
5
3
|
extend ActiveSupport::Concern
|
@@ -10,7 +8,7 @@ module ActionView
|
|
10
8
|
self._view_paths.freeze
|
11
9
|
end
|
12
10
|
|
13
|
-
delegate :template_exists?, :view_paths, :formats, :formats=,
|
11
|
+
delegate :template_exists?, :any_templates?, :view_paths, :formats, :formats=,
|
14
12
|
:locale, :locale=, :to => :lookup_context
|
15
13
|
|
16
14
|
module ClassMethods
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: actionview
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.0.0.
|
4
|
+
version: 5.0.0.beta4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Heinemeier Hansson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-04-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 5.0.0.
|
19
|
+
version: 5.0.0.beta4
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 5.0.0.
|
26
|
+
version: 5.0.0.beta4
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: builder
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -98,28 +98,28 @@ dependencies:
|
|
98
98
|
requirements:
|
99
99
|
- - '='
|
100
100
|
- !ruby/object:Gem::Version
|
101
|
-
version: 5.0.0.
|
101
|
+
version: 5.0.0.beta4
|
102
102
|
type: :development
|
103
103
|
prerelease: false
|
104
104
|
version_requirements: !ruby/object:Gem::Requirement
|
105
105
|
requirements:
|
106
106
|
- - '='
|
107
107
|
- !ruby/object:Gem::Version
|
108
|
-
version: 5.0.0.
|
108
|
+
version: 5.0.0.beta4
|
109
109
|
- !ruby/object:Gem::Dependency
|
110
110
|
name: activemodel
|
111
111
|
requirement: !ruby/object:Gem::Requirement
|
112
112
|
requirements:
|
113
113
|
- - '='
|
114
114
|
- !ruby/object:Gem::Version
|
115
|
-
version: 5.0.0.
|
115
|
+
version: 5.0.0.beta4
|
116
116
|
type: :development
|
117
117
|
prerelease: false
|
118
118
|
version_requirements: !ruby/object:Gem::Requirement
|
119
119
|
requirements:
|
120
120
|
- - '='
|
121
121
|
- !ruby/object:Gem::Version
|
122
|
-
version: 5.0.0.
|
122
|
+
version: 5.0.0.beta4
|
123
123
|
description: Simple, battle-tested conventions and helpers for building web pages.
|
124
124
|
email: david@loudthinking.com
|
125
125
|
executables: []
|
@@ -213,7 +213,7 @@ files:
|
|
213
213
|
- lib/action_view/renderer/template_renderer.rb
|
214
214
|
- lib/action_view/rendering.rb
|
215
215
|
- lib/action_view/routing_url_for.rb
|
216
|
-
- lib/action_view/tasks/
|
216
|
+
- lib/action_view/tasks/cache_digests.rake
|
217
217
|
- lib/action_view/template.rb
|
218
218
|
- lib/action_view/template/error.rb
|
219
219
|
- lib/action_view/template/handlers.rb
|
@@ -229,7 +229,7 @@ files:
|
|
229
229
|
- lib/action_view/testing/resolvers.rb
|
230
230
|
- lib/action_view/version.rb
|
231
231
|
- lib/action_view/view_paths.rb
|
232
|
-
homepage: http://
|
232
|
+
homepage: http://rubyonrails.org
|
233
233
|
licenses:
|
234
234
|
- MIT
|
235
235
|
metadata: {}
|
@@ -250,7 +250,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
250
250
|
requirements:
|
251
251
|
- none
|
252
252
|
rubyforge_project:
|
253
|
-
rubygems_version: 2.
|
253
|
+
rubygems_version: 2.6.4
|
254
254
|
signing_key:
|
255
255
|
specification_version: 4
|
256
256
|
summary: Rendering framework putting the V in MVC (part of Rails).
|