actionview 6.0.0.beta1 → 6.0.1.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 +90 -3
- data/README.rdoc +3 -1
- data/lib/action_view.rb +2 -1
- data/lib/action_view/base.rb +107 -10
- data/lib/action_view/cache_expiry.rb +54 -0
- data/lib/action_view/context.rb +0 -5
- data/lib/action_view/digestor.rb +8 -17
- data/lib/action_view/gem_version.rb +2 -2
- data/lib/action_view/helpers/asset_tag_helper.rb +5 -5
- data/lib/action_view/helpers/cache_helper.rb +5 -5
- data/lib/action_view/helpers/csp_helper.rb +4 -2
- data/lib/action_view/helpers/form_helper.rb +2 -2
- data/lib/action_view/helpers/form_options_helper.rb +4 -3
- data/lib/action_view/helpers/form_tag_helper.rb +5 -2
- data/lib/action_view/helpers/output_safety_helper.rb +1 -1
- data/lib/action_view/helpers/rendering_helper.rb +6 -4
- data/lib/action_view/helpers/sanitize_helper.rb +10 -16
- data/lib/action_view/helpers/tag_helper.rb +1 -1
- data/lib/action_view/helpers/tags/base.rb +1 -1
- data/lib/action_view/helpers/translation_helper.rb +3 -3
- data/lib/action_view/helpers/url_helper.rb +2 -2
- data/lib/action_view/layouts.rb +5 -5
- data/lib/action_view/lookup_context.rb +69 -27
- data/lib/action_view/path_set.rb +5 -10
- data/lib/action_view/railtie.rb +9 -4
- data/lib/action_view/renderer/abstract_renderer.rb +56 -3
- data/lib/action_view/renderer/partial_renderer.rb +66 -55
- data/lib/action_view/renderer/partial_renderer/collection_caching.rb +27 -20
- data/lib/action_view/renderer/renderer.rb +16 -4
- data/lib/action_view/renderer/streaming_template_renderer.rb +4 -4
- data/lib/action_view/renderer/template_renderer.rb +24 -18
- data/lib/action_view/rendering.rb +46 -27
- data/lib/action_view/template.rb +84 -69
- data/lib/action_view/template/error.rb +21 -1
- data/lib/action_view/template/handlers.rb +27 -1
- data/lib/action_view/template/handlers/builder.rb +2 -2
- data/lib/action_view/template/handlers/erb.rb +5 -5
- data/lib/action_view/template/handlers/erb/erubi.rb +7 -3
- data/lib/action_view/template/handlers/html.rb +1 -1
- data/lib/action_view/template/handlers/raw.rb +2 -2
- data/lib/action_view/template/html.rb +14 -5
- data/lib/action_view/template/inline.rb +22 -0
- data/lib/action_view/template/raw_file.rb +28 -0
- data/lib/action_view/template/resolver.rb +80 -117
- data/lib/action_view/template/sources.rb +13 -0
- data/lib/action_view/template/sources/file.rb +17 -0
- data/lib/action_view/template/text.rb +5 -3
- data/lib/action_view/testing/resolvers.rb +33 -20
- data/lib/action_view/unbound_template.rb +32 -0
- data/lib/action_view/view_paths.rb +25 -1
- data/lib/assets/compiled/rails-ujs.js +21 -12
- metadata +25 -16
@@ -19,10 +19,14 @@ module ActionView
|
|
19
19
|
|
20
20
|
# Main render entry point shared by Action View and Action Controller.
|
21
21
|
def render(context, options)
|
22
|
+
render_to_object(context, options).body
|
23
|
+
end
|
24
|
+
|
25
|
+
def render_to_object(context, options) # :nodoc:
|
22
26
|
if options.key?(:partial)
|
23
|
-
|
27
|
+
render_partial_to_object(context, options)
|
24
28
|
else
|
25
|
-
|
29
|
+
render_template_to_object(context, options)
|
26
30
|
end
|
27
31
|
end
|
28
32
|
|
@@ -41,16 +45,24 @@ module ActionView
|
|
41
45
|
|
42
46
|
# Direct access to template rendering.
|
43
47
|
def render_template(context, options) #:nodoc:
|
44
|
-
|
48
|
+
render_template_to_object(context, options).body
|
45
49
|
end
|
46
50
|
|
47
51
|
# Direct access to partial rendering.
|
48
52
|
def render_partial(context, options, &block) #:nodoc:
|
49
|
-
|
53
|
+
render_partial_to_object(context, options, &block).body
|
50
54
|
end
|
51
55
|
|
52
56
|
def cache_hits # :nodoc:
|
53
57
|
@cache_hits ||= {}
|
54
58
|
end
|
59
|
+
|
60
|
+
def render_template_to_object(context, options) #:nodoc:
|
61
|
+
TemplateRenderer.new(@lookup_context).render(context, options)
|
62
|
+
end
|
63
|
+
|
64
|
+
def render_partial_to_object(context, options, &block) #:nodoc:
|
65
|
+
PartialRenderer.new(@lookup_context).render(context, options, block)
|
66
|
+
end
|
55
67
|
end
|
56
68
|
end
|
@@ -34,7 +34,7 @@ module ActionView
|
|
34
34
|
return unless logger
|
35
35
|
|
36
36
|
message = +"\n#{exception.class} (#{exception.message}):\n"
|
37
|
-
message << exception.
|
37
|
+
message << exception.annotated_source_code.to_s if exception.respond_to?(:annotated_source_code)
|
38
38
|
message << " " << exception.backtrace.join("\n ")
|
39
39
|
logger.fatal("#{message}\n\n")
|
40
40
|
end
|
@@ -43,14 +43,14 @@ module ActionView
|
|
43
43
|
# For streaming, instead of rendering a given a template, we return a Body
|
44
44
|
# object that responds to each. This object is initialized with a block
|
45
45
|
# that knows how to render the template.
|
46
|
-
def render_template(template, layout_name = nil, locals = {}) #:nodoc:
|
47
|
-
return [super] unless layout_name && template.supports_streaming?
|
46
|
+
def render_template(view, template, layout_name = nil, locals = {}) #:nodoc:
|
47
|
+
return [super.body] unless layout_name && template.supports_streaming?
|
48
48
|
|
49
49
|
locals ||= {}
|
50
50
|
layout = layout_name && find_layout(layout_name, locals.keys, [formats.first])
|
51
51
|
|
52
52
|
Body.new do |buffer|
|
53
|
-
delayed_render(buffer, template, layout,
|
53
|
+
delayed_render(buffer, template, layout, view, locals)
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
@@ -5,15 +5,12 @@ require "active_support/core_ext/object/try"
|
|
5
5
|
module ActionView
|
6
6
|
class TemplateRenderer < AbstractRenderer #:nodoc:
|
7
7
|
def render(context, options)
|
8
|
-
@view = context
|
9
8
|
@details = extract_details(options)
|
10
9
|
template = determine_template(options)
|
11
10
|
|
12
|
-
prepend_formats(template.
|
11
|
+
prepend_formats(template.format)
|
13
12
|
|
14
|
-
|
15
|
-
|
16
|
-
render_template(template, options[:layout], options[:locals])
|
13
|
+
render_template(context, template, options[:layout], options[:locals] || {})
|
17
14
|
end
|
18
15
|
|
19
16
|
private
|
@@ -29,15 +26,25 @@ module ActionView
|
|
29
26
|
elsif options.key?(:html)
|
30
27
|
Template::HTML.new(options[:html], formats.first)
|
31
28
|
elsif options.key?(:file)
|
32
|
-
|
29
|
+
if File.exist?(options[:file])
|
30
|
+
Template::RawFile.new(options[:file])
|
31
|
+
else
|
32
|
+
ActiveSupport::Deprecation.warn "render file: should be given the absolute path to a file"
|
33
|
+
@lookup_context.with_fallbacks.find_template(options[:file], nil, false, keys, @details)
|
34
|
+
end
|
33
35
|
elsif options.key?(:inline)
|
34
36
|
handler = Template.handler_for_extension(options[:type] || "erb")
|
35
|
-
|
37
|
+
format = if handler.respond_to?(:default_format)
|
38
|
+
handler.default_format
|
39
|
+
else
|
40
|
+
@lookup_context.formats.first
|
41
|
+
end
|
42
|
+
Template::Inline.new(options[:inline], "inline template", handler, locals: keys, format: format)
|
36
43
|
elsif options.key?(:template)
|
37
44
|
if options[:template].respond_to?(:render)
|
38
45
|
options[:template]
|
39
46
|
else
|
40
|
-
find_template(options[:template], options[:prefixes], false, keys, @details)
|
47
|
+
@lookup_context.find_template(options[:template], options[:prefixes], false, keys, @details)
|
41
48
|
end
|
42
49
|
else
|
43
50
|
raise ArgumentError, "You invoked render but did not give any of :partial, :template, :inline, :file, :plain, :html or :body option."
|
@@ -46,27 +53,25 @@ module ActionView
|
|
46
53
|
|
47
54
|
# Renders the given template. A string representing the layout can be
|
48
55
|
# supplied as well.
|
49
|
-
def render_template(template, layout_name
|
50
|
-
view,
|
51
|
-
|
52
|
-
render_with_layout(layout_name, locals) do |layout|
|
56
|
+
def render_template(view, template, layout_name, locals)
|
57
|
+
render_with_layout(view, template, layout_name, locals) do |layout|
|
53
58
|
instrument(:template, identifier: template.identifier, layout: layout.try(:virtual_path)) do
|
54
59
|
template.render(view, locals) { |*name| view._layout_for(*name) }
|
55
60
|
end
|
56
61
|
end
|
57
62
|
end
|
58
63
|
|
59
|
-
def render_with_layout(path, locals)
|
64
|
+
def render_with_layout(view, template, path, locals)
|
60
65
|
layout = path && find_layout(path, locals.keys, [formats.first])
|
61
66
|
content = yield(layout)
|
62
67
|
|
63
|
-
if layout
|
64
|
-
view = @view
|
68
|
+
body = if layout
|
65
69
|
view.view_flow.set(:layout, content)
|
66
70
|
layout.render(view, locals) { |*name| view._layout_for(*name) }
|
67
71
|
else
|
68
72
|
content
|
69
73
|
end
|
74
|
+
build_rendered_template(body, template, layout)
|
70
75
|
end
|
71
76
|
|
72
77
|
# This is the method which actually finds the layout using details in the lookup
|
@@ -84,16 +89,17 @@ module ActionView
|
|
84
89
|
when String
|
85
90
|
begin
|
86
91
|
if layout.start_with?("/")
|
87
|
-
|
92
|
+
ActiveSupport::Deprecation.warn "Rendering layouts from an absolute path is deprecated."
|
93
|
+
@lookup_context.with_fallbacks.find_template(layout, nil, false, [], details)
|
88
94
|
else
|
89
|
-
find_template(layout, nil, false, [], details)
|
95
|
+
@lookup_context.find_template(layout, nil, false, [], details)
|
90
96
|
end
|
91
97
|
rescue ActionView::MissingTemplate
|
92
98
|
all_details = @details.merge(formats: @lookup_context.default_formats)
|
93
99
|
raise unless template_exists?(layout, nil, false, [], all_details)
|
94
100
|
end
|
95
101
|
when Proc
|
96
|
-
resolve_layout(layout.call(formats), keys, formats)
|
102
|
+
resolve_layout(layout.call(@lookup_context, formats), keys, formats)
|
97
103
|
else
|
98
104
|
layout
|
99
105
|
end
|
@@ -26,6 +26,13 @@ module ActionView
|
|
26
26
|
extend ActiveSupport::Concern
|
27
27
|
include ActionView::ViewPaths
|
28
28
|
|
29
|
+
attr_reader :rendered_format
|
30
|
+
|
31
|
+
def initialize
|
32
|
+
@rendered_format = nil
|
33
|
+
super
|
34
|
+
end
|
35
|
+
|
29
36
|
# Overwrite process to setup I18n proxy.
|
30
37
|
def process(*) #:nodoc:
|
31
38
|
old_config, I18n.config = I18n.config, I18nProxy.new(I18n.config, lookup_context)
|
@@ -35,30 +42,40 @@ module ActionView
|
|
35
42
|
end
|
36
43
|
|
37
44
|
module ClassMethods
|
38
|
-
def
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
45
|
+
def _routes
|
46
|
+
end
|
47
|
+
|
48
|
+
def _helpers
|
49
|
+
end
|
50
|
+
|
51
|
+
def build_view_context_class(klass, supports_path, routes, helpers)
|
52
|
+
Class.new(klass) do
|
53
|
+
if routes
|
54
|
+
include routes.url_helpers(supports_path)
|
55
|
+
include routes.mounted_helpers
|
56
|
+
end
|
57
|
+
|
58
|
+
if helpers
|
59
|
+
include helpers
|
53
60
|
end
|
54
61
|
end
|
55
62
|
end
|
56
|
-
end
|
57
63
|
|
58
|
-
|
64
|
+
def view_context_class
|
65
|
+
klass = ActionView::LookupContext::DetailsKey.view_context_class(ActionView::Base)
|
66
|
+
|
67
|
+
@view_context_class ||= build_view_context_class(klass, supports_path?, _routes, _helpers)
|
68
|
+
|
69
|
+
if klass.changed?(@view_context_class)
|
70
|
+
@view_context_class = build_view_context_class(klass, supports_path?, _routes, _helpers)
|
71
|
+
end
|
72
|
+
|
73
|
+
@view_context_class
|
74
|
+
end
|
75
|
+
end
|
59
76
|
|
60
77
|
def view_context_class
|
61
|
-
|
78
|
+
self.class.view_context_class
|
62
79
|
end
|
63
80
|
|
64
81
|
# An instance of a view class. The default view class is ActionView::Base.
|
@@ -72,11 +89,12 @@ module ActionView
|
|
72
89
|
#
|
73
90
|
# Override this method in a module to change the default behavior.
|
74
91
|
def view_context
|
75
|
-
view_context_class.new(
|
92
|
+
view_context_class.new(lookup_context, view_assigns, self)
|
76
93
|
end
|
77
94
|
|
78
95
|
# Returns an object that is able to render templates.
|
79
96
|
def view_renderer # :nodoc:
|
97
|
+
# Lifespan: Per controller
|
80
98
|
@_view_renderer ||= ActionView::Renderer.new(lookup_context)
|
81
99
|
end
|
82
100
|
|
@@ -85,10 +103,6 @@ module ActionView
|
|
85
103
|
_render_template(options)
|
86
104
|
end
|
87
105
|
|
88
|
-
def rendered_format
|
89
|
-
Template::Types[lookup_context.rendered_format]
|
90
|
-
end
|
91
|
-
|
92
106
|
private
|
93
107
|
|
94
108
|
# Find and render a template based on the options given.
|
@@ -98,17 +112,22 @@ module ActionView
|
|
98
112
|
context = view_context
|
99
113
|
|
100
114
|
context.assign assigns if assigns
|
101
|
-
lookup_context.rendered_format = nil if options[:formats]
|
102
115
|
lookup_context.variants = variant if variant
|
103
116
|
|
104
|
-
|
117
|
+
rendered_template = context.in_rendering_context(options) do |renderer|
|
118
|
+
renderer.render_to_object(context, options)
|
119
|
+
end
|
120
|
+
|
121
|
+
rendered_format = rendered_template.format || lookup_context.formats.first
|
122
|
+
@rendered_format = Template::Types[rendered_format]
|
123
|
+
|
124
|
+
rendered_template.body
|
105
125
|
end
|
106
126
|
|
107
127
|
# Assign the rendered format to look up context.
|
108
128
|
def _process_format(format)
|
109
129
|
super
|
110
|
-
lookup_context.formats = [format.to_sym]
|
111
|
-
lookup_context.rendered_format = lookup_context.formats.first
|
130
|
+
lookup_context.formats = [format.to_sym] if format.to_sym
|
112
131
|
end
|
113
132
|
|
114
133
|
# Normalize args by converting render "foo" to render :action => "foo" and
|
data/lib/action_view/template.rb
CHANGED
@@ -2,14 +2,22 @@
|
|
2
2
|
|
3
3
|
require "active_support/core_ext/object/try"
|
4
4
|
require "active_support/core_ext/kernel/singleton_class"
|
5
|
+
require "active_support/deprecation"
|
5
6
|
require "thread"
|
7
|
+
require "delegate"
|
6
8
|
|
7
9
|
module ActionView
|
8
10
|
# = Action View Template
|
9
11
|
class Template
|
10
12
|
extend ActiveSupport::Autoload
|
11
13
|
|
12
|
-
|
14
|
+
def self.finalize_compiled_template_methods
|
15
|
+
ActiveSupport::Deprecation.warn "ActionView::Template.finalize_compiled_template_methods is deprecated and has no effect"
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.finalize_compiled_template_methods=(_)
|
19
|
+
ActiveSupport::Deprecation.warn "ActionView::Template.finalize_compiled_template_methods= is deprecated and has no effect"
|
20
|
+
end
|
13
21
|
|
14
22
|
# === Encodings in ActionView::Template
|
15
23
|
#
|
@@ -105,44 +113,60 @@ module ActionView
|
|
105
113
|
|
106
114
|
eager_autoload do
|
107
115
|
autoload :Error
|
116
|
+
autoload :RawFile
|
108
117
|
autoload :Handlers
|
109
118
|
autoload :HTML
|
119
|
+
autoload :Inline
|
120
|
+
autoload :Sources
|
110
121
|
autoload :Text
|
111
122
|
autoload :Types
|
112
123
|
end
|
113
124
|
|
114
125
|
extend Template::Handlers
|
115
126
|
|
116
|
-
|
117
|
-
|
118
|
-
attr_reader :source, :identifier, :handler, :original_encoding, :updated_at
|
127
|
+
attr_reader :identifier, :handler, :original_encoding, :updated_at
|
128
|
+
attr_reader :variable, :format, :variant, :locals, :virtual_path
|
119
129
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
mod.module_eval do
|
125
|
-
remove_possible_method method_name
|
126
|
-
end
|
130
|
+
def initialize(source, identifier, handler, format: nil, variant: nil, locals: nil, virtual_path: nil, updated_at: nil)
|
131
|
+
unless locals
|
132
|
+
ActiveSupport::Deprecation.warn "ActionView::Template#initialize requires a locals parameter"
|
133
|
+
locals = []
|
127
134
|
end
|
128
|
-
end
|
129
|
-
|
130
|
-
def initialize(source, identifier, handler, details)
|
131
|
-
format = details[:format] || (handler.default_format if handler.respond_to?(:default_format))
|
132
135
|
|
133
136
|
@source = source
|
134
137
|
@identifier = identifier
|
135
138
|
@handler = handler
|
136
139
|
@compiled = false
|
137
|
-
@
|
138
|
-
@
|
139
|
-
|
140
|
-
@
|
141
|
-
|
142
|
-
|
140
|
+
@locals = locals
|
141
|
+
@virtual_path = virtual_path
|
142
|
+
|
143
|
+
@variable = if @virtual_path
|
144
|
+
base = @virtual_path[-1] == "/" ? "" : ::File.basename(@virtual_path)
|
145
|
+
base =~ /\A_?(.*?)(?:\.\w+)*\z/
|
146
|
+
$1.to_sym
|
147
|
+
end
|
148
|
+
|
149
|
+
if updated_at
|
150
|
+
ActiveSupport::Deprecation.warn "ActionView::Template#updated_at is deprecated"
|
151
|
+
@updated_at = updated_at
|
152
|
+
else
|
153
|
+
@updated_at = Time.now
|
154
|
+
end
|
155
|
+
@format = format
|
156
|
+
@variant = variant
|
143
157
|
@compile_mutex = Mutex.new
|
144
158
|
end
|
145
159
|
|
160
|
+
deprecate :original_encoding
|
161
|
+
deprecate :updated_at
|
162
|
+
deprecate def virtual_path=(_); end
|
163
|
+
deprecate def locals=(_); end
|
164
|
+
deprecate def formats=(_); end
|
165
|
+
deprecate def formats; Array(format); end
|
166
|
+
deprecate def variants=(_); end
|
167
|
+
deprecate def variants; [variant]; end
|
168
|
+
deprecate def refresh(_); self; end
|
169
|
+
|
146
170
|
# Returns whether the underlying handler supports streaming. If so,
|
147
171
|
# a streaming buffer *may* be passed when it starts rendering.
|
148
172
|
def supports_streaming?
|
@@ -155,40 +179,29 @@ module ActionView
|
|
155
179
|
# This method is instrumented as "!render_template.action_view". Notice that
|
156
180
|
# we use a bang in this instrumentation because you don't want to
|
157
181
|
# consume this in production. This is only slow if it's being listened to.
|
158
|
-
def render(view, locals, buffer =
|
182
|
+
def render(view, locals, buffer = ActionView::OutputBuffer.new, &block)
|
159
183
|
instrument_render_template do
|
160
184
|
compile!(view)
|
161
|
-
view.
|
185
|
+
view._run(method_name, self, locals, buffer, &block)
|
162
186
|
end
|
163
187
|
rescue => e
|
164
188
|
handle_render_error(view, e)
|
165
189
|
end
|
166
190
|
|
167
191
|
def type
|
168
|
-
@type ||= Types[
|
192
|
+
@type ||= Types[format]
|
169
193
|
end
|
170
194
|
|
171
|
-
|
172
|
-
|
173
|
-
# This method is useful if you have a template object but it does not contain its source
|
174
|
-
# anymore since it was already compiled. In such cases, all you need to do is to call
|
175
|
-
# refresh passing in the view object.
|
176
|
-
#
|
177
|
-
# Notice this method raises an error if the template to be refreshed does not have a
|
178
|
-
# virtual path set (true just for inline templates).
|
179
|
-
def refresh(view)
|
180
|
-
raise "A template needs to have a virtual path in order to be refreshed" unless @virtual_path
|
181
|
-
lookup = view.lookup_context
|
182
|
-
pieces = @virtual_path.split("/")
|
183
|
-
name = pieces.pop
|
184
|
-
partial = !!name.sub!(/^_/, "")
|
185
|
-
lookup.disable_cache do
|
186
|
-
lookup.find_template(name, [ pieces.join("/") ], partial, @locals)
|
187
|
-
end
|
195
|
+
def short_identifier
|
196
|
+
@short_identifier ||= defined?(Rails.root) ? identifier.sub("#{Rails.root}/", "") : identifier
|
188
197
|
end
|
189
198
|
|
190
199
|
def inspect
|
191
|
-
|
200
|
+
"#<#{self.class.name} #{short_identifier} locals=#{@locals.inspect}>"
|
201
|
+
end
|
202
|
+
|
203
|
+
def source
|
204
|
+
@source.to_s
|
192
205
|
end
|
193
206
|
|
194
207
|
# This method is responsible for properly setting the encoding of the
|
@@ -202,7 +215,9 @@ module ActionView
|
|
202
215
|
# before passing the source on to the template engine, leaving a
|
203
216
|
# blank line in its stead.
|
204
217
|
def encode!
|
205
|
-
|
218
|
+
source = self.source
|
219
|
+
|
220
|
+
return source unless source.encoding == Encoding::BINARY
|
206
221
|
|
207
222
|
# Look for # encoding: *. If we find one, we'll encode the
|
208
223
|
# String in that encoding, otherwise, we'll use the
|
@@ -240,11 +255,11 @@ module ActionView
|
|
240
255
|
# to ensure that references to the template object can be marshalled as well. This means forgoing
|
241
256
|
# the marshalling of the compiler mutex and instantiating that again on unmarshalling.
|
242
257
|
def marshal_dump # :nodoc:
|
243
|
-
[ @source, @identifier, @handler, @compiled, @
|
258
|
+
[ @source, @identifier, @handler, @compiled, @locals, @virtual_path, @updated_at, @format, @variant ]
|
244
259
|
end
|
245
260
|
|
246
261
|
def marshal_load(array) # :nodoc:
|
247
|
-
@source, @identifier, @handler, @compiled, @
|
262
|
+
@source, @identifier, @handler, @compiled, @locals, @virtual_path, @updated_at, @format, @variant = *array
|
248
263
|
@compile_mutex = Mutex.new
|
249
264
|
end
|
250
265
|
|
@@ -264,23 +279,25 @@ module ActionView
|
|
264
279
|
# re-compilation
|
265
280
|
return if @compiled
|
266
281
|
|
267
|
-
|
268
|
-
mod = ActionView::CompiledTemplates
|
269
|
-
else
|
270
|
-
mod = view.singleton_class
|
271
|
-
end
|
282
|
+
mod = view.compiled_method_container
|
272
283
|
|
273
284
|
instrument("!compile_template") do
|
274
285
|
compile(mod)
|
275
286
|
end
|
276
287
|
|
277
|
-
# Just discard the source if we have a virtual path. This
|
278
|
-
# means we can get the template back.
|
279
|
-
@source = nil if @virtual_path
|
280
288
|
@compiled = true
|
281
289
|
end
|
282
290
|
end
|
283
291
|
|
292
|
+
class LegacyTemplate < DelegateClass(Template) # :nodoc:
|
293
|
+
attr_reader :source
|
294
|
+
|
295
|
+
def initialize(template, source)
|
296
|
+
super(template)
|
297
|
+
@source = source
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
284
301
|
# Among other things, this method is responsible for properly setting
|
285
302
|
# the encoding of the compiled template.
|
286
303
|
#
|
@@ -294,16 +311,15 @@ module ActionView
|
|
294
311
|
# In general, this means that templates will be UTF-8 inside of Rails,
|
295
312
|
# regardless of the original source encoding.
|
296
313
|
def compile(mod)
|
297
|
-
encode!
|
298
|
-
code = @handler.call(self)
|
314
|
+
source = encode!
|
315
|
+
code = @handler.call(self, source)
|
299
316
|
|
300
317
|
# Make sure that the resulting String to be eval'd is in the
|
301
318
|
# encoding of the code
|
319
|
+
original_source = source
|
302
320
|
source = +<<-end_src
|
303
321
|
def #{method_name}(local_assigns, output_buffer)
|
304
|
-
|
305
|
-
ensure
|
306
|
-
@virtual_path, @output_buffer = _old_virtual_path, _old_output_buffer
|
322
|
+
@virtual_path = #{@virtual_path.inspect};#{locals_code};#{code}
|
307
323
|
end
|
308
324
|
end_src
|
309
325
|
|
@@ -318,12 +334,16 @@ module ActionView
|
|
318
334
|
# handler is valid in the default_internal. This is for handlers
|
319
335
|
# that handle encoding but screw up
|
320
336
|
unless source.valid_encoding?
|
321
|
-
raise WrongEncodingError.new(
|
337
|
+
raise WrongEncodingError.new(source, Encoding.default_internal)
|
322
338
|
end
|
323
339
|
|
324
|
-
|
325
|
-
|
326
|
-
|
340
|
+
begin
|
341
|
+
mod.module_eval(source, identifier, 0)
|
342
|
+
rescue SyntaxError
|
343
|
+
# Account for when code in the template is not syntactically valid; e.g. if we're using
|
344
|
+
# ERB and the user writes <%= foo( %>, attempting to call a helper `foo` and interpolate
|
345
|
+
# the result into the template, but missing an end parenthesis.
|
346
|
+
raise SyntaxErrorInTemplate.new(self, original_source)
|
327
347
|
end
|
328
348
|
end
|
329
349
|
|
@@ -332,12 +352,7 @@ module ActionView
|
|
332
352
|
e.sub_template_of(self)
|
333
353
|
raise e
|
334
354
|
else
|
335
|
-
|
336
|
-
unless template.source
|
337
|
-
template = refresh(view)
|
338
|
-
template.encode!
|
339
|
-
end
|
340
|
-
raise Template::Error.new(template)
|
355
|
+
raise Template::Error.new(self)
|
341
356
|
end
|
342
357
|
end
|
343
358
|
|
@@ -360,7 +375,7 @@ module ActionView
|
|
360
375
|
end
|
361
376
|
|
362
377
|
def identifier_method_name
|
363
|
-
|
378
|
+
short_identifier.tr("^a-z_", "_")
|
364
379
|
end
|
365
380
|
|
366
381
|
def instrument(action, &block) # :doc:
|