actionview 4.2.10 → 5.1.0
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 +141 -272
- data/MIT-LICENSE +1 -1
- data/README.rdoc +2 -3
- data/lib/action_view/base.rb +33 -21
- data/lib/action_view/buffers.rb +1 -1
- data/lib/action_view/context.rb +1 -1
- data/lib/action_view/dependency_tracker.rb +52 -20
- data/lib/action_view/digestor.rb +86 -83
- data/lib/action_view/flows.rb +9 -11
- data/lib/action_view/gem_version.rb +3 -3
- data/lib/action_view/helpers/active_model_helper.rb +8 -8
- data/lib/action_view/helpers/asset_tag_helper.rb +74 -38
- data/lib/action_view/helpers/asset_url_helper.rb +160 -59
- data/lib/action_view/helpers/atom_feed_helper.rb +16 -16
- data/lib/action_view/helpers/cache_helper.rb +90 -35
- data/lib/action_view/helpers/capture_helper.rb +7 -6
- data/lib/action_view/helpers/controller_helper.rb +3 -2
- data/lib/action_view/helpers/csrf_helper.rb +3 -3
- data/lib/action_view/helpers/date_helper.rb +156 -108
- data/lib/action_view/helpers/debug_helper.rb +3 -4
- data/lib/action_view/helpers/form_helper.rb +475 -94
- data/lib/action_view/helpers/form_options_helper.rb +87 -47
- data/lib/action_view/helpers/form_tag_helper.rb +88 -57
- data/lib/action_view/helpers/javascript_helper.rb +10 -10
- data/lib/action_view/helpers/number_helper.rb +76 -59
- data/lib/action_view/helpers/output_safety_helper.rb +34 -4
- data/lib/action_view/helpers/record_tag_helper.rb +12 -99
- data/lib/action_view/helpers/rendering_helper.rb +3 -3
- data/lib/action_view/helpers/sanitize_helper.rb +17 -14
- data/lib/action_view/helpers/tag_helper.rb +198 -73
- data/lib/action_view/helpers/tags/base.rb +132 -97
- data/lib/action_view/helpers/tags/check_box.rb +17 -17
- data/lib/action_view/helpers/tags/collection_check_boxes.rb +9 -33
- data/lib/action_view/helpers/tags/collection_helpers.rb +68 -36
- data/lib/action_view/helpers/tags/collection_radio_buttons.rb +3 -11
- data/lib/action_view/helpers/tags/collection_select.rb +2 -2
- data/lib/action_view/helpers/tags/date_select.rb +36 -36
- data/lib/action_view/helpers/tags/datetime_field.rb +1 -1
- data/lib/action_view/helpers/tags/grouped_collection_select.rb +2 -2
- data/lib/action_view/helpers/tags/label.rb +5 -1
- data/lib/action_view/helpers/tags/password_field.rb +1 -1
- data/lib/action_view/helpers/tags/placeholderable.rb +1 -1
- data/lib/action_view/helpers/tags/radio_button.rb +4 -4
- data/lib/action_view/helpers/tags/search_field.rb +12 -9
- data/lib/action_view/helpers/tags/select.rb +9 -9
- data/lib/action_view/helpers/tags/text_area.rb +1 -1
- data/lib/action_view/helpers/tags/text_field.rb +5 -6
- data/lib/action_view/helpers/tags/translator.rb +15 -13
- data/lib/action_view/helpers/text_helper.rb +47 -30
- data/lib/action_view/helpers/translation_helper.rb +60 -30
- data/lib/action_view/helpers/url_helper.rb +132 -104
- data/lib/action_view/helpers.rb +1 -1
- data/lib/action_view/layouts.rb +59 -54
- data/lib/action_view/log_subscriber.rb +56 -7
- data/lib/action_view/lookup_context.rb +76 -61
- data/lib/action_view/model_naming.rb +1 -1
- data/lib/action_view/path_set.rb +28 -19
- data/lib/action_view/railtie.rb +30 -6
- data/lib/action_view/record_identifier.rb +51 -25
- data/lib/action_view/renderer/abstract_renderer.rb +19 -15
- data/lib/action_view/renderer/partial_renderer/collection_caching.rb +55 -0
- data/lib/action_view/renderer/partial_renderer.rb +208 -206
- data/lib/action_view/renderer/renderer.rb +2 -6
- data/lib/action_view/renderer/streaming_template_renderer.rb +46 -48
- data/lib/action_view/renderer/template_renderer.rb +65 -66
- data/lib/action_view/rendering.rb +16 -9
- data/lib/action_view/routing_url_for.rb +25 -17
- data/lib/action_view/tasks/cache_digests.rake +23 -0
- data/lib/action_view/template/error.rb +14 -13
- data/lib/action_view/template/handlers/builder.rb +7 -7
- data/lib/action_view/template/handlers/erb/deprecated_erubis.rb +9 -0
- data/lib/action_view/template/handlers/erb/erubi.rb +81 -0
- data/lib/action_view/template/handlers/erb/erubis.rb +81 -0
- data/lib/action_view/template/handlers/erb.rb +9 -76
- data/lib/action_view/template/handlers/html.rb +9 -0
- data/lib/action_view/template/handlers/raw.rb +1 -3
- data/lib/action_view/template/handlers.rb +8 -6
- data/lib/action_view/template/html.rb +2 -4
- data/lib/action_view/template/resolver.rb +133 -109
- data/lib/action_view/template/text.rb +5 -8
- data/lib/action_view/template/types.rb +15 -17
- data/lib/action_view/template.rb +51 -28
- data/lib/action_view/test_case.rb +32 -27
- data/lib/action_view/testing/resolvers.rb +29 -31
- data/lib/action_view/version.rb +1 -1
- data/lib/action_view/view_paths.rb +26 -32
- data/lib/action_view.rb +5 -5
- data/lib/assets/compiled/rails-ujs.js +685 -0
- metadata +23 -23
- data/lib/action_view/tasks/dependencies.rake +0 -23
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "active_support/log_subscriber"
|
2
2
|
|
3
3
|
module ActionView
|
4
4
|
# = Action View Log Subscriber
|
@@ -19,25 +19,74 @@ module ActionView
|
|
19
19
|
message << " (#{event.duration.round(1)}ms)"
|
20
20
|
end
|
21
21
|
end
|
22
|
-
|
23
|
-
|
22
|
+
|
23
|
+
def render_partial(event)
|
24
|
+
info do
|
25
|
+
message = " Rendered #{from_rails_root(event.payload[:identifier])}"
|
26
|
+
message << " within #{from_rails_root(event.payload[:layout])}" if event.payload[:layout]
|
27
|
+
message << " (#{event.duration.round(1)}ms)"
|
28
|
+
message << " #{cache_message(event.payload)}" if event.payload.key?(:cache_hit)
|
29
|
+
message
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def render_collection(event)
|
34
|
+
identifier = event.payload[:identifier] || "templates"
|
35
|
+
|
36
|
+
info do
|
37
|
+
" Rendered collection of #{from_rails_root(identifier)}" \
|
38
|
+
" #{render_count(event.payload)} (#{event.duration.round(1)}ms)"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def start(name, id, payload)
|
43
|
+
if name == "render_template.action_view"
|
44
|
+
log_rendering_start(payload)
|
45
|
+
end
|
46
|
+
|
47
|
+
super
|
48
|
+
end
|
24
49
|
|
25
50
|
def logger
|
26
51
|
ActionView::Base.logger
|
27
52
|
end
|
28
53
|
|
29
|
-
|
54
|
+
private
|
30
55
|
|
31
|
-
EMPTY =
|
32
|
-
def from_rails_root(string)
|
56
|
+
EMPTY = ""
|
57
|
+
def from_rails_root(string) # :doc:
|
33
58
|
string = string.sub(rails_root, EMPTY)
|
34
59
|
string.sub!(VIEWS_PATTERN, EMPTY)
|
35
60
|
string
|
36
61
|
end
|
37
62
|
|
38
|
-
def rails_root
|
63
|
+
def rails_root # :doc:
|
39
64
|
@root ||= "#{Rails.root}/"
|
40
65
|
end
|
66
|
+
|
67
|
+
def render_count(payload) # :doc:
|
68
|
+
if payload[:cache_hits]
|
69
|
+
"[#{payload[:cache_hits]} / #{payload[:count]} cache hits]"
|
70
|
+
else
|
71
|
+
"[#{payload[:count]} times]"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def cache_message(payload) # :doc:
|
76
|
+
if payload[:cache_hit]
|
77
|
+
"[cache hit]"
|
78
|
+
else
|
79
|
+
"[cache miss]"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def log_rendering_start(payload)
|
84
|
+
info do
|
85
|
+
message = " Rendering #{from_rails_root(payload[:identifier])}"
|
86
|
+
message << " within #{from_rails_root(payload[:layout])}" if payload[:layout]
|
87
|
+
message
|
88
|
+
end
|
89
|
+
end
|
41
90
|
end
|
42
91
|
end
|
43
92
|
|
@@ -1,15 +1,16 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
1
|
+
require "concurrent/map"
|
2
|
+
require "active_support/core_ext/module/remove_method"
|
3
|
+
require "active_support/core_ext/module/attribute_accessors"
|
4
|
+
require "action_view/template/resolver"
|
5
5
|
|
6
6
|
module ActionView
|
7
7
|
# = Action View Lookup Context
|
8
8
|
#
|
9
|
-
# LookupContext is the object responsible
|
10
|
-
# templates, i.e. view paths and details.
|
11
|
-
#
|
12
|
-
#
|
9
|
+
# <tt>LookupContext</tt> is the object responsible for holding all information
|
10
|
+
# required for looking up templates, i.e. view paths and details.
|
11
|
+
# <tt>LookupContext</tt> is also responsible for generating a key, given to
|
12
|
+
# view paths, used in the resolver cache lookup. Since this key is generated
|
13
|
+
# only once during the request, it speeds up all cache accesses.
|
13
14
|
class LookupContext #:nodoc:
|
14
15
|
attr_accessor :prefixes, :rendered_format
|
15
16
|
|
@@ -19,9 +20,9 @@ module ActionView
|
|
19
20
|
mattr_accessor :registered_details
|
20
21
|
self.registered_details = []
|
21
22
|
|
22
|
-
def self.register_detail(name,
|
23
|
-
|
24
|
-
|
23
|
+
def self.register_detail(name, &block)
|
24
|
+
registered_details << name
|
25
|
+
Accessors::DEFAULT_PROCS[name] = block
|
25
26
|
|
26
27
|
Accessors.send :define_method, :"default_#{name}", &block
|
27
28
|
Accessors.module_eval <<-METHOD, __FILE__, __LINE__ + 1
|
@@ -33,16 +34,12 @@ module ActionView
|
|
33
34
|
value = value.present? ? Array(value) : default_#{name}
|
34
35
|
_set_detail(:#{name}, value) if value != @details[:#{name}]
|
35
36
|
end
|
36
|
-
|
37
|
-
remove_possible_method :initialize_details
|
38
|
-
def initialize_details(details)
|
39
|
-
#{initialize.join("\n")}
|
40
|
-
end
|
41
37
|
METHOD
|
42
38
|
end
|
43
39
|
|
44
40
|
# Holds accessors for the registered details.
|
45
41
|
module Accessors #:nodoc:
|
42
|
+
DEFAULT_PROCS = {}
|
46
43
|
end
|
47
44
|
|
48
45
|
register_detail(:locale) do
|
@@ -54,29 +51,27 @@ module ActionView
|
|
54
51
|
end
|
55
52
|
register_detail(:formats) { ActionView::Base.default_formats || [:html, :text, :js, :css, :xml, :json] }
|
56
53
|
register_detail(:variants) { [] }
|
57
|
-
register_detail(:handlers){ Template::Handlers.extensions }
|
54
|
+
register_detail(:handlers) { Template::Handlers.extensions }
|
58
55
|
|
59
56
|
class DetailsKey #:nodoc:
|
60
57
|
alias :eql? :equal?
|
61
|
-
alias :object_hash :hash
|
62
58
|
|
63
|
-
|
64
|
-
@details_keys = ThreadSafe::Cache.new
|
59
|
+
@details_keys = Concurrent::Map.new
|
65
60
|
|
66
61
|
def self.get(details)
|
67
62
|
if details[:formats]
|
68
63
|
details = details.dup
|
69
|
-
details[:formats] &=
|
64
|
+
details[:formats] &= Template::Types.symbols
|
70
65
|
end
|
71
|
-
@details_keys[details] ||= new
|
66
|
+
@details_keys[details] ||= Concurrent::Map.new
|
72
67
|
end
|
73
68
|
|
74
69
|
def self.clear
|
75
70
|
@details_keys.clear
|
76
71
|
end
|
77
72
|
|
78
|
-
def
|
79
|
-
@
|
73
|
+
def self.digest_caches
|
74
|
+
@details_keys.values
|
80
75
|
end
|
81
76
|
end
|
82
77
|
|
@@ -98,9 +93,9 @@ module ActionView
|
|
98
93
|
@cache = old_value
|
99
94
|
end
|
100
95
|
|
101
|
-
|
96
|
+
private
|
102
97
|
|
103
|
-
def _set_detail(key, value)
|
98
|
+
def _set_detail(key, value) # :doc:
|
104
99
|
@details = @details.dup if @details_key
|
105
100
|
@details_key = nil
|
106
101
|
@details[key] = value
|
@@ -130,11 +125,16 @@ module ActionView
|
|
130
125
|
@view_paths.find_all(*args_for_lookup(name, prefixes, partial, keys, options))
|
131
126
|
end
|
132
127
|
|
133
|
-
def exists?(name, prefixes = [], partial = false, keys = [], options
|
128
|
+
def exists?(name, prefixes = [], partial = false, keys = [], **options)
|
134
129
|
@view_paths.exists?(*args_for_lookup(name, prefixes, partial, keys, options))
|
135
130
|
end
|
136
131
|
alias :template_exists? :exists?
|
137
132
|
|
133
|
+
def any?(name, prefixes = [], partial = false)
|
134
|
+
@view_paths.exists?(*args_for_any(name, prefixes, partial))
|
135
|
+
end
|
136
|
+
alias :any_templates? :any?
|
137
|
+
|
138
138
|
# Adds fallbacks to the view paths. Useful in cases when you are rendering
|
139
139
|
# a :file.
|
140
140
|
def with_fallbacks
|
@@ -149,16 +149,16 @@ module ActionView
|
|
149
149
|
added_resolvers.times { view_paths.pop }
|
150
150
|
end
|
151
151
|
|
152
|
-
|
152
|
+
private
|
153
153
|
|
154
|
-
def args_for_lookup(name, prefixes, partial, keys, details_options)
|
154
|
+
def args_for_lookup(name, prefixes, partial, keys, details_options)
|
155
155
|
name, prefixes = normalize_name(name, prefixes)
|
156
156
|
details, details_key = detail_args_for(details_options)
|
157
157
|
[name, prefixes, partial || false, details, details_key, keys]
|
158
158
|
end
|
159
159
|
|
160
160
|
# Compute details hash and key according to user options (e.g. passed from #render).
|
161
|
-
def detail_args_for(options)
|
161
|
+
def detail_args_for(options) # :doc:
|
162
162
|
return @details, details_key if options.empty? # most common path.
|
163
163
|
user_details = @details.merge(options)
|
164
164
|
|
@@ -171,18 +171,44 @@ module ActionView
|
|
171
171
|
[user_details, details_key]
|
172
172
|
end
|
173
173
|
|
174
|
+
def args_for_any(name, prefixes, partial)
|
175
|
+
name, prefixes = normalize_name(name, prefixes)
|
176
|
+
details, details_key = detail_args_for_any
|
177
|
+
[name, prefixes, partial || false, details, details_key]
|
178
|
+
end
|
179
|
+
|
180
|
+
def detail_args_for_any
|
181
|
+
@detail_args_for_any ||= begin
|
182
|
+
details = {}
|
183
|
+
|
184
|
+
registered_details.each do |k|
|
185
|
+
if k == :variants
|
186
|
+
details[k] = :any
|
187
|
+
else
|
188
|
+
details[k] = Accessors::DEFAULT_PROCS[k].call
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
if @cache
|
193
|
+
[details, DetailsKey.get(details)]
|
194
|
+
else
|
195
|
+
[details, nil]
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
174
200
|
# Support legacy foo.erb names even though we now ignore .erb
|
175
201
|
# as well as incorrectly putting part of the path in the template
|
176
202
|
# name instead of the prefix.
|
177
|
-
def normalize_name(name, prefixes)
|
203
|
+
def normalize_name(name, prefixes)
|
178
204
|
prefixes = prefixes.presence
|
179
|
-
parts = name.to_s.split(
|
205
|
+
parts = name.to_s.split("/".freeze)
|
180
206
|
parts.shift if parts.first.empty?
|
181
|
-
name
|
207
|
+
name = parts.pop
|
182
208
|
|
183
209
|
return name, prefixes || [""] if parts.empty?
|
184
210
|
|
185
|
-
parts = parts.join(
|
211
|
+
parts = parts.join("/".freeze)
|
186
212
|
prefixes = prefixes ? prefixes.map { |p| "#{p}/#{parts}" } : [parts]
|
187
213
|
|
188
214
|
return name, prefixes
|
@@ -194,21 +220,32 @@ module ActionView
|
|
194
220
|
include ViewPaths
|
195
221
|
|
196
222
|
def initialize(view_paths, details = {}, prefixes = [])
|
197
|
-
@
|
198
|
-
@skip_default_locale = false
|
223
|
+
@details_key = nil
|
199
224
|
@cache = true
|
200
225
|
@prefixes = prefixes
|
201
226
|
@rendered_format = nil
|
202
227
|
|
228
|
+
@details = initialize_details({}, details)
|
203
229
|
self.view_paths = view_paths
|
204
|
-
initialize_details(details)
|
205
230
|
end
|
206
231
|
|
232
|
+
def digest_cache
|
233
|
+
details_key
|
234
|
+
end
|
235
|
+
|
236
|
+
def initialize_details(target, details)
|
237
|
+
registered_details.each do |k|
|
238
|
+
target[k] = details[k] || Accessors::DEFAULT_PROCS[k].call
|
239
|
+
end
|
240
|
+
target
|
241
|
+
end
|
242
|
+
private :initialize_details
|
243
|
+
|
207
244
|
# Override formats= to expand ["*/*"] values and automatically
|
208
245
|
# add :html as fallback to :js.
|
209
246
|
def formats=(values)
|
210
247
|
if values
|
211
|
-
values.concat(default_formats) if values.delete "*/*"
|
248
|
+
values.concat(default_formats) if values.delete "*/*".freeze
|
212
249
|
if values == [:js]
|
213
250
|
values << :html
|
214
251
|
@html_fallback_for_js = true
|
@@ -217,12 +254,6 @@ module ActionView
|
|
217
254
|
super(values)
|
218
255
|
end
|
219
256
|
|
220
|
-
# Do not use the default locale on template lookup.
|
221
|
-
def skip_default_locale!
|
222
|
-
@skip_default_locale = true
|
223
|
-
self.locale = nil
|
224
|
-
end
|
225
|
-
|
226
257
|
# Override locale to return a symbol instead of array.
|
227
258
|
def locale
|
228
259
|
@details[:locale].first
|
@@ -237,23 +268,7 @@ module ActionView
|
|
237
268
|
config.locale = value
|
238
269
|
end
|
239
270
|
|
240
|
-
super(
|
241
|
-
end
|
242
|
-
|
243
|
-
# Uses the first format in the formats array for layout lookup.
|
244
|
-
def with_layout_format
|
245
|
-
if formats.size == 1
|
246
|
-
yield
|
247
|
-
else
|
248
|
-
old_formats = formats
|
249
|
-
_set_detail(:formats, formats[0,1])
|
250
|
-
|
251
|
-
begin
|
252
|
-
yield
|
253
|
-
ensure
|
254
|
-
_set_detail(:formats, old_formats)
|
255
|
-
end
|
256
|
-
end
|
271
|
+
super(default_locale)
|
257
272
|
end
|
258
273
|
end
|
259
274
|
end
|
data/lib/action_view/path_set.rb
CHANGED
@@ -58,32 +58,41 @@ module ActionView #:nodoc:
|
|
58
58
|
find_all(path, prefixes, *args).any?
|
59
59
|
end
|
60
60
|
|
61
|
+
def find_all_with_query(query) # :nodoc:
|
62
|
+
paths.each do |resolver|
|
63
|
+
templates = resolver.find_all_with_query(query)
|
64
|
+
return templates unless templates.empty?
|
65
|
+
end
|
66
|
+
|
67
|
+
[]
|
68
|
+
end
|
69
|
+
|
61
70
|
private
|
62
71
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
72
|
+
def _find_all(path, prefixes, args, outside_app)
|
73
|
+
prefixes = [prefixes] if String === prefixes
|
74
|
+
prefixes.each do |prefix|
|
75
|
+
paths.each do |resolver|
|
76
|
+
if outside_app
|
77
|
+
templates = resolver.find_all_anywhere(path, prefix, *args)
|
78
|
+
else
|
79
|
+
templates = resolver.find_all(path, prefix, *args)
|
80
|
+
end
|
81
|
+
return templates unless templates.empty?
|
71
82
|
end
|
72
|
-
return templates unless templates.empty?
|
73
83
|
end
|
84
|
+
[]
|
74
85
|
end
|
75
|
-
[]
|
76
|
-
end
|
77
86
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
87
|
+
def typecast(paths)
|
88
|
+
paths.map do |path|
|
89
|
+
case path
|
90
|
+
when Pathname, String
|
91
|
+
OptimizedFileSystemResolver.new path.to_s
|
92
|
+
else
|
93
|
+
path
|
94
|
+
end
|
85
95
|
end
|
86
96
|
end
|
87
|
-
end
|
88
97
|
end
|
89
98
|
end
|
data/lib/action_view/railtie.rb
CHANGED
@@ -3,9 +3,10 @@ require "rails"
|
|
3
3
|
|
4
4
|
module ActionView
|
5
5
|
# = Action View Railtie
|
6
|
-
class Railtie < Rails::
|
6
|
+
class Railtie < Rails::Engine # :nodoc:
|
7
7
|
config.action_view = ActiveSupport::OrderedOptions.new
|
8
|
-
config.action_view.embed_authenticity_token_in_remote_forms =
|
8
|
+
config.action_view.embed_authenticity_token_in_remote_forms = nil
|
9
|
+
config.action_view.debug_missing_translation = true
|
9
10
|
|
10
11
|
config.eager_load_namespaces << ActionView
|
11
12
|
|
@@ -16,13 +17,22 @@ module ActionView
|
|
16
17
|
end
|
17
18
|
end
|
18
19
|
|
20
|
+
initializer "action_view.form_with_generates_remote_forms" do |app|
|
21
|
+
ActiveSupport.on_load(:action_view) do
|
22
|
+
form_with_generates_remote_forms = app.config.action_view.delete(:form_with_generates_remote_forms)
|
23
|
+
unless form_with_generates_remote_forms.nil?
|
24
|
+
ActionView::Helpers::FormHelper.form_with_generates_remote_forms = form_with_generates_remote_forms
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
19
29
|
initializer "action_view.logger" do
|
20
30
|
ActiveSupport.on_load(:action_view) { self.logger ||= Rails.logger }
|
21
31
|
end
|
22
32
|
|
23
33
|
initializer "action_view.set_configs" do |app|
|
24
34
|
ActiveSupport.on_load(:action_view) do
|
25
|
-
app.config.action_view.each do |k,v|
|
35
|
+
app.config.action_view.each do |k, v|
|
26
36
|
send "#{k}=", v
|
27
37
|
end
|
28
38
|
end
|
@@ -36,14 +46,28 @@ module ActionView
|
|
36
46
|
end
|
37
47
|
end
|
38
48
|
|
49
|
+
initializer "action_view.per_request_digest_cache" do |app|
|
50
|
+
ActiveSupport.on_load(:action_view) do
|
51
|
+
unless ActionView::Resolver.caching?
|
52
|
+
app.executor.to_run ActionView::Digestor::PerExecutionDigestCacheExpiry
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
39
57
|
initializer "action_view.setup_action_pack" do |app|
|
40
58
|
ActiveSupport.on_load(:action_controller) do
|
41
|
-
ActionView::RoutingUrlFor.
|
59
|
+
ActionView::RoutingUrlFor.include(ActionDispatch::Routing::UrlFor)
|
42
60
|
end
|
43
61
|
end
|
44
62
|
|
45
|
-
|
46
|
-
|
63
|
+
initializer "action_view.collection_caching", after: "action_controller.set_configs" do |app|
|
64
|
+
PartialRenderer.collection_cache = app.config.action_controller.cache_store
|
65
|
+
end
|
66
|
+
|
67
|
+
rake_tasks do |app|
|
68
|
+
unless app.config.api_only
|
69
|
+
load "action_view/tasks/cache_digests.rake"
|
70
|
+
end
|
47
71
|
end
|
48
72
|
end
|
49
73
|
end
|
@@ -1,38 +1,64 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "active_support/core_ext/module"
|
2
|
+
require "action_view/model_naming"
|
3
3
|
|
4
4
|
module ActionView
|
5
|
-
#
|
6
|
-
#
|
7
|
-
# a higher logical level.
|
5
|
+
# RecordIdentifier encapsulates methods used by various ActionView helpers
|
6
|
+
# to associate records with DOM elements.
|
8
7
|
#
|
9
|
-
#
|
10
|
-
# resources :posts
|
8
|
+
# Consider for example the following code that form of post:
|
11
9
|
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
# <% end %> </div>
|
10
|
+
# <%= form_for(post) do |f| %>
|
11
|
+
# <%= f.text_field :body %>
|
12
|
+
# <% end %>
|
16
13
|
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
# post = Post.find(params[:id])
|
20
|
-
# post.update(params[:post])
|
14
|
+
# When +post+ is a new, unsaved ActiveRecord::Base instance, the resulting HTML
|
15
|
+
# is:
|
21
16
|
#
|
22
|
-
#
|
23
|
-
#
|
17
|
+
# <form class="new_post" id="new_post" action="/posts" accept-charset="UTF-8" method="post">
|
18
|
+
# <input type="text" name="post[body]" id="post_body" />
|
19
|
+
# </form>
|
20
|
+
#
|
21
|
+
# When +post+ is a persisted ActiveRecord::Base instance, the resulting HTML
|
22
|
+
# is:
|
23
|
+
#
|
24
|
+
# <form class="edit_post" id="edit_post_42" action="/posts/42" accept-charset="UTF-8" method="post">
|
25
|
+
# <input type="text" value="What a wonderful world!" name="post[body]" id="post_body" />
|
26
|
+
# </form>
|
27
|
+
#
|
28
|
+
# In both cases, the +id+ and +class+ of the wrapping DOM element are
|
29
|
+
# automatically generated, following naming conventions encapsulated by the
|
30
|
+
# RecordIdentifier methods #dom_id and #dom_class:
|
31
|
+
#
|
32
|
+
# dom_id(Post.new) # => "new_post"
|
33
|
+
# dom_class(Post.new) # => "post"
|
34
|
+
# dom_id(Post.find 42) # => "post_42"
|
35
|
+
# dom_class(Post.find 42) # => "post"
|
24
36
|
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
37
|
+
# Note that these methods do not strictly require +Post+ to be a subclass of
|
38
|
+
# ActiveRecord::Base.
|
39
|
+
# Any +Post+ class will work as long as its instances respond to +to_key+
|
40
|
+
# and +model_name+, given that +model_name+ responds to +param_key+.
|
41
|
+
# For instance:
|
42
|
+
#
|
43
|
+
# class Post
|
44
|
+
# attr_accessor :to_key
|
45
|
+
#
|
46
|
+
# def model_name
|
47
|
+
# OpenStruct.new param_key: 'post'
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# def self.find(id)
|
51
|
+
# new.tap { |post| post.to_key = [id] }
|
52
|
+
# end
|
53
|
+
# end
|
28
54
|
module RecordIdentifier
|
29
55
|
extend self
|
30
56
|
extend ModelNaming
|
31
57
|
|
32
58
|
include ModelNaming
|
33
59
|
|
34
|
-
JOIN =
|
35
|
-
NEW =
|
60
|
+
JOIN = "_".freeze
|
61
|
+
NEW = "new".freeze
|
36
62
|
|
37
63
|
# The DOM class convention is to use the singular form of an object or class.
|
38
64
|
#
|
@@ -66,7 +92,7 @@ module ActionView
|
|
66
92
|
end
|
67
93
|
end
|
68
94
|
|
69
|
-
|
95
|
+
private
|
70
96
|
|
71
97
|
# Returns a string representation of the key attribute(s) that is suitable for use in an HTML DOM id.
|
72
98
|
# This can be overwritten to customize the default generated string representation if desired.
|
@@ -76,9 +102,9 @@ module ActionView
|
|
76
102
|
# overwritten version of the method. By default, this implementation passes the key string through a
|
77
103
|
# method that replaces all characters that are invalid inside DOM ids, with valid ones. You need to
|
78
104
|
# make sure yourself that your dom ids are valid, in case you overwrite this method.
|
79
|
-
def record_key_for_dom_id(record)
|
105
|
+
def record_key_for_dom_id(record) # :doc:
|
80
106
|
key = convert_to_model(record).to_key
|
81
|
-
key ? key.join(
|
107
|
+
key ? key.join(JOIN) : key
|
82
108
|
end
|
83
109
|
end
|
84
110
|
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, :
|
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
|
@@ -25,25 +25,29 @@ module ActionView
|
|
25
25
|
raise NotImplementedError
|
26
26
|
end
|
27
27
|
|
28
|
-
|
28
|
+
private
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
30
|
+
def extract_details(options) # :doc:
|
31
|
+
@lookup_context.registered_details.each_with_object({}) do |key, details|
|
32
|
+
value = options[key]
|
33
33
|
|
34
|
-
|
34
|
+
details[key] = Array(value) if value
|
35
|
+
end
|
35
36
|
end
|
36
|
-
end
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
|
38
|
+
def instrument(name, **options) # :doc:
|
39
|
+
options[:identifier] ||= (@template && @template.identifier) || @path
|
40
|
+
|
41
|
+
ActiveSupport::Notifications.instrument("render_#{name}.action_view", options) do |payload|
|
42
|
+
yield payload
|
43
|
+
end
|
44
|
+
end
|
41
45
|
|
42
|
-
|
43
|
-
|
44
|
-
|
46
|
+
def prepend_formats(formats) # :doc:
|
47
|
+
formats = Array(formats)
|
48
|
+
return if formats.empty? || @lookup_context.html_fallback_for_js
|
45
49
|
|
46
|
-
|
47
|
-
|
50
|
+
@lookup_context.formats = formats | @lookup_context.formats
|
51
|
+
end
|
48
52
|
end
|
49
53
|
end
|