mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
66a7cfa910
The current code base is not uniform. After some discussion, we have chosen to go with double quotes by default.
153 lines
4.5 KiB
Ruby
153 lines
4.5 KiB
Ruby
require "active_support/core_ext/enumerable"
|
|
require "active_support/core_ext/regexp"
|
|
|
|
module ActionView
|
|
# = Action View Errors
|
|
class ActionViewError < StandardError #:nodoc:
|
|
end
|
|
|
|
class EncodingError < StandardError #:nodoc:
|
|
end
|
|
|
|
class MissingRequestError < StandardError #:nodoc:
|
|
end
|
|
|
|
class WrongEncodingError < EncodingError #:nodoc:
|
|
def initialize(string, encoding)
|
|
@string, @encoding = string, encoding
|
|
end
|
|
|
|
def message
|
|
@string.force_encoding(Encoding::ASCII_8BIT)
|
|
"Your template was not saved as valid #{@encoding}. Please " \
|
|
"either specify #{@encoding} as the encoding for your template " \
|
|
"in your text editor, or mark the template with its " \
|
|
"encoding by inserting the following as the first line " \
|
|
"of the template:\n\n# encoding: <name of correct encoding>.\n\n" \
|
|
"The source of your template was:\n\n#{@string}"
|
|
end
|
|
end
|
|
|
|
class MissingTemplate < ActionViewError #:nodoc:
|
|
attr_reader :path
|
|
|
|
def initialize(paths, path, prefixes, partial, details, *)
|
|
@path = path
|
|
prefixes = Array(prefixes)
|
|
template_type = if partial
|
|
"partial"
|
|
elsif /layouts/i.match?(path)
|
|
"layout"
|
|
else
|
|
"template"
|
|
end
|
|
|
|
if partial && path.present?
|
|
path = path.sub(%r{([^/]+)$}, "_\\1")
|
|
end
|
|
searched_paths = prefixes.map { |prefix| [prefix, path].join("/") }
|
|
|
|
out = "Missing #{template_type} #{searched_paths.join(", ")} with #{details.inspect}. Searched in:\n"
|
|
out += paths.compact.map { |p| " * #{p.to_s.inspect}\n" }.join
|
|
super out
|
|
end
|
|
end
|
|
|
|
class Template
|
|
# The Template::Error exception is raised when the compilation or rendering of the template
|
|
# fails. This exception then gathers a bunch of intimate details and uses it to report a
|
|
# precise exception message.
|
|
class Error < ActionViewError #:nodoc:
|
|
SOURCE_CODE_RADIUS = 3
|
|
|
|
# Override to prevent #cause resetting during re-raise.
|
|
attr_reader :cause
|
|
|
|
def initialize(template, original_exception = nil)
|
|
if original_exception
|
|
ActiveSupport::Deprecation.warn("Passing #original_exception is deprecated and has no effect. " \
|
|
"Exceptions will automatically capture the original exception.", caller)
|
|
end
|
|
|
|
super($!.message)
|
|
set_backtrace($!.backtrace)
|
|
@cause = $!
|
|
@template, @sub_templates = template, nil
|
|
end
|
|
|
|
def original_exception
|
|
ActiveSupport::Deprecation.warn("#original_exception is deprecated. Use #cause instead.", caller)
|
|
cause
|
|
end
|
|
|
|
def file_name
|
|
@template.identifier
|
|
end
|
|
|
|
def sub_template_message
|
|
if @sub_templates
|
|
"Trace of template inclusion: " +
|
|
@sub_templates.collect(&:inspect).join(", ")
|
|
else
|
|
""
|
|
end
|
|
end
|
|
|
|
def source_extract(indentation = 0, output = :console)
|
|
return unless num = line_number
|
|
num = num.to_i
|
|
|
|
source_code = @template.source.split("\n")
|
|
|
|
start_on_line = [ num - SOURCE_CODE_RADIUS - 1, 0 ].max
|
|
end_on_line = [ num + SOURCE_CODE_RADIUS - 1, source_code.length].min
|
|
|
|
indent = end_on_line.to_s.size + indentation
|
|
return unless source_code = source_code[start_on_line..end_on_line]
|
|
|
|
formatted_code_for(source_code, start_on_line, indent, output)
|
|
end
|
|
|
|
def sub_template_of(template_path)
|
|
@sub_templates ||= []
|
|
@sub_templates << template_path
|
|
end
|
|
|
|
def line_number
|
|
@line_number ||=
|
|
if file_name
|
|
regexp = /#{Regexp.escape File.basename(file_name)}:(\d+)/
|
|
$1 if message =~ regexp || backtrace.find { |line| line =~ regexp }
|
|
end
|
|
end
|
|
|
|
def annoted_source_code
|
|
source_extract(4)
|
|
end
|
|
|
|
private
|
|
|
|
def source_location
|
|
if line_number
|
|
"on line ##{line_number} of "
|
|
else
|
|
"in "
|
|
end + file_name
|
|
end
|
|
|
|
def formatted_code_for(source_code, line_counter, indent, output)
|
|
start_value = (output == :html) ? {} : []
|
|
source_code.inject(start_value) do |result, line|
|
|
line_counter += 1
|
|
if output == :html
|
|
result.update(line_counter.to_s => "%#{indent}s %s\n" % ["", line])
|
|
else
|
|
result << "%#{indent}s: %s" % [line_counter, line]
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
TemplateError = Template::Error
|
|
end
|