instance method compile

Ruby on Rails 3.0.20

Since v3.0.20 Private

Available in: v3.0.20 v5.2.8.1 v6.0.6 v6.1.7.10 v7.0.10 v7.1.6 v7.2.3 v8.0.4 v8.1.2

Signature

compile(locals, view, mod)

Among other things, this method is responsible for properly setting the encoding of the source. Until this point, we assume that the source is BINARY data. If no additional information is supplied, we assume the encoding is the same as Encoding.default_external.

The user can also specify the encoding via a comment on the first line of the template (# encoding: NAME-OF-ENCODING). This will work with any template engine, as we process out the encoding comment before passing the source on to the template engine, leaving a blank line in its stead.

If the template engine handles encodings, we send the encoded String to the engine without further processing. This allows the template engine to support additional mechanisms for specifying the encoding. For instance, ERB supports <%# encoding: %>

Otherwise, after we figure out the correct encoding, we then encode the source into Encoding.default_internal. In general, this means that templates will be UTF-8 inside of Rails, regardless of the original source encoding.

Parameters

locals req
view req
mod req
Source
# File actionpack/lib/action_view/template.rb, line 188
      def compile(locals, view, mod)
        method_name = build_method_name(locals)
        return method_name if view.respond_to?(method_name)

        locals_code = locals.keys.map! { |key| "#{key} = local_assigns[:#{key}];" }.join

        if source.encoding_aware?
          # Avoid performing in-place mutation for SafeBuffer
          @source = source.to_str if source.html_safe?

          # Look for # encoding: *. If we find one, we'll encode the
          # String in that encoding, otherwise, we'll use the
          # default external encoding.
          if source.sub!(/\A#{ENCODING_FLAG}/, '')
            encoding = magic_encoding = $1
          else
            encoding = Encoding.default_external
          end

          # Tag the source with the default external encoding
          # or the encoding specified in the file
          source.force_encoding(encoding)

          # If the user didn't specify an encoding, and the handler
          # handles encodings, we simply pass the String as is to
          # the handler (with the default_external tag)
          if !magic_encoding && @handler.respond_to?(:handles_encoding?) && @handler.handles_encoding?
            source
          # Otherwise, if the String is valid in the encoding,
          # encode immediately to default_internal. This means
          # that if a handler doesn't handle encodings, it will
          # always get Strings in the default_internal
          elsif source.valid_encoding?
            source.encode!
          # Otherwise, since the String is invalid in the encoding
          # specified, raise an exception
          else
            raise WrongEncodingError.new(source, encoding)
          end
        end

        code = @handler.call(self)

        # Make sure that the resulting String to be evalled is in the
        # encoding of the code
        source = <<-end_src
          def #{method_name}(local_assigns)
            _old_virtual_path, @_virtual_path = @_virtual_path, #{@virtual_path.inspect};_old_output_buffer = @output_buffer;#{locals_code};#{code}
          ensure
            @_virtual_path, @output_buffer = _old_virtual_path, _old_output_buffer
          end
        end_src

        if source.encoding_aware?
          # Make sure the source is in the encoding of the returned code
          source.force_encoding(code.encoding)

          # In case we get back a String from a handler that is not in
          # BINARY or the default_internal, encode it to the default_internal
          source.encode!

          # Now, validate that the source we got back from the template
          # handler is valid in the default_internal. This is for handlers
          # that handle encoding but screw up
          unless source.valid_encoding?
            raise WrongEncodingError.new(@source, Encoding.default_internal)
          end
        end

        begin
          mod.module_eval(source, identifier, 0)
          ObjectSpace.define_finalizer(self, Finalizer[method_name, mod])

          method_name
        rescue Exception => e # errors from template code
          if logger = (view && view.logger)
            logger.debug "ERROR: compiling #{method_name} RAISED #{e}"
            logger.debug "Function body: #{source}"
            logger.debug "Backtrace: #{e.backtrace.join("\n")}"
          end

          raise ActionView::Template::Error.new(self, {}, e)
        end
      end

Defined in actionpack/lib/action_view/template.rb line 188 · View on GitHub · Improve this page · Find usages on GitHub

Defined in ActionView::Template

Type at least 2 characters to search.

↑↓ navigate · open · esc close