Froze rails gems
[depot.git] / vendor / rails / actionpack / lib / action_view / template_error.rb
1 module ActionView
2 # The TemplateError exception is raised when the compilation of the template fails. This exception then gathers a
3 # bunch of intimate details and uses it to report a very precise exception message.
4 class TemplateError < ActionViewError #:nodoc:
5 SOURCE_CODE_RADIUS = 3
6
7 attr_reader :original_exception
8
9 def initialize(template, assigns, original_exception)
10 @template, @assigns, @original_exception = template, assigns.dup, original_exception
11 @backtrace = compute_backtrace
12 end
13
14 def file_name
15 @template.relative_path
16 end
17
18 def message
19 ActiveSupport::Deprecation.silence { original_exception.message }
20 end
21
22 def clean_backtrace
23 original_exception.clean_backtrace
24 end
25
26 def sub_template_message
27 if @sub_templates
28 "Trace of template inclusion: " +
29 @sub_templates.collect { |template| template.relative_path }.join(", ")
30 else
31 ""
32 end
33 end
34
35 def source_extract(indentation = 0)
36 return unless num = line_number
37 num = num.to_i
38
39 source_code = @template.source.split("\n")
40
41 start_on_line = [ num - SOURCE_CODE_RADIUS - 1, 0 ].max
42 end_on_line = [ num + SOURCE_CODE_RADIUS - 1, source_code.length].min
43
44 indent = ' ' * indentation
45 line_counter = start_on_line
46 return unless source_code = source_code[start_on_line..end_on_line]
47
48 source_code.sum do |line|
49 line_counter += 1
50 "#{indent}#{line_counter}: #{line}\n"
51 end
52 end
53
54 def sub_template_of(template_path)
55 @sub_templates ||= []
56 @sub_templates << template_path
57 end
58
59 def line_number
60 @line_number ||=
61 if file_name
62 regexp = /#{Regexp.escape File.basename(file_name)}:(\d+)/
63
64 $1 if message =~ regexp or clean_backtrace.find { |line| line =~ regexp }
65 end
66 end
67
68 def to_s
69 "\n\n#{self.class} (#{message}) #{source_location}:\n" +
70 "#{source_extract}\n #{clean_backtrace.join("\n ")}\n\n"
71 end
72
73 # don't do anything nontrivial here. Any raised exception from here becomes fatal
74 # (and can't be rescued).
75 def backtrace
76 @backtrace
77 end
78
79 private
80 def compute_backtrace
81 [
82 "#{source_location.capitalize}\n\n#{source_extract(4)}\n " +
83 clean_backtrace.join("\n ")
84 ]
85 end
86
87 def source_location
88 if line_number
89 "on line ##{line_number} of "
90 else
91 'in '
92 end + file_name
93 end
94 end
95 end
96
97 if defined?(Exception::TraceSubstitutions)
98 Exception::TraceSubstitutions << [/:in\s+`_run_.*'\s*$/, '']
99 Exception::TraceSubstitutions << [%r{^\s*#{Regexp.escape RAILS_ROOT}/}, ''] if defined?(RAILS_ROOT)
100 end