aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_dispatch
diff options
context:
space:
mode:
authorRafael Mendonça França <rafaelmfranca@gmail.com>2014-08-12 11:10:42 -0300
committerRafael Mendonça França <rafaelmfranca@gmail.com>2014-08-12 11:10:42 -0300
commita2400308eab88b5eff27e05d1f7624345fb33b54 (patch)
tree38630de37ac59c50061734d9f353ebb798ba2023 /actionpack/lib/action_dispatch
parent045d7173167043389dbe8bd961425c1b1cc86d48 (diff)
parent82e28492e7c581cdeea904464a18eb11118f4ac0 (diff)
downloadrails-a2400308eab88b5eff27e05d1f7624345fb33b54.tar.gz
rails-a2400308eab88b5eff27e05d1f7624345fb33b54.tar.bz2
rails-a2400308eab88b5eff27e05d1f7624345fb33b54.zip
Merge branch 'master' into loofah
Conflicts: actionpack/CHANGELOG.md actionpack/test/controller/integration_test.rb actionview/CHANGELOG.md
Diffstat (limited to 'actionpack/lib/action_dispatch')
-rw-r--r--actionpack/lib/action_dispatch/http/request.rb4
-rw-r--r--actionpack/lib/action_dispatch/http/upload.rb10
-rw-r--r--actionpack/lib/action_dispatch/http/url.rb69
-rw-r--r--actionpack/lib/action_dispatch/journey/formatter.rb6
-rw-r--r--actionpack/lib/action_dispatch/journey/parser.rb54
-rw-r--r--actionpack/lib/action_dispatch/journey/parser.y22
-rw-r--r--actionpack/lib/action_dispatch/middleware/cookies.rb4
-rw-r--r--actionpack/lib/action_dispatch/middleware/debug_exceptions.rb35
-rw-r--r--actionpack/lib/action_dispatch/middleware/exception_wrapper.rb17
-rw-r--r--actionpack/lib/action_dispatch/middleware/request_id.rb2
-rw-r--r--actionpack/lib/action_dispatch/middleware/session/cache_store.rb6
-rw-r--r--actionpack/lib/action_dispatch/middleware/show_exceptions.rb1
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/_source.erb40
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb44
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb10
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/layout.erb6
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb25
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb1
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb126
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb237
-rw-r--r--actionpack/lib/action_dispatch/routing/url_for.rb7
-rw-r--r--actionpack/lib/action_dispatch/testing/assertions/response.rb9
-rw-r--r--actionpack/lib/action_dispatch/testing/assertions/routing.rb2
-rw-r--r--actionpack/lib/action_dispatch/testing/integration.rb4
24 files changed, 434 insertions, 307 deletions
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index 01f117be99..8c035c3c6c 100644
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -23,7 +23,7 @@ module ActionDispatch
autoload :Session, 'action_dispatch/request/session'
autoload :Utils, 'action_dispatch/request/utils'
- LOCALHOST = Regexp.union [/^127\.0\.0\.\d{1,3}$/, /^::1$/, /^0:0:0:0:0:0:0:1(%.*)?$/]
+ LOCALHOST = Regexp.union [/^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/, /^::1$/, /^0:0:0:0:0:0:0:1(%.*)?$/]
ENV_METHODS = %w[ AUTH_TYPE GATEWAY_INTERFACE
PATH_TRANSLATED REMOTE_HOST
@@ -225,7 +225,7 @@ module ActionDispatch
@remote_ip ||= (@env["action_dispatch.remote_ip"] || ip).to_s
end
- # Returns the unique request id, which is based off either the X-Request-Id header that can
+ # Returns the unique request id, which is based on either the X-Request-Id header that can
# be generated by a firewall, load balancer, or web server or by the RequestId middleware
# (which sets the action_dispatch.request_id environment variable).
#
diff --git a/actionpack/lib/action_dispatch/http/upload.rb b/actionpack/lib/action_dispatch/http/upload.rb
index 45bf751d09..540e11a4a0 100644
--- a/actionpack/lib/action_dispatch/http/upload.rb
+++ b/actionpack/lib/action_dispatch/http/upload.rb
@@ -27,7 +27,8 @@ module ActionDispatch
@tempfile = hash[:tempfile]
raise(ArgumentError, ':tempfile is required') unless @tempfile
- @original_filename = encode_filename(hash[:filename])
+ @original_filename = hash[:filename]
+ @original_filename &&= @original_filename.encode "UTF-8"
@content_type = hash[:type]
@headers = hash[:head]
end
@@ -66,13 +67,6 @@ module ActionDispatch
def eof?
@tempfile.eof?
end
-
- private
-
- def encode_filename(filename)
- # Encode the filename in the utf8 encoding, unless it is nil
- filename.force_encoding(Encoding::UTF_8).encode! if filename
- end
end
end
end
diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb
index 6ba2820d09..6b8dcaf497 100644
--- a/actionpack/lib/action_dispatch/http/url.rb
+++ b/actionpack/lib/action_dispatch/http/url.rb
@@ -29,39 +29,48 @@ module ActionDispatch
end
def url_for(options)
- host = options[:host]
- unless host || options[:only_path]
- raise ArgumentError, 'Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true'
+ if options[:only_path]
+ path_for options
+ else
+ full_url_for options
end
+ end
- path = options[:script_name].to_s.chomp("/")
- path << options[:path].to_s
+ def full_url_for(options)
+ host = options[:host]
+ protocol = options[:protocol]
+ port = options[:port]
- path = add_trailing_slash(path) if options[:trailing_slash]
+ unless host
+ raise ArgumentError, 'Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true'
+ end
- result = if options[:only_path]
- path
- else
- protocol = options[:protocol]
- port = options[:port]
- build_host_url(host, port, protocol, options).concat path
- end
+ build_host_url(host, port, protocol, options, path_for(options))
+ end
- if options.key? :params
- params = options[:params].is_a?(Hash) ?
- options[:params] :
- { params: options[:params] }
+ def path_for(options)
+ path = options[:script_name].to_s.chomp("/")
+ path << options[:path] if options.key?(:path)
- params.reject! { |_,v| v.to_param.nil? }
- result << "?#{params.to_query}" unless params.empty?
- end
+ add_trailing_slash(path) if options[:trailing_slash]
+ add_params(path, options[:params]) if options.key?(:params)
+ add_anchor(path, options[:anchor]) if options.key?(:anchor)
- result << "##{Journey::Router::Utils.escape_fragment(options[:anchor].to_param.to_s)}" if options[:anchor]
- result
+ path
end
private
+ def add_params(path, params)
+ params = { params: params } unless params.is_a?(Hash)
+ params.reject! { |_,v| v.to_param.nil? }
+ path << "?#{params.to_query}" unless params.empty?
+ end
+
+ def add_anchor(path, anchor)
+ path << "##{Journey::Router::Utils.escape_fragment(anchor.to_param.to_s)}"
+ end
+
def extract_domain_from(host, tld_length)
host.split('.').last(1 + tld_length).join('.')
end
@@ -79,19 +88,17 @@ module ActionDispatch
elsif !path.include?(".")
path.sub!(/[^\/]\z|\A\z/, '\&/')
end
-
- path
end
- def build_host_url(host, port, protocol, options)
+ def build_host_url(host, port, protocol, options, path)
if match = host.match(HOST_REGEXP)
- protocol ||= match[1] unless protocol == false
- host = match[2]
- port = match[3] unless options.key? :port
+ protocol ||= match[1] unless protocol == false
+ host = match[2]
+ port = match[3] unless options.key? :port
end
- protocol = normalize_protocol protocol
- host = normalize_host(host, options)
+ protocol = normalize_protocol protocol
+ host = normalize_host(host, options)
result = protocol.dup
@@ -104,7 +111,7 @@ module ActionDispatch
result << ":#{normalized_port}"
}
- result
+ result.concat path
end
def named_host?(host)
diff --git a/actionpack/lib/action_dispatch/journey/formatter.rb b/actionpack/lib/action_dispatch/journey/formatter.rb
index 6d58323789..59b353b1b7 100644
--- a/actionpack/lib/action_dispatch/journey/formatter.rb
+++ b/actionpack/lib/action_dispatch/journey/formatter.rb
@@ -12,12 +12,12 @@ module ActionDispatch
@cache = nil
end
- def generate(name, options, recall = {}, parameterize = nil)
- constraints = recall.merge(options)
+ def generate(name, options, path_parameters, parameterize = nil)
+ constraints = path_parameters.merge(options)
missing_keys = []
match_route(name, constraints) do |route|
- parameterized_parts = extract_parameterized_parts(route, options, recall, parameterize)
+ parameterized_parts = extract_parameterized_parts(route, options, path_parameters, parameterize)
# Skip this route unless a name has been provided or it is a
# standard Rails route since we can't determine whether an options
diff --git a/actionpack/lib/action_dispatch/journey/parser.rb b/actionpack/lib/action_dispatch/journey/parser.rb
index d129ba7e16..9012297400 100644
--- a/actionpack/lib/action_dispatch/journey/parser.rb
+++ b/actionpack/lib/action_dispatch/journey/parser.rb
@@ -86,7 +86,7 @@ racc_token_table = {
racc_nt_base = 10
-racc_use_result_var = true
+racc_use_result_var = false
Racc_arg = [
racc_action_table,
@@ -133,14 +133,12 @@ Racc_debug_parser = false
# reduce 0 omitted
-def _reduce_1(val, _values, result)
- result = Cat.new(val.first, val.last)
- result
+def _reduce_1(val, _values)
+ Cat.new(val.first, val.last)
end
-def _reduce_2(val, _values, result)
- result = val.first
- result
+def _reduce_2(val, _values)
+ val.first
end
# reduce 3 omitted
@@ -151,24 +149,20 @@ end
# reduce 6 omitted
-def _reduce_7(val, _values, result)
- result = Group.new(val[1])
- result
+def _reduce_7(val, _values)
+ Group.new(val[1])
end
-def _reduce_8(val, _values, result)
- result = Or.new([val.first, val.last])
- result
+def _reduce_8(val, _values)
+ Or.new([val.first, val.last])
end
-def _reduce_9(val, _values, result)
- result = Or.new([val.first, val.last])
- result
+def _reduce_9(val, _values)
+ Or.new([val.first, val.last])
end
-def _reduce_10(val, _values, result)
- result = Star.new(Symbol.new(val.last))
- result
+def _reduce_10(val, _values)
+ Star.new(Symbol.new(val.last))
end
# reduce 11 omitted
@@ -179,27 +173,23 @@ end
# reduce 14 omitted
-def _reduce_15(val, _values, result)
- result = Slash.new('/')
- result
+def _reduce_15(val, _values)
+ Slash.new('/')
end
-def _reduce_16(val, _values, result)
- result = Symbol.new(val.first)
- result
+def _reduce_16(val, _values)
+ Symbol.new(val.first)
end
-def _reduce_17(val, _values, result)
- result = Literal.new(val.first)
- result
+def _reduce_17(val, _values)
+ Literal.new(val.first)
end
-def _reduce_18(val, _values, result)
- result = Dot.new(val.first)
- result
+def _reduce_18(val, _values)
+ Dot.new(val.first)
end
-def _reduce_none(val, _values, result)
+def _reduce_none(val, _values)
val[0]
end
diff --git a/actionpack/lib/action_dispatch/journey/parser.y b/actionpack/lib/action_dispatch/journey/parser.y
index 0ead222551..d3f7c4d765 100644
--- a/actionpack/lib/action_dispatch/journey/parser.y
+++ b/actionpack/lib/action_dispatch/journey/parser.y
@@ -1,11 +1,11 @@
class ActionDispatch::Journey::Parser
-
+ options no_result_var
token SLASH LITERAL SYMBOL LPAREN RPAREN DOT STAR OR
rule
expressions
- : expression expressions { result = Cat.new(val.first, val.last) }
- | expression { result = val.first }
+ : expression expressions { Cat.new(val.first, val.last) }
+ | expression { val.first }
| or
;
expression
@@ -14,14 +14,14 @@ rule
| star
;
group
- : LPAREN expressions RPAREN { result = Group.new(val[1]) }
+ : LPAREN expressions RPAREN { Group.new(val[1]) }
;
or
- : expression OR expression { result = Or.new([val.first, val.last]) }
- | expression OR or { result = Or.new([val.first, val.last]) }
+ : expression OR expression { Or.new([val.first, val.last]) }
+ | expression OR or { Or.new([val.first, val.last]) }
;
star
- : STAR { result = Star.new(Symbol.new(val.last)) }
+ : STAR { Star.new(Symbol.new(val.last)) }
;
terminal
: symbol
@@ -30,16 +30,16 @@ rule
| dot
;
slash
- : SLASH { result = Slash.new('/') }
+ : SLASH { Slash.new('/') }
;
symbol
- : SYMBOL { result = Symbol.new(val.first) }
+ : SYMBOL { Symbol.new(val.first) }
;
literal
- : LITERAL { result = Literal.new(val.first) }
+ : LITERAL { Literal.new(val.first) }
;
dot
- : DOT { result = Dot.new(val.first) }
+ : DOT { Dot.new(val.first) }
;
end
diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb
index e069840b8e..ac9e5effe2 100644
--- a/actionpack/lib/action_dispatch/middleware/cookies.rb
+++ b/actionpack/lib/action_dispatch/middleware/cookies.rb
@@ -468,7 +468,7 @@ module ActionDispatch
options = { :value => @verifier.generate(serialize(name, options)) }
end
- raise CookieOverflow if options[:value].size > MAX_COOKIE_SIZE
+ raise CookieOverflow if options[:value].bytesize > MAX_COOKIE_SIZE
@parent_jar[name] = options
end
@@ -526,7 +526,7 @@ module ActionDispatch
options[:value] = @encryptor.encrypt_and_sign(serialize(name, options[:value]))
- raise CookieOverflow if options[:value].size > MAX_COOKIE_SIZE
+ raise CookieOverflow if options[:value].bytesize > MAX_COOKIE_SIZE
@parent_jar[name] = options
end
diff --git a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
index 0ca1a87645..274f6f2f22 100644
--- a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
+++ b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
@@ -38,9 +38,7 @@ module ActionDispatch
template = ActionView::Base.new([RESCUES_TEMPLATE_PATH],
request: request,
exception: wrapper.exception,
- application_trace: wrapper.application_trace,
- framework_trace: wrapper.framework_trace,
- full_trace: wrapper.full_trace,
+ traces: traces_from_wrapper(wrapper),
routes_inspector: routes_inspector(exception),
source_extract: wrapper.source_extract,
line_number: wrapper.line_number,
@@ -95,5 +93,36 @@ module ActionDispatch
ActionDispatch::Routing::RoutesInspector.new(@routes_app.routes.routes)
end
end
+
+ # Augment the exception traces by providing ids for all unique stack frame
+ def traces_from_wrapper(wrapper)
+ application_trace = wrapper.application_trace
+ framework_trace = wrapper.framework_trace
+ full_trace = wrapper.full_trace
+
+ if application_trace && framework_trace
+ id_counter = 0
+
+ application_trace = application_trace.map do |trace|
+ prev = id_counter
+ id_counter += 1
+ { id: prev, trace: trace }
+ end
+
+ framework_trace = framework_trace.map do |trace|
+ prev = id_counter
+ id_counter += 1
+ { id: prev, trace: trace }
+ end
+
+ full_trace = application_trace + framework_trace
+ end
+
+ {
+ "Application Trace" => application_trace,
+ "Framework Trace" => framework_trace,
+ "Full Trace" => full_trace
+ }
+ end
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
index 2326bb043a..b98b553c38 100644
--- a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
+++ b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
@@ -61,12 +61,15 @@ module ActionDispatch
end
def source_extract
- if application_trace && trace = application_trace.first
- file, line, _ = trace.split(":")
- @file = file
- @line_number = line.to_i
- source_fragment(@file, @line_number)
- end
+ exception.backtrace.map do |trace|
+ file, line = trace.split(":")
+ line_number = line.to_i
+ {
+ code: source_fragment(file, line_number),
+ file: file,
+ line_number: line_number
+ }
+ end if exception.backtrace
end
private
@@ -110,7 +113,7 @@ module ActionDispatch
def expand_backtrace
@exception.backtrace.unshift(
@exception.to_s.split("\n")
- ).flatten!
+ ).flatten!
end
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/request_id.rb b/actionpack/lib/action_dispatch/middleware/request_id.rb
index 5d1740d0d4..25658bac3d 100644
--- a/actionpack/lib/action_dispatch/middleware/request_id.rb
+++ b/actionpack/lib/action_dispatch/middleware/request_id.rb
@@ -5,7 +5,7 @@ module ActionDispatch
# Makes a unique request id available to the action_dispatch.request_id env variable (which is then accessible through
# ActionDispatch::Request#uuid) and sends the same id to the client via the X-Request-Id header.
#
- # The unique request id is either based off the X-Request-Id header in the request, which would typically be generated
+ # The unique request id is either based on the X-Request-Id header in the request, which would typically be generated
# by a firewall, load balancer, or the web server, or, if this header is not available, a random uuid. If the
# header is accepted from the outside world, we sanitize it to a max of 255 chars and alphanumeric and dashes only.
#
diff --git a/actionpack/lib/action_dispatch/middleware/session/cache_store.rb b/actionpack/lib/action_dispatch/middleware/session/cache_store.rb
index 1db6194271..625050dc4b 100644
--- a/actionpack/lib/action_dispatch/middleware/session/cache_store.rb
+++ b/actionpack/lib/action_dispatch/middleware/session/cache_store.rb
@@ -16,9 +16,9 @@ module ActionDispatch
# Get a session from the cache.
def get_session(env, sid)
- sid ||= generate_sid
- session = @cache.read(cache_key(sid))
- session ||= {}
+ unless sid and session = @cache.read(cache_key(sid))
+ sid, session = generate_sid, {}
+ end
[sid, session]
end
diff --git a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb
index 1d4f0f89a6..f0779279c1 100644
--- a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb
+++ b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb
@@ -42,6 +42,7 @@ module ActionDispatch
wrapper = ExceptionWrapper.new(env, exception)
status = wrapper.status_code
env["action_dispatch.exception"] = wrapper.exception
+ env["action_dispatch.original_path"] = env["PATH_INFO"]
env["PATH_INFO"] = "/#{status}"
response = @exceptions_app.call(env)
response[1]['X-Cascade'] == 'pass' ? pass_response(status) : response
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/_source.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/_source.erb
index 38429cb78e..51660a619b 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/_source.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/_source.erb
@@ -1,25 +1,29 @@
<% if @source_extract %>
-<div class="source">
-<div class="info">
- Extracted source (around line <strong>#<%= @line_number %></strong>):
-</div>
-<div class="data">
- <table cellpadding="0" cellspacing="0" class="lines">
- <tr>
- <td>
- <pre class="line_numbers">
- <% @source_extract.keys.each do |line_number| %>
+ <% @source_extract.each_with_index do |extract_source, index| %>
+ <% if extract_source[:code] %>
+ <div class="source <%="hidden" if index != 0%>" id="frame-source-<%=index%>">
+ <div class="info">
+ Extracted source (around line <strong>#<%= extract_source[:line_number] %></strong>):
+ </div>
+ <div class="data">
+ <table cellpadding="0" cellspacing="0" class="lines">
+ <tr>
+ <td>
+ <pre class="line_numbers">
+ <% extract_source[:code].keys.each do |line_number| %>
<span><%= line_number -%></span>
- <% end %>
- </pre>
- </td>
+ <% end %>
+ </pre>
+ </td>
<td width="100%">
<pre>
-<% @source_extract.each do |line, source| -%><div class="line<%= " active" if line == @line_number -%>"><%= source -%></div><% end -%>
+<% extract_source[:code].each do |line, source| -%><div class="line<%= " active" if line == extract_source[:line_number] -%>"><%= source -%></div><% end -%>
</pre>
</td>
- </tr>
- </table>
-</div>
-</div>
+ </tr>
+ </table>
+ </div>
+ </div>
+ <% end %>
+ <% end %>
<% end %>
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb
index b181909bff..f62caf51d7 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb
@@ -1,9 +1,4 @@
-<%
- traces = { "Application Trace" => @application_trace,
- "Framework Trace" => @framework_trace,
- "Full Trace" => @full_trace }
- names = traces.keys
-%>
+<% names = @traces.keys %>
<p><code>Rails.root: <%= defined?(Rails) && Rails.respond_to?(:root) ? Rails.root : "unset" %></code></p>
@@ -16,9 +11,42 @@
<a href="#" onclick="<%= hide.join %><%= show %>; return false;"><%= name %></a> <%= '|' unless names.last == name %>
<% end %>
- <% traces.each do |name, trace| %>
+ <% @traces.each do |name, trace| %>
<div id="<%= name.gsub(/\s/, '-') %>" style="display: <%= (name == "Application Trace") ? 'block' : 'none' %>;">
- <pre><code><%= trace.join "\n" %></code></pre>
+ <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
index d4af5c9b06..36b01bf952 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb
@@ -1,15 +1,9 @@
-<%
- traces = { "Application Trace" => @application_trace,
- "Framework Trace" => @framework_trace,
- "Full Trace" => @full_trace }
-%>
-
Rails.root: <%= defined?(Rails) && Rails.respond_to?(:root) ? Rails.root : "unset" %>
-<% traces.each do |name, trace| %>
+<% @traces.each do |name, trace| %>
<% if trace.any? %>
<%= name %>
-<%= trace.join("\n") %>
+<%= trace.map(&:trace).join("\n") %>
<% end %>
<% end %>
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/layout.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/layout.erb
index bc5d03dc10..e0509f56f4 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/layout.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/layout.erb
@@ -116,9 +116,15 @@
background-color: #FFCCCC;
}
+ .hidden {
+ display: none;
+ }
+
a { color: #980905; }
a:visited { color: #666; }
+ a.trace-frames { color: #666; }
a:hover { color: #C52F24; }
+ a.trace-frames.selected { color: #C52F24 }
<%= yield :style %>
</style>
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
index 027a0f5b3e..c1e8b6cae3 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb
@@ -1,4 +1,3 @@
-<% @source_extract = @exception.source_extract(0, :html) %>
<header>
<h1>
<%= @exception.original_exception.class.to_s %> in
@@ -12,29 +11,7 @@
</p>
<pre><code><%= h @exception.message %></code></pre>
- <div class="source">
- <div class="info">
- <p>Extracted source (around line <strong>#<%= @exception.line_number %></strong>):</p>
- </div>
- <div class="data">
- <table cellpadding="0" cellspacing="0" class="lines">
- <tr>
- <td>
- <pre class="line_numbers">
- <% @source_extract.keys.each do |line_number| %>
-<span><%= line_number -%></span>
- <% end %>
- </pre>
- </td>
-<td width="100%">
-<pre>
-<% @source_extract.each do |line, source| -%><div class="line<%= " active" if line == @exception.line_number -%>"><%= source -%></div><% end -%>
-</pre>
-</td>
- </tr>
- </table>
-</div>
-</div>
+ <%= render template: "rescues/_source" %>
<p><%= @exception.sub_template_message %></p>
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
index 5da21d9784..77bcd26726 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb
@@ -1,4 +1,3 @@
-<% @source_extract = @exception.source_extract(0, :html) %>
<%= @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:
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index 235a840682..cd94f35e8f 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -13,9 +13,6 @@ module ActionDispatch
module Routing
class Mapper
URL_OPTIONS = [:protocol, :subdomain, :domain, :host, :port]
- SCOPE_OPTIONS = [:path, :shallow_path, :as, :shallow_prefix, :module,
- :controller, :action, :path_names, :constraints,
- :shallow, :blocks, :defaults, :options]
class Constraints < Endpoint #:nodoc:
attr_reader :app, :constraints
@@ -66,7 +63,7 @@ module ActionDispatch
attr_reader :requirements, :conditions, :defaults
attr_reader :to, :default_controller, :default_action, :as, :anchor
- def self.build(scope, path, options)
+ def self.build(scope, set, path, options)
options = scope[:options].merge(options) if scope[:options]
options.delete :only
@@ -77,12 +74,13 @@ module ActionDispatch
defaults = (scope[:defaults] || {}).merge options.delete(:defaults) || {}
- new scope, path, defaults, options
+ new scope, set, path, defaults, options
end
- def initialize(scope, path, defaults, options)
+ def initialize(scope, set, path, defaults, options)
@requirements, @conditions = {}, {}
@defaults = defaults
+ @set = set
@to = options.delete :to
@default_controller = options.delete(:controller) || scope[:controller]
@@ -249,9 +247,9 @@ module ActionDispatch
Constraints.new(to, blocks, false)
else
if blocks.any?
- Constraints.new(dispatcher, blocks, true)
+ Constraints.new(dispatcher(defaults), blocks, true)
else
- dispatcher
+ dispatcher(defaults)
end
end
end
@@ -348,8 +346,8 @@ module ActionDispatch
parser.parse path
end
- def dispatcher
- Routing::RouteSet::Dispatcher.new(defaults)
+ def dispatcher(defaults)
+ @set.dispatcher defaults
end
end
@@ -576,13 +574,21 @@ module ActionDispatch
raise "A rack application must be specified" unless path
- options[:as] ||= app_name(app)
+ rails_app = rails_app? app
+
+ if rails_app
+ options[:as] ||= app.railtie_name
+ else
+ # non rails apps can't have an :as
+ options[:as] = nil
+ end
+
target_as = name_for_action(options[:as], path)
options[:via] ||= :all
match(path, options.merge(:to => app, :anchor => false, :format => false))
- define_generate_prefix(app, target_as)
+ define_generate_prefix(app, target_as) if rails_app
self
end
@@ -603,31 +609,24 @@ module ActionDispatch
end
private
- def app_name(app)
- return unless app.respond_to?(:routes)
-
- if app.respond_to?(:railtie_name)
- app.railtie_name
- else
- class_name = app.class.is_a?(Class) ? app.name : app.class.name
- ActiveSupport::Inflector.underscore(class_name).tr("/", "_")
- end
+ def rails_app?(app)
+ app.is_a?(Class) && app < Rails::Railtie
end
def define_generate_prefix(app, name)
- return unless app.respond_to?(:routes) && app.routes.respond_to?(:define_mounted_helper)
-
- _route = @set.named_routes.routes[name.to_sym]
+ _route = @set.named_routes.get name
_routes = @set
app.routes.define_mounted_helper(name)
app.routes.extend Module.new {
- def mounted?; true; end
+ def optimize_routes_generation?; false; end
define_method :find_script_name do |options|
- super(options) || begin
- prefix_options = options.slice(*_route.segment_keys)
- # we must actually delete prefix segment keys to avoid passing them to next url_for
- _route.segment_keys.each { |k| options.delete(k) }
- _routes.url_helpers.send("#{name}_path", prefix_options)
+ if options.key? :script_name
+ super(options)
+ else
+ prefix_options = options.slice(*_route.segment_keys)
+ # we must actually delete prefix segment keys to avoid passing them to next url_for
+ _route.segment_keys.each { |k| options.delete(k) }
+ _routes.url_helpers.send("#{name}_path", prefix_options)
end
end
}
@@ -771,7 +770,7 @@ module ActionDispatch
# end
def scope(*args)
options = args.extract_options!.dup
- recover = {}
+ scope = {}
options[:path] = args.flatten.join('/') if args.any?
options[:constraints] ||= {}
@@ -791,7 +790,7 @@ module ActionDispatch
block, options[:constraints] = options[:constraints], {}
end
- SCOPE_OPTIONS.each do |option|
+ @scope.options.each do |option|
if option == :blocks
value = block
elsif option == :options
@@ -801,15 +800,15 @@ module ActionDispatch
end
if value
- recover[option] = @scope[option]
- @scope[option] = send("merge_#{option}_scope", @scope[option], value)
+ scope[option] = send("merge_#{option}_scope", @scope[option], value)
end
end
+ @scope = @scope.new scope
yield
self
ensure
- @scope.merge!(recover)
+ @scope = @scope.parent
end
# Scopes routes to a specific controller
@@ -1545,13 +1544,13 @@ module ActionDispatch
action = nil
end
- if !options.fetch(:as, true)
+ if !options.fetch(:as, true) # if it's set to nil or false
options.delete(:as)
else
options[:as] = name_for_action(options[:as], action)
end
- mapping = Mapping.build(@scope, URI.parser.escape(path), options)
+ mapping = Mapping.build(@scope, @set, URI.parser.escape(path), options)
app, conditions, requirements, defaults, as, anchor = mapping.to_route
@set.add_route(app, conditions, requirements, defaults, as, anchor)
end
@@ -1645,27 +1644,26 @@ module ActionDispatch
def with_exclusive_scope
begin
- old_name_prefix, old_path = @scope[:as], @scope[:path]
- @scope[:as], @scope[:path] = nil, nil
+ @scope = @scope.new(:as => nil, :path => nil)
with_scope_level(:exclusive) do
yield
end
ensure
- @scope[:as], @scope[:path] = old_name_prefix, old_path
+ @scope = @scope.parent
end
end
def with_scope_level(kind)
- old, @scope[:scope_level] = @scope[:scope_level], kind
+ @scope = @scope.new(:scope_level => kind)
yield
ensure
- @scope[:scope_level] = old
+ @scope = @scope.parent
end
def resource_scope(kind, resource) #:nodoc:
resource.shallow = @scope[:shallow]
- old_resource, @scope[:scope_level_resource] = @scope[:scope_level_resource], resource
+ @scope = @scope.new(:scope_level_resource => resource)
@nesting.push(resource)
with_scope_level(kind) do
@@ -1673,7 +1671,7 @@ module ActionDispatch
end
ensure
@nesting.pop
- @scope[:scope_level_resource] = old_resource
+ @scope = @scope.parent
end
def nested_options #:nodoc:
@@ -1706,12 +1704,13 @@ module ActionDispatch
end
def shallow_scope(path, options = {}) #:nodoc:
- old_name_prefix, old_path = @scope[:as], @scope[:path]
- @scope[:as], @scope[:path] = @scope[:shallow_prefix], @scope[:shallow_path]
+ scope = { :as => @scope[:shallow_prefix],
+ :path => @scope[:shallow_path] }
+ @scope = @scope.new scope
scope(path, options) { yield }
ensure
- @scope[:as], @scope[:path] = old_name_prefix, old_path
+ @scope = @scope.parent
end
def path_for_action(action, path) #:nodoc:
@@ -1768,7 +1767,7 @@ module ActionDispatch
# and return nil in case it isn't. Otherwise, we pass the invalid name
# forward so the underlying router engine treats it and raises an exception.
if as.nil?
- candidate unless @set.routes.find { |r| r.name == candidate } || candidate !~ /\A[_a-z]/i
+ candidate unless candidate !~ /\A[_a-z]/i || @set.named_routes.key?(candidate)
else
candidate
end
@@ -1893,9 +1892,38 @@ module ActionDispatch
end
end
+ class Scope # :nodoc:
+ OPTIONS = [:path, :shallow_path, :as, :shallow_prefix, :module,
+ :controller, :action, :path_names, :constraints,
+ :shallow, :blocks, :defaults, :options]
+
+ attr_reader :parent
+
+ def initialize(hash, parent = {})
+ @hash = hash
+ @parent = parent
+ end
+
+ def options
+ OPTIONS
+ end
+
+ def new(hash)
+ self.class.new hash, self
+ end
+
+ def [](key)
+ @hash.fetch(key) { @parent[key] }
+ end
+
+ def []=(k,v)
+ @hash[k] = v
+ end
+ end
+
def initialize(set) #:nodoc:
@set = set
- @scope = { :path_names => @set.resources_path_names }
+ @scope = Scope.new({ :path_names => @set.resources_path_names })
@concerns = {}
@nesting = []
end
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index 69535faabd..5b3651aaee 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -86,36 +86,64 @@ module ActionDispatch
# named routes.
class NamedRouteCollection #:nodoc:
include Enumerable
- attr_reader :routes, :helpers, :module
+ attr_reader :routes, :url_helpers_module
def initialize
@routes = {}
- @helpers = []
- @module = Module.new
+ @path_helpers = Set.new
+ @url_helpers = Set.new
+ @url_helpers_module = Module.new
+ @path_helpers_module = Module.new
+ end
+
+ def route_defined?(name)
+ key = name.to_sym
+ @path_helpers.include?(key) || @url_helpers.include?(key)
end
def helper_names
- @helpers.map(&:to_s)
+ @path_helpers.map(&:to_s) + @url_helpers.map(&:to_s)
end
def clear!
- @helpers.each do |helper|
- @module.remove_possible_method helper
+ @path_helpers.each do |helper|
+ @path_helpers_module.send :undef_method, helper
+ end
+
+ @url_helpers.each do |helper|
+ @url_helpers_module.send :undef_method, helper
end
@routes.clear
- @helpers.clear
+ @path_helpers.clear
+ @url_helpers.clear
end
def add(name, route)
- routes[name.to_sym] = route
- define_named_route_methods(name, route)
+ key = name.to_sym
+ path_name = :"#{name}_path"
+ url_name = :"#{name}_url"
+
+ if routes.key? key
+ @path_helpers_module.send :undef_method, path_name
+ @url_helpers_module.send :undef_method, url_name
+ end
+ routes[key] = route
+ define_url_helper @path_helpers_module, route, path_name, route.defaults, name, PATH
+ define_url_helper @url_helpers_module, route, url_name, route.defaults, name, FULL
+
+ @path_helpers << path_name
+ @url_helpers << url_name
end
def get(name)
routes[name.to_sym]
end
+ def key?(name)
+ routes.key? name.to_sym
+ end
+
alias []= add
alias [] get
alias clear clear!
@@ -133,12 +161,31 @@ module ActionDispatch
routes.length
end
+ def path_helpers_module(warn = false)
+ if warn
+ mod = @path_helpers_module
+ helpers = @path_helpers
+ Module.new do
+ include mod
+
+ helpers.each do |meth|
+ define_method(meth) do |*args, &block|
+ ActiveSupport::Deprecation.warn("The method `#{meth}` cannot be used here as a full URL is required. Use `#{meth.to_s.sub(/_path$/, '_url')}` instead")
+ super(*args, &block)
+ end
+ end
+ end
+ else
+ @path_helpers_module
+ end
+ end
+
class UrlHelper # :nodoc:
- def self.create(route, options)
+ def self.create(route, options, route_name, url_strategy)
if optimize_helper?(route)
- OptimizedUrlHelper.new(route, options)
+ OptimizedUrlHelper.new(route, options, route_name, url_strategy)
else
- new route, options
+ new route, options, route_name, url_strategy
end
end
@@ -146,20 +193,22 @@ module ActionDispatch
!route.glob? && route.path.requirements.empty?
end
+ attr_reader :url_strategy, :route_name
+
class OptimizedUrlHelper < UrlHelper # :nodoc:
attr_reader :arg_size
- def initialize(route, options)
+ def initialize(route, options, route_name, url_strategy)
super
@required_parts = @route.required_parts
@arg_size = @required_parts.size
end
- def call(t, args)
- if args.size == arg_size && !args.last.is_a?(Hash) && optimize_routes_generation?(t)
+ def call(t, args, inner_options)
+ if args.size == arg_size && !inner_options && optimize_routes_generation?(t)
options = t.url_options.merge @options
options[:path] = optimized_helper(args)
- ActionDispatch::Http::URL.url_for(options)
+ url_strategy.call options
else
super
end
@@ -201,21 +250,27 @@ module ActionDispatch
end
end
- def initialize(route, options)
+ def initialize(route, options, route_name, url_strategy)
@options = options
@segment_keys = route.segment_keys.uniq
@route = route
+ @url_strategy = url_strategy
+ @route_name = route_name
end
- def call(t, args)
+ def call(t, args, inner_options)
controller_options = t.url_options
options = controller_options.merge @options
- hash = handle_positional_args(controller_options, args, options, @segment_keys)
- t._routes.url_for(hash)
+ hash = handle_positional_args(controller_options,
+ inner_options || {},
+ args,
+ options,
+ @segment_keys)
+
+ t._routes.url_for(hash, route_name, url_strategy)
end
- def handle_positional_args(controller_options, args, result, path_params)
- inner_options = args.extract_options!
+ def handle_positional_args(controller_options, inner_options, args, result, path_params)
if args.size > 0
if args.size < path_params.size - 1 # take format into account
@@ -245,27 +300,25 @@ module ActionDispatch
#
# foo_url(bar, baz, bang, sort_by: 'baz')
#
- def define_url_helper(route, name, options)
- helper = UrlHelper.create(route, options.dup)
-
- @module.remove_possible_method name
- @module.module_eval do
+ def define_url_helper(mod, route, name, opts, route_key, url_strategy)
+ helper = UrlHelper.create(route, opts, route_key, url_strategy)
+ mod.module_eval do
define_method(name) do |*args|
- helper.call self, args
+ options = nil
+ options = args.pop if args.last.is_a? Hash
+ helper.call self, args, options
end
end
-
- helpers << name
- end
-
- def define_named_route_methods(name, route)
- define_url_helper route, :"#{name}_path",
- route.defaults.merge(:use_route => name, :only_path => true)
- define_url_helper route, :"#{name}_url",
- route.defaults.merge(:use_route => name, :only_path => false)
end
end
+ # :stopdoc:
+ # strategy for building urls to send to the client
+ PATH = ->(options) { ActionDispatch::Http::URL.path_for(options) }
+ FULL = ->(options) { ActionDispatch::Http::URL.full_url_for(options) }
+ UNKNOWN = ->(options) { ActionDispatch::Http::URL.url_for(options) }
+ # :startdoc:
+
attr_accessor :formatter, :set, :named_routes, :default_scope, :router
attr_accessor :disable_clear_and_finalize, :resources_path_names
attr_accessor :default_url_options, :request_class
@@ -278,7 +331,7 @@ module ActionDispatch
def initialize(request_class = ActionDispatch::Request)
self.named_routes = NamedRouteCollection.new
- self.resources_path_names = self.class.default_resources_path_names.dup
+ self.resources_path_names = self.class.default_resources_path_names
self.default_url_options = {}
self.request_class = request_class
@@ -319,6 +372,7 @@ module ActionDispatch
mapper.instance_exec(&block)
end
end
+ private :eval_block
def finalize!
return if @finalized
@@ -334,6 +388,10 @@ module ActionDispatch
@prepend.each { |blk| eval_block(blk) }
end
+ def dispatcher(defaults)
+ Routing::RouteSet::Dispatcher.new(defaults)
+ end
+
module MountedHelpers #:nodoc:
extend ActiveSupport::Concern
include UrlFor
@@ -364,42 +422,51 @@ module ActionDispatch
RUBY
end
- def url_helpers
- @url_helpers ||= begin
- routes = self
-
- Module.new do
- extend ActiveSupport::Concern
- include UrlFor
-
- # Define url_for in the singleton level so one can do:
- # Rails.application.routes.url_helpers.url_for(args)
- @_routes = routes
- class << self
- delegate :url_for, :optimize_routes_generation?, :to => '@_routes'
- attr_reader :_routes
- def url_options; {}; end
- end
+ def url_helpers(include_path_helpers = true)
+ routes = self
- # Make named_routes available in the module singleton
- # as well, so one can do:
- # Rails.application.routes.url_helpers.posts_path
- extend routes.named_routes.module
+ Module.new do
+ extend ActiveSupport::Concern
+ include UrlFor
+
+ # Define url_for in the singleton level so one can do:
+ # Rails.application.routes.url_helpers.url_for(args)
+ @_routes = routes
+ class << self
+ delegate :url_for, :optimize_routes_generation?, to: '@_routes'
+ attr_reader :_routes
+ def url_options; {}; end
+ end
- # Any class that includes this module will get all
- # named routes...
- include routes.named_routes.module
+ url_helpers = routes.named_routes.url_helpers_module
- # plus a singleton class method called _routes ...
- included do
- singleton_class.send(:redefine_method, :_routes) { routes }
- end
+ # Make named_routes available in the module singleton
+ # as well, so one can do:
+ # Rails.application.routes.url_helpers.posts_path
+ extend url_helpers
- # And an instance method _routes. Note that
- # UrlFor (included in this module) add extra
- # conveniences for working with @_routes.
- define_method(:_routes) { @_routes || routes }
+ # Any class that includes this module will get all
+ # named routes...
+ include url_helpers
+
+ if include_path_helpers
+ path_helpers = routes.named_routes.path_helpers_module
+ else
+ path_helpers = routes.named_routes.path_helpers_module(true)
end
+
+ include path_helpers
+ extend path_helpers
+
+ # plus a singleton class method called _routes ...
+ included do
+ singleton_class.send(:redefine_method, :_routes) { routes }
+ end
+
+ # And an instance method _routes. Note that
+ # UrlFor (included in this module) add extra
+ # conveniences for working with @_routes.
+ define_method(:_routes) { @_routes || routes }
end
end
@@ -491,8 +558,8 @@ module ActionDispatch
attr_reader :options, :recall, :set, :named_route
- def initialize(options, recall, set)
- @named_route = options.delete(:use_route)
+ def initialize(named_route, options, recall, set)
+ @named_route = named_route
@options = options.dup
@recall = recall.dup
@set = set
@@ -608,32 +675,34 @@ module ActionDispatch
end
def generate_extras(options, recall={})
- path, params = generate(options, recall)
+ route_key = options.delete :use_route
+ path, params = generate(route_key, options, recall)
return path, params.keys
end
- def generate(options, recall = {})
- Generator.new(options, recall, self).generate
+ def generate(route_key, options, recall = {})
+ Generator.new(route_key, options, recall, self).generate
end
+ private :generate
RESERVED_OPTIONS = [:host, :protocol, :port, :subdomain, :domain, :tld_length,
:trailing_slash, :anchor, :params, :only_path, :script_name,
:original_script_name]
- def mounted?
- false
- end
-
def optimize_routes_generation?
- !mounted? && default_url_options.empty?
+ default_url_options.empty?
end
def find_script_name(options)
- options.delete :script_name
+ options.delete(:script_name) { '' }
+ end
+
+ def path_for(options, route_name = nil) # :nodoc:
+ url_for(options, route_name, PATH)
end
# The +options+ argument must be a hash whose keys are *symbols*.
- def url_for(options)
+ def url_for(options, route_name = nil, url_strategy = UNKNOWN)
options = default_url_options.merge options
user = password = nil
@@ -648,14 +717,14 @@ module ActionDispatch
original_script_name = options.delete(:original_script_name)
script_name = find_script_name options
- if script_name && original_script_name
+ if original_script_name
script_name = original_script_name + script_name
end
path_options = options.dup
RESERVED_OPTIONS.each { |ro| path_options.delete ro }
- path, params = generate(path_options, recall)
+ path, params = generate(route_name, path_options, recall)
if options.key? :params
params.merge! options[:params]
@@ -667,7 +736,7 @@ module ActionDispatch
options[:user] = user
options[:password] = password
- ActionDispatch::Http::URL.url_for(options)
+ url_strategy.call options
end
def call(env)
diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb
index e624fe3c4a..eb554ec383 100644
--- a/actionpack/lib/action_dispatch/routing/url_for.rb
+++ b/actionpack/lib/action_dispatch/routing/url_for.rb
@@ -152,7 +152,9 @@ module ActionDispatch
when nil
_routes.url_for(url_options.symbolize_keys)
when Hash
- _routes.url_for(options.symbolize_keys.reverse_merge!(url_options))
+ route_name = options.delete :use_route
+ _routes.url_for(options.symbolize_keys.reverse_merge!(url_options),
+ route_name)
when String
options
when Symbol
@@ -169,8 +171,7 @@ module ActionDispatch
protected
def optimize_routes_generation?
- return @_optimized_routes if defined?(@_optimized_routes)
- @_optimized_routes = _routes.optimize_routes_generation? && default_url_options.empty?
+ _routes.optimize_routes_generation? && default_url_options.empty?
end
def _with_routes(routes)
diff --git a/actionpack/lib/action_dispatch/testing/assertions/response.rb b/actionpack/lib/action_dispatch/testing/assertions/response.rb
index 0adc6c84ff..13a72220b3 100644
--- a/actionpack/lib/action_dispatch/testing/assertions/response.rb
+++ b/actionpack/lib/action_dispatch/testing/assertions/response.rb
@@ -73,13 +73,8 @@ module ActionDispatch
if Regexp === fragment
fragment
else
- handle = @controller || Class.new(ActionController::Metal) do
- include ActionController::Redirecting
- def initialize(request)
- @_request = request
- end
- end.new(@request)
- handle._compute_redirect_to_location(fragment)
+ handle = @controller || ActionController::Redirecting
+ handle._compute_redirect_to_location(@request, fragment)
end
end
end
diff --git a/actionpack/lib/action_dispatch/testing/assertions/routing.rb b/actionpack/lib/action_dispatch/testing/assertions/routing.rb
index f1f998d932..2cf38a9c2d 100644
--- a/actionpack/lib/action_dispatch/testing/assertions/routing.rb
+++ b/actionpack/lib/action_dispatch/testing/assertions/routing.rb
@@ -165,7 +165,7 @@ module ActionDispatch
# ROUTES TODO: These assertions should really work in an integration context
def method_missing(selector, *args, &block)
- if defined?(@controller) && @controller && @routes && @routes.named_routes.helpers.include?(selector)
+ if defined?(@controller) && @controller && @routes && @routes.named_routes.route_defined?(selector)
@controller.send(selector, *args, &block)
else
super
diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb
index e326776bbc..2d1c3ac5c7 100644
--- a/actionpack/lib/action_dispatch/testing/integration.rb
+++ b/actionpack/lib/action_dispatch/testing/integration.rb
@@ -3,6 +3,7 @@ require 'uri'
require 'active_support/core_ext/kernel/singleton_class'
require 'active_support/core_ext/object/try'
require 'rack/test'
+require 'minitest'
module ActionDispatch
module Integration #:nodoc:
@@ -200,7 +201,7 @@ module ActionDispatch
@url_options ||= default_url_options.dup.tap do |url_options|
url_options.reverse_merge!(controller.url_options) if controller
- if @app.respond_to?(:routes) && @app.routes.respond_to?(:default_url_options)
+ if @app.respond_to?(:routes)
url_options.reverse_merge!(@app.routes.default_url_options)
end
@@ -329,6 +330,7 @@ module ActionDispatch
xml_http_request xhr get_via_redirect post_via_redirect).each do |method|
define_method(method) do |*args|
reset! unless integration_session
+ reset_template_assertion
# reset the html_document variable, but only for new get/post calls
@html_document = nil unless method == 'cookies' || method == 'assigns'
integration_session.__send__(method, *args).tap do