actionview 5.2.4.1 → 6.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of actionview might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +193 -79
- data/MIT-LICENSE +1 -1
- data/README.rdoc +4 -2
- data/lib/action_view.rb +3 -2
- data/lib/action_view/base.rb +107 -10
- data/lib/action_view/buffers.rb +15 -0
- data/lib/action_view/cache_expiry.rb +54 -0
- data/lib/action_view/context.rb +5 -9
- data/lib/action_view/digestor.rb +12 -20
- data/lib/action_view/gem_version.rb +4 -4
- data/lib/action_view/helpers.rb +0 -2
- data/lib/action_view/helpers/asset_tag_helper.rb +7 -30
- data/lib/action_view/helpers/asset_url_helper.rb +4 -3
- data/lib/action_view/helpers/cache_helper.rb +18 -10
- data/lib/action_view/helpers/capture_helper.rb +4 -0
- data/lib/action_view/helpers/csp_helper.rb +4 -2
- data/lib/action_view/helpers/csrf_helper.rb +1 -1
- data/lib/action_view/helpers/date_helper.rb +69 -25
- data/lib/action_view/helpers/form_helper.rb +238 -6
- data/lib/action_view/helpers/form_options_helper.rb +27 -18
- data/lib/action_view/helpers/form_tag_helper.rb +12 -9
- data/lib/action_view/helpers/javascript_helper.rb +9 -8
- data/lib/action_view/helpers/number_helper.rb +5 -0
- 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 +12 -18
- data/lib/action_view/helpers/tag_helper.rb +7 -6
- data/lib/action_view/helpers/tags/base.rb +9 -5
- data/lib/action_view/helpers/tags/color_field.rb +1 -1
- data/lib/action_view/helpers/tags/translator.rb +1 -6
- data/lib/action_view/helpers/text_helper.rb +3 -3
- data/lib/action_view/helpers/translation_helper.rb +16 -12
- data/lib/action_view/helpers/url_helper.rb +14 -14
- data/lib/action_view/layouts.rb +5 -5
- data/lib/action_view/log_subscriber.rb +6 -6
- data/lib/action_view/lookup_context.rb +73 -31
- data/lib/action_view/path_set.rb +5 -10
- data/lib/action_view/railtie.rb +24 -1
- data/lib/action_view/record_identifier.rb +2 -2
- 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 +62 -16
- data/lib/action_view/renderer/renderer.rb +16 -4
- data/lib/action_view/renderer/streaming_template_renderer.rb +5 -5
- data/lib/action_view/renderer/template_renderer.rb +24 -18
- data/lib/action_view/rendering.rb +51 -31
- data/lib/action_view/routing_url_for.rb +12 -11
- data/lib/action_view/template.rb +102 -70
- 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 +17 -7
- 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 +136 -133
- 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/test_case.rb +1 -1
- 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 +29 -3
- metadata +25 -17
- data/lib/action_view/helpers/record_tag_helper.rb +0 -23
| @@ -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,47 +42,59 @@ 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.
         | 
| 65 82 | 
             
                #
         | 
| 66 83 | 
             
                # The view class must have the following methods:
         | 
| 67 | 
            -
                # | 
| 68 | 
            -
                # | 
| 69 | 
            -
                #  | 
| 70 | 
            -
                # | 
| 84 | 
            +
                #
         | 
| 85 | 
            +
                # * <tt>View.new(lookup_context, assigns, controller)</tt> — Create a new
         | 
| 86 | 
            +
                #   ActionView instance for a controller and we can also pass the arguments.
         | 
| 87 | 
            +
                #
         | 
| 88 | 
            +
                # * <tt>View#render(option)</tt> — Returns String with the rendered template.
         | 
| 71 89 | 
             
                #
         | 
| 72 90 | 
             
                # Override this method in a module to change the default behavior.
         | 
| 73 91 | 
             
                def view_context
         | 
| 74 | 
            -
                  view_context_class.new( | 
| 92 | 
            +
                  view_context_class.new(lookup_context, view_assigns, self)
         | 
| 75 93 | 
             
                end
         | 
| 76 94 |  | 
| 77 95 | 
             
                # Returns an object that is able to render templates.
         | 
| 78 96 | 
             
                def view_renderer # :nodoc:
         | 
| 97 | 
            +
                  # Lifespan: Per controller
         | 
| 79 98 | 
             
                  @_view_renderer ||= ActionView::Renderer.new(lookup_context)
         | 
| 80 99 | 
             
                end
         | 
| 81 100 |  | 
| @@ -84,10 +103,6 @@ module ActionView | |
| 84 103 | 
             
                  _render_template(options)
         | 
| 85 104 | 
             
                end
         | 
| 86 105 |  | 
| 87 | 
            -
                def rendered_format
         | 
| 88 | 
            -
                  Template::Types[lookup_context.rendered_format]
         | 
| 89 | 
            -
                end
         | 
| 90 | 
            -
             | 
| 91 106 | 
             
                private
         | 
| 92 107 |  | 
| 93 108 | 
             
                  # Find and render a template based on the options given.
         | 
| @@ -97,17 +112,22 @@ module ActionView | |
| 97 112 | 
             
                    context = view_context
         | 
| 98 113 |  | 
| 99 114 | 
             
                    context.assign assigns if assigns
         | 
| 100 | 
            -
                    lookup_context.rendered_format = nil if options[:formats]
         | 
| 101 115 | 
             
                    lookup_context.variants = variant if variant
         | 
| 102 116 |  | 
| 103 | 
            -
                     | 
| 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
         | 
| 104 125 | 
             
                  end
         | 
| 105 126 |  | 
| 106 127 | 
             
                  # Assign the rendered format to look up context.
         | 
| 107 128 | 
             
                  def _process_format(format)
         | 
| 108 129 | 
             
                    super
         | 
| 109 | 
            -
                    lookup_context.formats = [format.to_sym]
         | 
| 110 | 
            -
                    lookup_context.rendered_format = lookup_context.formats.first
         | 
| 130 | 
            +
                    lookup_context.formats = [format.to_sym] if format.to_sym
         | 
| 111 131 | 
             
                  end
         | 
| 112 132 |  | 
| 113 133 | 
             
                  # Normalize args by converting render "foo" to render :action => "foo" and
         | 
| @@ -84,25 +84,24 @@ module ActionView | |
| 84 84 | 
             
                    super(only_path: _generate_paths_by_default)
         | 
| 85 85 | 
             
                  when Hash
         | 
| 86 86 | 
             
                    options = options.symbolize_keys
         | 
| 87 | 
            -
                     | 
| 88 | 
            -
                      options[:only_path] = only_path?(options[:host])
         | 
| 89 | 
            -
                    end
         | 
| 87 | 
            +
                    ensure_only_path_option(options)
         | 
| 90 88 |  | 
| 91 89 | 
             
                    super(options)
         | 
| 92 90 | 
             
                  when ActionController::Parameters
         | 
| 93 | 
            -
                     | 
| 94 | 
            -
                      options[:only_path] = only_path?(options[:host])
         | 
| 95 | 
            -
                    end
         | 
| 91 | 
            +
                    ensure_only_path_option(options)
         | 
| 96 92 |  | 
| 97 93 | 
             
                    super(options)
         | 
| 98 94 | 
             
                  when :back
         | 
| 99 95 | 
             
                    _back_url
         | 
| 100 96 | 
             
                  when Array
         | 
| 101 97 | 
             
                    components = options.dup
         | 
| 102 | 
            -
                     | 
| 103 | 
            -
             | 
| 98 | 
            +
                    options = components.extract_options!
         | 
| 99 | 
            +
                    ensure_only_path_option(options)
         | 
| 100 | 
            +
             | 
| 101 | 
            +
                    if options[:only_path]
         | 
| 102 | 
            +
                      polymorphic_path(components, options)
         | 
| 104 103 | 
             
                    else
         | 
| 105 | 
            -
                      polymorphic_url(components,  | 
| 104 | 
            +
                      polymorphic_url(components, options)
         | 
| 106 105 | 
             
                    end
         | 
| 107 106 | 
             
                  else
         | 
| 108 107 | 
             
                    method = _generate_paths_by_default ? :path : :url
         | 
| @@ -138,8 +137,10 @@ module ActionView | |
| 138 137 | 
             
                    true
         | 
| 139 138 | 
             
                  end
         | 
| 140 139 |  | 
| 141 | 
            -
                  def  | 
| 142 | 
            -
                     | 
| 140 | 
            +
                  def ensure_only_path_option(options)
         | 
| 141 | 
            +
                    unless options.key?(:only_path)
         | 
| 142 | 
            +
                      options[:only_path] = _generate_paths_by_default unless options[:host]
         | 
| 143 | 
            +
                    end
         | 
| 143 144 | 
             
                  end
         | 
| 144 145 | 
             
              end
         | 
| 145 146 | 
             
            end
         | 
    
        data/lib/action_view/template.rb
    CHANGED
    
    | @@ -2,13 +2,23 @@ | |
| 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 |  | 
| 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
         | 
| 21 | 
            +
             | 
| 12 22 | 
             
                # === Encodings in ActionView::Template
         | 
| 13 23 | 
             
                #
         | 
| 14 24 | 
             
                # ActionView::Template is one of a few sources of potential
         | 
| @@ -103,44 +113,60 @@ module ActionView | |
| 103 113 |  | 
| 104 114 | 
             
                eager_autoload do
         | 
| 105 115 | 
             
                  autoload :Error
         | 
| 116 | 
            +
                  autoload :RawFile
         | 
| 106 117 | 
             
                  autoload :Handlers
         | 
| 107 118 | 
             
                  autoload :HTML
         | 
| 119 | 
            +
                  autoload :Inline
         | 
| 120 | 
            +
                  autoload :Sources
         | 
| 108 121 | 
             
                  autoload :Text
         | 
| 109 122 | 
             
                  autoload :Types
         | 
| 110 123 | 
             
                end
         | 
| 111 124 |  | 
| 112 125 | 
             
                extend Template::Handlers
         | 
| 113 126 |  | 
| 114 | 
            -
                 | 
| 127 | 
            +
                attr_reader :identifier, :handler, :original_encoding, :updated_at
         | 
| 128 | 
            +
                attr_reader :variable, :format, :variant, :locals, :virtual_path
         | 
| 115 129 |  | 
| 116 | 
            -
                 | 
| 117 | 
            -
             | 
| 118 | 
            -
             | 
| 119 | 
            -
             | 
| 120 | 
            -
                Finalizer = proc do |method_name, mod| # :nodoc:
         | 
| 121 | 
            -
                  proc do
         | 
| 122 | 
            -
                    mod.module_eval do
         | 
| 123 | 
            -
                      remove_possible_method method_name
         | 
| 124 | 
            -
                    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 = []
         | 
| 125 134 | 
             
                  end
         | 
| 126 | 
            -
                end
         | 
| 127 | 
            -
             | 
| 128 | 
            -
                def initialize(source, identifier, handler, details)
         | 
| 129 | 
            -
                  format = details[:format] || (handler.default_format if handler.respond_to?(:default_format))
         | 
| 130 135 |  | 
| 131 136 | 
             
                  @source            = source
         | 
| 132 137 | 
             
                  @identifier        = identifier
         | 
| 133 138 | 
             
                  @handler           = handler
         | 
| 134 139 | 
             
                  @compiled          = false
         | 
| 135 | 
            -
                  @ | 
| 136 | 
            -
                  @ | 
| 137 | 
            -
             | 
| 138 | 
            -
                  @ | 
| 139 | 
            -
             | 
| 140 | 
            -
             | 
| 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
         | 
| 141 157 | 
             
                  @compile_mutex     = Mutex.new
         | 
| 142 158 | 
             
                end
         | 
| 143 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 | 
            +
             | 
| 144 170 | 
             
                # Returns whether the underlying handler supports streaming. If so,
         | 
| 145 171 | 
             
                # a streaming buffer *may* be passed when it starts rendering.
         | 
| 146 172 | 
             
                def supports_streaming?
         | 
| @@ -153,40 +179,29 @@ module ActionView | |
| 153 179 | 
             
                # This method is instrumented as "!render_template.action_view". Notice that
         | 
| 154 180 | 
             
                # we use a bang in this instrumentation because you don't want to
         | 
| 155 181 | 
             
                # consume this in production. This is only slow if it's being listened to.
         | 
| 156 | 
            -
                def render(view, locals, buffer =  | 
| 182 | 
            +
                def render(view, locals, buffer = ActionView::OutputBuffer.new, &block)
         | 
| 157 183 | 
             
                  instrument_render_template do
         | 
| 158 184 | 
             
                    compile!(view)
         | 
| 159 | 
            -
                    view. | 
| 185 | 
            +
                    view._run(method_name, self, locals, buffer, &block)
         | 
| 160 186 | 
             
                  end
         | 
| 161 187 | 
             
                rescue => e
         | 
| 162 188 | 
             
                  handle_render_error(view, e)
         | 
| 163 189 | 
             
                end
         | 
| 164 190 |  | 
| 165 191 | 
             
                def type
         | 
| 166 | 
            -
                  @type ||= Types[ | 
| 192 | 
            +
                  @type ||= Types[format]
         | 
| 167 193 | 
             
                end
         | 
| 168 194 |  | 
| 169 | 
            -
                 | 
| 170 | 
            -
             | 
| 171 | 
            -
                # This method is useful if you have a template object but it does not contain its source
         | 
| 172 | 
            -
                # anymore since it was already compiled. In such cases, all you need to do is to call
         | 
| 173 | 
            -
                # refresh passing in the view object.
         | 
| 174 | 
            -
                #
         | 
| 175 | 
            -
                # Notice this method raises an error if the template to be refreshed does not have a
         | 
| 176 | 
            -
                # virtual path set (true just for inline templates).
         | 
| 177 | 
            -
                def refresh(view)
         | 
| 178 | 
            -
                  raise "A template needs to have a virtual path in order to be refreshed" unless @virtual_path
         | 
| 179 | 
            -
                  lookup  = view.lookup_context
         | 
| 180 | 
            -
                  pieces  = @virtual_path.split("/")
         | 
| 181 | 
            -
                  name    = pieces.pop
         | 
| 182 | 
            -
                  partial = !!name.sub!(/^_/, "")
         | 
| 183 | 
            -
                  lookup.disable_cache do
         | 
| 184 | 
            -
                    lookup.find_template(name, [ pieces.join("/") ], partial, @locals)
         | 
| 185 | 
            -
                  end
         | 
| 195 | 
            +
                def short_identifier
         | 
| 196 | 
            +
                  @short_identifier ||= defined?(Rails.root) ? identifier.sub("#{Rails.root}/", "") : identifier
         | 
| 186 197 | 
             
                end
         | 
| 187 198 |  | 
| 188 199 | 
             
                def inspect
         | 
| 189 | 
            -
                   | 
| 200 | 
            +
                  "#<#{self.class.name} #{short_identifier} locals=#{@locals.inspect}>"
         | 
| 201 | 
            +
                end
         | 
| 202 | 
            +
             | 
| 203 | 
            +
                def source
         | 
| 204 | 
            +
                  @source.to_s
         | 
| 190 205 | 
             
                end
         | 
| 191 206 |  | 
| 192 207 | 
             
                # This method is responsible for properly setting the encoding of the
         | 
| @@ -200,7 +215,9 @@ module ActionView | |
| 200 215 | 
             
                # before passing the source on to the template engine, leaving a
         | 
| 201 216 | 
             
                # blank line in its stead.
         | 
| 202 217 | 
             
                def encode!
         | 
| 203 | 
            -
                   | 
| 218 | 
            +
                  source = self.source
         | 
| 219 | 
            +
             | 
| 220 | 
            +
                  return source unless source.encoding == Encoding::BINARY
         | 
| 204 221 |  | 
| 205 222 | 
             
                  # Look for # encoding: *. If we find one, we'll encode the
         | 
| 206 223 | 
             
                  # String in that encoding, otherwise, we'll use the
         | 
| @@ -233,6 +250,19 @@ module ActionView | |
| 233 250 | 
             
                  end
         | 
| 234 251 | 
             
                end
         | 
| 235 252 |  | 
| 253 | 
            +
             | 
| 254 | 
            +
                # Exceptions are marshalled when using the parallel test runner with DRb, so we need
         | 
| 255 | 
            +
                # to ensure that references to the template object can be marshalled as well. This means forgoing
         | 
| 256 | 
            +
                # the marshalling of the compiler mutex and instantiating that again on unmarshalling.
         | 
| 257 | 
            +
                def marshal_dump # :nodoc:
         | 
| 258 | 
            +
                  [ @source, @identifier, @handler, @compiled, @locals, @virtual_path, @updated_at, @format, @variant ]
         | 
| 259 | 
            +
                end
         | 
| 260 | 
            +
             | 
| 261 | 
            +
                def marshal_load(array) # :nodoc:
         | 
| 262 | 
            +
                  @source, @identifier, @handler, @compiled, @locals, @virtual_path, @updated_at, @format, @variant = *array
         | 
| 263 | 
            +
                  @compile_mutex = Mutex.new
         | 
| 264 | 
            +
                end
         | 
| 265 | 
            +
             | 
| 236 266 | 
             
                private
         | 
| 237 267 |  | 
| 238 268 | 
             
                  # Compile a template. This method ensures a template is compiled
         | 
| @@ -249,23 +279,25 @@ module ActionView | |
| 249 279 | 
             
                      # re-compilation
         | 
| 250 280 | 
             
                      return if @compiled
         | 
| 251 281 |  | 
| 252 | 
            -
                       | 
| 253 | 
            -
                        mod = ActionView::CompiledTemplates
         | 
| 254 | 
            -
                      else
         | 
| 255 | 
            -
                        mod = view.singleton_class
         | 
| 256 | 
            -
                      end
         | 
| 282 | 
            +
                      mod = view.compiled_method_container
         | 
| 257 283 |  | 
| 258 284 | 
             
                      instrument("!compile_template") do
         | 
| 259 285 | 
             
                        compile(mod)
         | 
| 260 286 | 
             
                      end
         | 
| 261 287 |  | 
| 262 | 
            -
                      # Just discard the source if we have a virtual path. This
         | 
| 263 | 
            -
                      # means we can get the template back.
         | 
| 264 | 
            -
                      @source = nil if @virtual_path
         | 
| 265 288 | 
             
                      @compiled = true
         | 
| 266 289 | 
             
                    end
         | 
| 267 290 | 
             
                  end
         | 
| 268 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 | 
            +
             | 
| 269 301 | 
             
                  # Among other things, this method is responsible for properly setting
         | 
| 270 302 | 
             
                  # the encoding of the compiled template.
         | 
| 271 303 | 
             
                  #
         | 
| @@ -279,16 +311,15 @@ module ActionView | |
| 279 311 | 
             
                  # In general, this means that templates will be UTF-8 inside of Rails,
         | 
| 280 312 | 
             
                  # regardless of the original source encoding.
         | 
| 281 313 | 
             
                  def compile(mod)
         | 
| 282 | 
            -
                    encode!
         | 
| 283 | 
            -
                    code = @handler.call(self)
         | 
| 314 | 
            +
                    source = encode!
         | 
| 315 | 
            +
                    code = @handler.call(self, source)
         | 
| 284 316 |  | 
| 285 317 | 
             
                    # Make sure that the resulting String to be eval'd is in the
         | 
| 286 318 | 
             
                    # encoding of the code
         | 
| 287 | 
            -
                     | 
| 319 | 
            +
                    original_source = source
         | 
| 320 | 
            +
                    source = +<<-end_src
         | 
| 288 321 | 
             
                      def #{method_name}(local_assigns, output_buffer)
         | 
| 289 | 
            -
                         | 
| 290 | 
            -
                      ensure
         | 
| 291 | 
            -
                        @virtual_path, @output_buffer = _old_virtual_path, _old_output_buffer
         | 
| 322 | 
            +
                        @virtual_path = #{@virtual_path.inspect};#{locals_code};#{code}
         | 
| 292 323 | 
             
                      end
         | 
| 293 324 | 
             
                    end_src
         | 
| 294 325 |  | 
| @@ -303,11 +334,17 @@ module ActionView | |
| 303 334 | 
             
                    # handler is valid in the default_internal. This is for handlers
         | 
| 304 335 | 
             
                    # that handle encoding but screw up
         | 
| 305 336 | 
             
                    unless source.valid_encoding?
         | 
| 306 | 
            -
                      raise WrongEncodingError.new( | 
| 337 | 
            +
                      raise WrongEncodingError.new(source, Encoding.default_internal)
         | 
| 307 338 | 
             
                    end
         | 
| 308 339 |  | 
| 309 | 
            -
                     | 
| 310 | 
            -
             | 
| 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)
         | 
| 347 | 
            +
                    end
         | 
| 311 348 | 
             
                  end
         | 
| 312 349 |  | 
| 313 350 | 
             
                  def handle_render_error(view, e)
         | 
| @@ -315,12 +352,7 @@ module ActionView | |
| 315 352 | 
             
                      e.sub_template_of(self)
         | 
| 316 353 | 
             
                      raise e
         | 
| 317 354 | 
             
                    else
         | 
| 318 | 
            -
                       | 
| 319 | 
            -
                      unless template.source
         | 
| 320 | 
            -
                        template = refresh(view)
         | 
| 321 | 
            -
                        template.encode!
         | 
| 322 | 
            -
                      end
         | 
| 323 | 
            -
                      raise Template::Error.new(template)
         | 
| 355 | 
            +
                      raise Template::Error.new(self)
         | 
| 324 356 | 
             
                    end
         | 
| 325 357 | 
             
                  end
         | 
| 326 358 |  | 
| @@ -331,19 +363,19 @@ module ActionView | |
| 331 363 | 
             
                    locals = locals.grep(/\A@?(?![A-Z0-9])(?:[[:alnum:]_]|[^\0-\177])+\z/)
         | 
| 332 364 |  | 
| 333 365 | 
             
                    # Assign for the same variable is to suppress unused variable warning
         | 
| 334 | 
            -
                    locals.each_with_object("" | 
| 366 | 
            +
                    locals.each_with_object(+"") { |key, code| code << "#{key} = local_assigns[:#{key}]; #{key} = #{key};" }
         | 
| 335 367 | 
             
                  end
         | 
| 336 368 |  | 
| 337 369 | 
             
                  def method_name
         | 
| 338 370 | 
             
                    @method_name ||= begin
         | 
| 339 | 
            -
                      m = "_#{identifier_method_name}__#{@identifier.hash}_#{__id__}" | 
| 340 | 
            -
                      m.tr!("-" | 
| 371 | 
            +
                      m = +"_#{identifier_method_name}__#{@identifier.hash}_#{__id__}"
         | 
| 372 | 
            +
                      m.tr!("-", "_")
         | 
| 341 373 | 
             
                      m
         | 
| 342 374 | 
             
                    end
         | 
| 343 375 | 
             
                  end
         | 
| 344 376 |  | 
| 345 377 | 
             
                  def identifier_method_name
         | 
| 346 | 
            -
                     | 
| 378 | 
            +
                    short_identifier.tr("^a-z_", "_")
         | 
| 347 379 | 
             
                  end
         | 
| 348 380 |  | 
| 349 381 | 
             
                  def instrument(action, &block) # :doc:
         | 
| @@ -351,7 +383,7 @@ module ActionView | |
| 351 383 | 
             
                  end
         | 
| 352 384 |  | 
| 353 385 | 
             
                  def instrument_render_template(&block)
         | 
| 354 | 
            -
                    ActiveSupport::Notifications.instrument("!render_template.action_view" | 
| 386 | 
            +
                    ActiveSupport::Notifications.instrument("!render_template.action_view", instrument_payload, &block)
         | 
| 355 387 | 
             
                  end
         | 
| 356 388 |  | 
| 357 389 | 
             
                  def instrument_payload
         |