diff options
Diffstat (limited to 'actionpack/lib/action_dispatch/middleware/templates')
25 files changed, 600 insertions, 116 deletions
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb deleted file mode 100644 index 823f5d25b6..0000000000 --- a/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +++ /dev/null @@ -1,31 +0,0 @@ -<% unless @exception.blamed_files.blank? %> - <% if (hide = @exception.blamed_files.length > 8) %> - <a href="#" onclick="document.getElementById('blame_trace').style.display='block'; return false;">Show blamed files</a> - <% end %> - <pre id="blame_trace" <%='style="display:none"' if hide %>><code><%=h @exception.describe_blame %></code></pre> -<% end %> - -<% - clean_params = @request.filtered_parameters.clone - clean_params.delete("action") - clean_params.delete("controller") - - request_dump = clean_params.empty? ? 'None' : clean_params.inspect.gsub(',', ",\n") - - def debug_hash(object) - object.to_hash.sort_by { |k, v| k.to_s }.map { |k, v| "#{k}: #{v.inspect rescue $!.message}" }.join("\n") - end unless self.class.method_defined?(:debug_hash) -%> - -<h2 style="margin-top: 30px">Request</h2> -<p><b>Parameters</b>: <pre><%=h request_dump %></pre></p> - -<p><a href="#" onclick="document.getElementById('session_dump').style.display='block'; return false;">Show session dump</a></p> -<div id="session_dump" style="display:none"><pre><%= debug_hash @request.session %></pre></div> - -<p><a href="#" onclick="document.getElementById('env_dump').style.display='block'; return false;">Show env dump</a></p> -<div id="env_dump" style="display:none"><pre><%= debug_hash @request.env.slice(*@request.class::ENV_METHODS) %></pre></div> - - -<h2 style="margin-top: 30px">Response</h2> -<p><b>Headers</b>: <pre><%=h defined?(@response) ? @response.headers.inspect.gsub(',', ",\n") : 'None' %></pre></p> diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb new file mode 100644 index 0000000000..49b1e83551 --- /dev/null +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb @@ -0,0 +1,22 @@ +<% unless @exception.blamed_files.blank? %> + <% if (hide = @exception.blamed_files.length > 8) %> + <a href="#" onclick="return toggleTrace()">Toggle blamed files</a> + <% end %> + <pre id="blame_trace" <%='style="display:none"' if hide %>><code><%= @exception.describe_blame %></code></pre> +<% end %> + +<h2 style="margin-top: 30px">Request</h2> +<p><b>Parameters</b>:</p> <pre><%= debug_params(@request.filtered_parameters) %></pre> + +<div class="details"> + <div class="summary"><a href="#" onclick="return toggleSessionDump()">Toggle session dump</a></div> + <div id="session_dump" style="display:none"><pre><%= debug_hash @request.session %></pre></div> +</div> + +<div class="details"> + <div class="summary"><a href="#" onclick="return toggleEnvDump()">Toggle env dump</a></div> + <div id="env_dump" style="display:none"><pre><%= debug_hash @request.env.slice(*@request.class::ENV_METHODS) %></pre></div> +</div> + +<h2 style="margin-top: 30px">Response</h2> +<p><b>Headers</b>:</p> <pre><%= debug_headers(defined?(@response) ? @response.headers : {}) %></pre> diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb new file mode 100644 index 0000000000..396768ecee --- /dev/null +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb @@ -0,0 +1,23 @@ +<% + clean_params = @request.filtered_parameters.clone + clean_params.delete("action") + clean_params.delete("controller") + + request_dump = clean_params.empty? ? 'None' : clean_params.inspect.gsub(',', ",\n") + + def debug_hash(object) + object.to_hash.sort_by { |k, _| k.to_s }.map { |k, v| "#{k}: #{v.inspect rescue $!.message}" }.join("\n") + end unless self.class.method_defined?(:debug_hash) +%> + +Request parameters +<%= request_dump %> + +Session dump +<%= debug_hash @request.session %> + +Env dump +<%= debug_hash @request.env.slice(*@request.class::ENV_METHODS) %> + +Response headers +<%= defined?(@response) ? @response.headers.inspect.gsub(',', ",\n") : 'None' %> diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/_source.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/_source.erb new file mode 100644 index 0000000000..e7b913bbe4 --- /dev/null +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/_source.erb @@ -0,0 +1,27 @@ +<% @source_extracts.each_with_index do |source_extract, index| %> + <% if source_extract[:code] %> + <div class="source <%="hidden" if @show_source_idx != index%>" id="frame-source-<%=index%>"> + <div class="info"> + Extracted source (around line <strong>#<%= source_extract[:line_number] %></strong>): + </div> + <div class="data"> + <table cellpadding="0" cellspacing="0" class="lines"> + <tr> + <td> + <pre class="line_numbers"> + <% source_extract[:code].each_key do |line_number| %> +<span><%= line_number -%></span> + <% end %> + </pre> + </td> +<td width="100%"> +<pre> +<% source_extract[:code].each do |line, source| -%><div class="line<%= " active" if line == source_extract[:line_number] -%>"><%= source -%></div><% end -%> +</pre> +</td> + </tr> + </table> + </div> + </div> + <% end %> +<% end %> diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.erb deleted file mode 100644 index 8771b5fd6d..0000000000 --- a/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.erb +++ /dev/null @@ -1,26 +0,0 @@ -<% - traces = [ - ["Application Trace", @application_trace], - ["Framework Trace", @framework_trace], - ["Full Trace", @full_trace] - ] - names = traces.collect {|name, trace| name} -%> - -<p><code>Rails.root: <%= defined?(Rails) && Rails.respond_to?(:root) ? Rails.root : "unset" %></code></p> - -<div id="traces"> - <% names.each do |name| %> - <% - show = "document.getElementById('#{name.gsub(/\s/, '-')}').style.display='block';" - hide = (names - [name]).collect {|hide_name| "document.getElementById('#{hide_name.gsub(/\s/, '-')}').style.display='none';"} - %> - <a href="#" onclick="<%= hide.join %><%= show %>; return false;"><%= name %></a> <%= '|' unless names.last == name %> - <% end %> - - <% traces.each do |name, trace| %> - <div id="<%= name.gsub(/\s/, '-') %>" style="display: <%= (name == "Application Trace") ? 'block' : 'none' %>;"> - <pre><code><%=h trace.join "\n" %></code></pre> - </div> - <% end %> -</div> diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb new file mode 100644 index 0000000000..ab57b11c7d --- /dev/null +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb @@ -0,0 +1,52 @@ +<% names = @traces.keys %> + +<p><code>Rails.root: <%= defined?(Rails) && Rails.respond_to?(:root) ? Rails.root : "unset" %></code></p> + +<div id="traces"> + <% names.each do |name| %> + <% + show = "show('#{name.gsub(/\s/, '-')}');" + hide = (names - [name]).collect {|hide_name| "hide('#{hide_name.gsub(/\s/, '-')}');"} + %> + <a href="#" onclick="<%= hide.join %><%= show %>; return false;"><%= name %></a> <%= '|' unless names.last == name %> + <% end %> + + <% @traces.each do |name, trace| %> + <div id="<%= name.gsub(/\s/, '-') %>" style="display: <%= (name == @trace_to_show) ? 'block' : 'none' %>;"> + <pre><code><% trace.each do |frame| %><a class="trace-frames" data-frame-id="<%= frame[:id] %>" href="#"><%= frame[:trace] %></a><br><% end %></code></pre> + </div> + <% end %> + + <script type="text/javascript"> + var traceFrames = document.getElementsByClassName('trace-frames'); + var selectedFrame, currentSource = document.getElementById('frame-source-0'); + + // Add click listeners for all stack frames + for (var i = 0; i < traceFrames.length; i++) { + traceFrames[i].addEventListener('click', function(e) { + e.preventDefault(); + var target = e.target; + var frame_id = target.dataset.frameId; + + if (selectedFrame) { + selectedFrame.className = selectedFrame.className.replace("selected", ""); + } + + target.className += " selected"; + selectedFrame = target; + + // Change the extracted source code + changeSourceExtract(frame_id); + }); + + function changeSourceExtract(frame_id) { + var el = document.getElementById('frame-source-' + frame_id); + if (currentSource && el) { + currentSource.className += " hidden"; + el.className = el.className.replace(" hidden", ""); + currentSource = el; + } + } + } + </script> +</div> diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb new file mode 100644 index 0000000000..c0b53068f7 --- /dev/null +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb @@ -0,0 +1,9 @@ +Rails.root: <%= defined?(Rails) && Rails.respond_to?(:root) ? Rails.root : "unset" %> + +<% @traces.each do |name, trace| %> +<% if trace.any? %> +<%= name %> +<%= trace.map { |t| t[:trace] }.join("\n") %> + +<% end %> +<% end %> diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb deleted file mode 100644 index c5043c5e7b..0000000000 --- a/actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +++ /dev/null @@ -1,10 +0,0 @@ -<h1> - <%=h @exception.class.to_s %> - <% if @request.parameters['controller'] %> - in <%=h @request.parameters['controller'].camelize %>Controller<% if @request.parameters['action'] %>#<%=h @request.parameters['action'] %><% end %> - <% end %> -</h1> -<pre><%=h @exception.message %></pre> - -<%= render template: "rescues/_trace" %> -<%= render template: "rescues/_request_and_response" %> diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb new file mode 100644 index 0000000000..f154021ae6 --- /dev/null +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb @@ -0,0 +1,16 @@ +<header> + <h1> + <%= @exception.class.to_s %> + <% if @request.parameters['controller'] %> + in <%= @request.parameters['controller'].camelize %>Controller<% if @request.parameters['action'] %>#<%= @request.parameters['action'] %><% end %> + <% end %> + </h1> +</header> + +<div id="container"> + <h2><%= h @exception.message %></h2> + + <%= render template: "rescues/_source" %> + <%= render template: "rescues/_trace" %> + <%= render template: "rescues/_request_and_response" %> +</div> diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb new file mode 100644 index 0000000000..603de54b8b --- /dev/null +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb @@ -0,0 +1,9 @@ +<%= @exception.class.to_s %><% + if @request.parameters['controller'] +%> in <%= @request.parameters['controller'].camelize %>Controller<% if @request.parameters['action'] %>#<%= @request.parameters['action'] %><% end %> +<% end %> + +<%= @exception.message %> +<%= render template: "rescues/_source" %> +<%= render template: "rescues/_trace" %> +<%= render template: "rescues/_request_and_response" %> diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/layout.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/layout.erb index 1a308707d1..e0509f56f4 100644 --- a/actionpack/lib/action_dispatch/middleware/templates/rescues/layout.erb +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/layout.erb @@ -4,7 +4,11 @@ <meta charset="utf-8" /> <title>Action Controller: Exception caught</title> <style> - body { background-color: #fff; color: #333; } + body { + background-color: #FAFAFA; + color: #333; + margin: 0px; + } body, p, ol, ul, td { font-family: helvetica, verdana, arial, sans-serif; @@ -13,16 +17,140 @@ } pre { - background-color: #eee; - padding: 10px; font-size: 11px; white-space: pre-wrap; } - a { color: #000; } + pre.box { + border: 1px solid #EEE; + padding: 10px; + margin: 0px; + width: 958px; + } + + header { + color: #F0F0F0; + background: #C52F24; + padding: 0.5em 1.5em; + } + + h1 { + margin: 0.2em 0; + line-height: 1.1em; + font-size: 2em; + } + + h2 { + color: #C52F24; + line-height: 25px; + } + + .details { + border: 1px solid #D0D0D0; + border-radius: 4px; + margin: 1em 0px; + display: block; + width: 978px; + } + + .summary { + padding: 8px 15px; + border-bottom: 1px solid #D0D0D0; + display: block; + } + + .details pre { + margin: 5px; + border: none; + } + + #container { + box-sizing: border-box; + width: 100%; + padding: 0 1.5em; + } + + .source * { + margin: 0px; + padding: 0px; + } + + .source { + border: 1px solid #D9D9D9; + background: #ECECEC; + width: 978px; + } + + .source pre { + padding: 10px 0px; + border: none; + } + + .source .data { + font-size: 80%; + overflow: auto; + background-color: #FFF; + } + + .info { + padding: 0.5em; + } + + .source .data .line_numbers { + background-color: #ECECEC; + color: #AAA; + padding: 1em .5em; + border-right: 1px solid #DDD; + text-align: right; + } + + .line { + padding-left: 10px; + } + + .line:hover { + background-color: #F6F6F6; + } + + .line.active { + background-color: #FFCCCC; + } + + .hidden { + display: none; + } + + a { color: #980905; } a:visited { color: #666; } - a:hover { color: #fff; background-color:#000; } + a.trace-frames { color: #666; } + a:hover { color: #C52F24; } + a.trace-frames.selected { color: #C52F24 } + + <%= yield :style %> </style> + + <script> + var toggle = function(id) { + var s = document.getElementById(id).style; + s.display = s.display == 'none' ? 'block' : 'none'; + return false; + } + var show = function(id) { + document.getElementById(id).style.display = 'block'; + } + var hide = function(id) { + document.getElementById(id).style.display = 'none'; + } + var toggleTrace = function() { + return toggle('blame_trace'); + } + var toggleSessionDump = function() { + return toggle('session_dump'); + } + var toggleEnvDump = function() { + return toggle('env_dump'); + } + </script> </head> <body> diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/missing_template.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/missing_template.erb deleted file mode 100644 index dbfdf76947..0000000000 --- a/actionpack/lib/action_dispatch/middleware/templates/rescues/missing_template.erb +++ /dev/null @@ -1,2 +0,0 @@ -<h1>Template is missing</h1> -<p><%=h @exception.message %></p> diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb new file mode 100644 index 0000000000..2a65fd06ad --- /dev/null +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb @@ -0,0 +1,11 @@ +<header> + <h1>Template is missing</h1> +</header> + +<div id="container"> + <h2><%= h @exception.message %></h2> + + <%= render template: "rescues/_source" %> + <%= render template: "rescues/_trace" %> + <%= render template: "rescues/_request_and_response" %> +</div> diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/missing_template.text.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/missing_template.text.erb new file mode 100644 index 0000000000..ae62d9eb02 --- /dev/null +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/missing_template.text.erb @@ -0,0 +1,3 @@ +Template is missing + +<%= @exception.message %> diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/routing_error.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/routing_error.erb deleted file mode 100644 index a357a7ba11..0000000000 --- a/actionpack/lib/action_dispatch/middleware/templates/rescues/routing_error.erb +++ /dev/null @@ -1,23 +0,0 @@ -<h1>Routing Error</h1> -<p><pre><%=h @exception.message %></pre></p> -<% unless @exception.failures.empty? %> - <p> - <h2>Failure reasons:</h2> - <ol> - <% @exception.failures.each do |route, reason| %> - <li><code><%=h route.inspect.gsub('\\', '') %></code> failed because <%=h reason.downcase %></li> - <% end %> - </ol> - </p> -<% end %> -<%= render template: "rescues/_trace" %> - -<h2> - Routes -</h2> - -<p> - Routes match in priority from top to bottom -</p> - -<p><pre><%= @routes %></pre></p> diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb new file mode 100644 index 0000000000..55dd5ddc7b --- /dev/null +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb @@ -0,0 +1,32 @@ +<header> + <h1>Routing Error</h1> +</header> +<div id="container"> + <h2><%= h @exception.message %></h2> + <% unless @exception.failures.empty? %> + <p> + <h2>Failure reasons:</h2> + <ol> + <% @exception.failures.each do |route, reason| %> + <li><code><%= route.inspect.delete('\\') %></code> failed because <%= reason.downcase %></li> + <% end %> + </ol> + </p> + <% end %> + + <%= render template: "rescues/_trace" %> + + <% if @routes_inspector %> + <h2> + Routes + </h2> + + <p> + Routes match in priority from top to bottom + </p> + + <%= @routes_inspector.format(ActionDispatch::Routing::HtmlTableFormatter.new(self)) %> + <% end %> + + <%= render template: "rescues/_request_and_response" %> +</div> diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/routing_error.text.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/routing_error.text.erb new file mode 100644 index 0000000000..f6e4dac1f3 --- /dev/null +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/routing_error.text.erb @@ -0,0 +1,11 @@ +Routing Error + +<%= @exception.message %> +<% unless @exception.failures.empty? %> +Failure reasons: +<% @exception.failures.each do |route, reason| %> + - <%= route.inspect.delete('\\') %></code> failed because <%= reason.downcase %> +<% end %> +<% end %> + +<%= render template: "rescues/_trace", format: :text %> diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.erb deleted file mode 100644 index a1b377f68c..0000000000 --- a/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.erb +++ /dev/null @@ -1,17 +0,0 @@ -<h1> - <%=h @exception.original_exception.class.to_s %> in - <%=h @request.parameters["controller"].capitalize if @request.parameters["controller"]%>#<%=h @request.parameters["action"] %> -</h1> - -<p> - Showing <i><%=h @exception.file_name %></i> where line <b>#<%=h @exception.line_number %></b> raised: - <pre><code><%=h @exception.message %></code></pre> -</p> - -<p>Extracted source (around line <b>#<%=h @exception.line_number %></b>): -<pre><code><%=h @exception.source_extract %></code></pre></p> - -<p><%=h @exception.sub_template_message %></p> - -<%= render template: "rescues/_trace" %> -<%= render template: "rescues/_request_and_response" %> diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb new file mode 100644 index 0000000000..c1e8b6cae3 --- /dev/null +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb @@ -0,0 +1,20 @@ +<header> + <h1> + <%= @exception.original_exception.class.to_s %> in + <%= @request.parameters["controller"].camelize if @request.parameters["controller"] %>#<%= @request.parameters["action"] %> + </h1> +</header> + +<div id="container"> + <p> + Showing <i><%= @exception.file_name %></i> where line <b>#<%= @exception.line_number %></b> raised: + </p> + <pre><code><%= h @exception.message %></code></pre> + + <%= render template: "rescues/_source" %> + + <p><%= @exception.sub_template_message %></p> + + <%= render template: "rescues/_trace" %> + <%= render template: "rescues/_request_and_response" %> +</div> diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb new file mode 100644 index 0000000000..77bcd26726 --- /dev/null +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb @@ -0,0 +1,7 @@ +<%= @exception.original_exception.class.to_s %> in <%= @request.parameters["controller"].camelize if @request.parameters["controller"] %>#<%= @request.parameters["action"] %> + +Showing <%= @exception.file_name %> where line #<%= @exception.line_number %> raised: +<%= @exception.message %> +<%= @exception.sub_template_message %> +<%= render template: "rescues/_trace", format: :text %> +<%= render template: "rescues/_request_and_response", format: :text %> diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb deleted file mode 100644 index 683379da10..0000000000 --- a/actionpack/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb +++ /dev/null @@ -1,2 +0,0 @@ -<h1>Unknown action</h1> -<p><%=h @exception.message %></p> diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb new file mode 100644 index 0000000000..259fb2bb3b --- /dev/null +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb @@ -0,0 +1,6 @@ +<header> + <h1>Unknown action</h1> +</header> +<div id="container"> + <h2><%= h @exception.message %></h2> +</div> diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb new file mode 100644 index 0000000000..83973addcb --- /dev/null +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb @@ -0,0 +1,3 @@ +Unknown action + +<%= @exception.message %> diff --git a/actionpack/lib/action_dispatch/middleware/templates/routes/_route.html.erb b/actionpack/lib/action_dispatch/middleware/templates/routes/_route.html.erb new file mode 100644 index 0000000000..24e44f31ac --- /dev/null +++ b/actionpack/lib/action_dispatch/middleware/templates/routes/_route.html.erb @@ -0,0 +1,16 @@ +<tr class='route_row' data-helper='path'> + <td data-route-name='<%= route[:name] %>'> + <% if route[:name].present? %> + <%= route[:name] %><span class='helper'>_path</span> + <% end %> + </td> + <td data-route-verb='<%= route[:verb] %>'> + <%= route[:verb] %> + </td> + <td data-route-path='<%= route[:path] %>' data-regexp='<%= route[:regexp] %>'> + <%= route[:path] %> + </td> + <td data-route-reqs='<%= route[:reqs] %>'> + <%= route[:reqs] %> + </td> +</tr> diff --git a/actionpack/lib/action_dispatch/middleware/templates/routes/_table.html.erb b/actionpack/lib/action_dispatch/middleware/templates/routes/_table.html.erb new file mode 100644 index 0000000000..5cee0b5932 --- /dev/null +++ b/actionpack/lib/action_dispatch/middleware/templates/routes/_table.html.erb @@ -0,0 +1,200 @@ +<% content_for :style do %> + #route_table { + margin: 0; + border-collapse: collapse; + } + + #route_table thead tr { + border-bottom: 2px solid #ddd; + } + + #route_table thead tr.bottom { + border-bottom: none; + } + + #route_table thead tr.bottom th { + padding: 10px 0; + line-height: 15px; + } + + #route_table tbody tr { + border-bottom: 1px solid #ddd; + } + + #route_table tbody tr:nth-child(odd) { + background: #f2f2f2; + } + + #route_table tbody.exact_matches, + #route_table tbody.fuzzy_matches { + background-color: LightGoldenRodYellow; + border-bottom: solid 2px SlateGrey; + } + + #route_table tbody.exact_matches tr, + #route_table tbody.fuzzy_matches tr { + background: none; + border-bottom: none; + } + + #route_table td { + padding: 4px 30px; + } + + #path_search { + width: 80%; + font-size: inherit; + } +<% end %> + +<table id='route_table' class='route_table'> + <thead> + <tr> + <th>Helper</th> + <th>HTTP Verb</th> + <th>Path</th> + <th>Controller#Action</th> + </tr> + <tr class='bottom'> + <th><%# Helper %> + <%= link_to "Path", "#", 'data-route-helper' => '_path', + title: "Returns a relative path (without the http or domain)" %> / + <%= link_to "Url", "#", 'data-route-helper' => '_url', + title: "Returns an absolute url (with the http and domain)" %> + </th> + <th><%# HTTP Verb %> + </th> + <th><%# Path %> + <%= search_field(:path, nil, id: 'search', placeholder: "Path Match") %> + </th> + <th><%# Controller#action %> + </th> + </tr> + </thead> + <tbody class='exact_matches' id='exact_matches'> + </tbody> + <tbody class='fuzzy_matches' id='fuzzy_matches'> + </tbody> + <tbody> + <%= yield %> + </tbody> +</table> + +<script type='text/javascript'> + // Iterates each element through a function + function each(elems, func) { + if (!elems instanceof Array) { elems = [elems]; } + for (var i = 0, len = elems.length; i < len; i++) { + func(elems[i]); + } + } + + // Sets innerHTML for an element + function setContent(elem, text) { + elem.innerHTML = text; + } + + // Enables path search functionality + function setupMatchPaths() { + // Check if the user input (sanitized as a path) matches the regexp data attribute + function checkExactMatch(section, elem, value) { + var string = sanitizePath(value), + regexp = elem.getAttribute("data-regexp"); + + showMatch(string, regexp, section, elem); + } + + // Check if the route path data attribute contains the user input + function checkFuzzyMatch(section, elem, value) { + var string = elem.getAttribute("data-route-path"), + regexp = value; + + showMatch(string, regexp, section, elem); + } + + // Display the parent <tr> element in the appropriate section when there's a match + function showMatch(string, regexp, section, elem) { + if(string.match(RegExp(regexp))) { + section.appendChild(elem.parentNode.cloneNode(true)); + } + } + + // Check if there are any matched results in a section + function checkNoMatch(section, defaultText, noMatchText) { + if (section.innerHTML === defaultText) { + setContent(section, defaultText + noMatchText); + } + } + + // Ensure path always starts with a slash "/" and remove params or fragments + function sanitizePath(path) { + var path = path.charAt(0) == '/' ? path : "/" + path; + return path.replace(/\#.*|\?.*/, ''); + } + + var regexpElems = document.querySelectorAll('#route_table [data-regexp]'), + searchElem = document.querySelector('#search'), + exactMatches = document.querySelector('#exact_matches'), + fuzzyMatches = document.querySelector('#fuzzy_matches'); + + // Remove matches when no search value is present + searchElem.onblur = function(e) { + if (searchElem.value === "") { + setContent(exactMatches, ""); + setContent(fuzzyMatches, ""); + } + } + + // On key press perform a search for matching paths + searchElem.onkeyup = function(e){ + var userInput = searchElem.value, + defaultExactMatch = '<tr><th colspan="4">Paths Matching (' + escape(sanitizePath(userInput)) +'):</th></tr>', + defaultFuzzyMatch = '<tr><th colspan="4">Paths Containing (' + escape(userInput) +'):</th></tr>', + noExactMatch = '<tr><th colspan="4">No Exact Matches Found</th></tr>', + noFuzzyMatch = '<tr><th colspan="4">No Fuzzy Matches Found</th></tr>'; + + // Clear out results section + setContent(exactMatches, defaultExactMatch); + setContent(fuzzyMatches, defaultFuzzyMatch); + + // Display exact matches and fuzzy matches + each(regexpElems, function(elem) { + checkExactMatch(exactMatches, elem, userInput); + checkFuzzyMatch(fuzzyMatches, elem, userInput); + }) + + // Display 'No Matches' message when no matches are found + checkNoMatch(exactMatches, defaultExactMatch, noExactMatch); + checkNoMatch(fuzzyMatches, defaultFuzzyMatch, noFuzzyMatch); + } + } + + // Enables functionality to toggle between `_path` and `_url` helper suffixes + function setupRouteToggleHelperLinks() { + + // Sets content for each element + function setValOn(elems, val) { + each(elems, function(elem) { + setContent(elem, val); + }); + } + + // Sets onClick event for each element + function onClick(elems, func) { + each(elems, function(elem) { + elem.onclick = func; + }); + } + + var toggleLinks = document.querySelectorAll('#route_table [data-route-helper]'); + onClick(toggleLinks, function(){ + var helperTxt = this.getAttribute("data-route-helper"), + helperElems = document.querySelectorAll('[data-route-name] span.helper'); + + setValOn(helperElems, helperTxt); + }); + } + + setupMatchPaths(); + setupRouteToggleHelperLinks(); +</script> |