aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib')
-rw-r--r--actionpack/lib/abstract_controller/callbacks.rb5
-rw-r--r--actionpack/lib/action_controller/metal/conditional_get.rb18
-rw-r--r--actionpack/lib/action_controller/metal/request_forgery_protection.rb4
-rw-r--r--actionpack/lib/action_controller/metal/strong_parameters.rb1
-rw-r--r--actionpack/lib/action_dispatch/http/mime_type.rb2
-rw-r--r--actionpack/lib/action_dispatch/http/request.rb8
-rw-r--r--actionpack/lib/action_dispatch/http/response.rb8
-rw-r--r--actionpack/lib/action_dispatch/journey/router.rb1
-rw-r--r--actionpack/lib/action_dispatch/middleware/request_id.rb14
-rw-r--r--actionpack/lib/action_dispatch/middleware/static.rb5
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/routes/_route.html.erb8
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/routes/_table.html.erb122
-rw-r--r--actionpack/lib/action_dispatch/routing/inspector.rb26
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb2
-rw-r--r--actionpack/lib/action_dispatch/routing/polymorphic_routes.rb2
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb4
-rw-r--r--actionpack/lib/action_dispatch/routing/routes_proxy.rb9
-rw-r--r--actionpack/lib/action_dispatch/testing/assertions/routing.rb22
-rw-r--r--actionpack/lib/action_dispatch/testing/integration.rb26
-rw-r--r--actionpack/lib/action_dispatch/testing/test_response.rb13
20 files changed, 150 insertions, 150 deletions
diff --git a/actionpack/lib/abstract_controller/callbacks.rb b/actionpack/lib/abstract_controller/callbacks.rb
index 69f490b327..59ffb0a19e 100644
--- a/actionpack/lib/abstract_controller/callbacks.rb
+++ b/actionpack/lib/abstract_controller/callbacks.rb
@@ -1,5 +1,3 @@
-require 'active_support/deprecation'
-
module AbstractController
module Callbacks
extend ActiveSupport::Concern
@@ -63,13 +61,14 @@ module AbstractController
# impossible to skip a callback defined using an anonymous proc
# using #skip_action_callback
def skip_action_callback(*names)
+ ActiveSupport::Deprecation.warn('`skip_action_callback` is deprecated and will be removed in the next major version of Rails. Please use skip_before_action, skip_after_action or skip_around_action instead.')
skip_before_action(*names)
skip_after_action(*names)
skip_around_action(*names)
end
def skip_filter(*names)
- ActiveSupport::Deprecation.warn("#{callback}_filter is deprecated and will be removed in Rails 5.1. Use #{callback}_action instead.")
+ ActiveSupport::Deprecation.warn("`skip_filter` is deprecated and will be removed in Rails 5.1. Use skip_before_action, skip_after_action or skip_around_action instead.")
skip_action_callback(*names)
end
diff --git a/actionpack/lib/action_controller/metal/conditional_get.rb b/actionpack/lib/action_controller/metal/conditional_get.rb
index 28f0b6e349..858870d8b8 100644
--- a/actionpack/lib/action_controller/metal/conditional_get.rb
+++ b/actionpack/lib/action_controller/metal/conditional_get.rb
@@ -215,6 +215,24 @@ module ActionController
response.cache_control.replace(:no_cache => true)
end
+ # Cache or yield the block. The cache is supposed to never expire.
+ #
+ # You can use this method when you have a HTTP response that never changes,
+ # and the browser and proxies should cache it indefinitely.
+ #
+ # * +public+: By default, HTTP responses are private, cached only on the
+ # user's web browser. To allow proxies to cache the response, set +true+ to
+ # indicate that they can serve the cached response to all users.
+ #
+ # * +version+: the version passed as a key for the cache.
+ def http_cache_forever(public: false, version: 'v1')
+ expires_in 100.years, public: public
+
+ yield if stale?(etag: "#{version}-#{request.fullpath}",
+ last_modified: Time.parse('2011-01-01').utc,
+ public: public)
+ end
+
private
def combine_etags(options)
etags = etaggers.map { |etagger| instance_exec(options, &etagger) }.compact
diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
index 7facbe79aa..367b736035 100644
--- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb
+++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
@@ -275,7 +275,9 @@ module ActionController #:nodoc:
# session token. Essentially the inverse of
# +masked_authenticity_token+.
def valid_authenticity_token?(session, encoded_masked_token)
- return false if encoded_masked_token.nil? || encoded_masked_token.empty?
+ if encoded_masked_token.nil? || encoded_masked_token.empty? || !encoded_masked_token.is_a?(String)
+ return false
+ end
begin
masked_token = Base64.strict_decode64(encoded_masked_token)
diff --git a/actionpack/lib/action_controller/metal/strong_parameters.rb b/actionpack/lib/action_controller/metal/strong_parameters.rb
index 01bbd749c1..f19c4201ba 100644
--- a/actionpack/lib/action_controller/metal/strong_parameters.rb
+++ b/actionpack/lib/action_controller/metal/strong_parameters.rb
@@ -1,7 +1,6 @@
require 'active_support/core_ext/hash/indifferent_access'
require 'active_support/core_ext/array/wrap'
require 'active_support/core_ext/string/filters'
-require 'active_support/deprecation'
require 'active_support/rescuable'
require 'action_dispatch/http/upload'
require 'stringio'
diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb
index 047a17937a..7e585aa244 100644
--- a/actionpack/lib/action_dispatch/http/mime_type.rb
+++ b/actionpack/lib/action_dispatch/http/mime_type.rb
@@ -45,7 +45,7 @@ module Mime
#
# respond_to do |format|
# format.html
- # format.ics { render text: @post.to_ics, mime_type: Mime::Type["text/calendar"] }
+ # format.ics { render text: @post.to_ics, mime_type: Mime::Type.lookup("text/calendar") }
# format.xml { render xml: @post }
# end
# end
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index cadbfc88cb..07b3814ca4 100644
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -50,7 +50,7 @@ module ActionDispatch
@original_fullpath = nil
@fullpath = nil
@ip = nil
- @uuid = nil
+ @request_id = nil
end
def check_path_parameters!
@@ -249,10 +249,12 @@ module ActionDispatch
#
# This unique ID is useful for tracing a request from end-to-end as part of logging or debugging.
# This relies on the rack variable set by the ActionDispatch::RequestId middleware.
- def uuid
- @uuid ||= env["action_dispatch.request_id"]
+ def request_id
+ @request_id ||= env["action_dispatch.request_id"]
end
+ alias_method :uuid, :request_id
+
# Returns the lowercase name of the HTTP server software.
def server_software
(@env['SERVER_SOFTWARE'] && /^([a-zA-Z]+)/ =~ @env['SERVER_SOFTWARE']) ? $1.downcase : nil
diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb
index 4061ea71a3..a895d1ab18 100644
--- a/actionpack/lib/action_dispatch/http/response.rb
+++ b/actionpack/lib/action_dispatch/http/response.rb
@@ -113,10 +113,10 @@ module ActionDispatch # :nodoc:
# The underlying body, as a streamable object.
attr_reader :stream
- def initialize(status = 200, header = {}, body = [])
+ def initialize(status = 200, header = {}, body = [], default_headers: self.class.default_headers)
super()
- header = merge_default_headers(header, self.class.default_headers)
+ header = merge_default_headers(header, default_headers)
self.body, self.header, self.status = body, header, status
@@ -308,9 +308,7 @@ module ActionDispatch # :nodoc:
end
def merge_default_headers(original, default)
- return original unless default.respond_to?(:merge)
-
- default.merge(original)
+ default.respond_to?(:merge) ? default.merge(original) : original
end
def build_buffer(response, body)
diff --git a/actionpack/lib/action_dispatch/journey/router.rb b/actionpack/lib/action_dispatch/journey/router.rb
index e9df984c86..2b036796ab 100644
--- a/actionpack/lib/action_dispatch/journey/router.rb
+++ b/actionpack/lib/action_dispatch/journey/router.rb
@@ -121,7 +121,6 @@ module ActionDispatch
end
def match_head_routes(routes, req)
- routes.delete_if { |route| route.verb == // }
head_routes = match_routes(routes, req)
if head_routes.empty?
diff --git a/actionpack/lib/action_dispatch/middleware/request_id.rb b/actionpack/lib/action_dispatch/middleware/request_id.rb
index 25658bac3d..b9ca524309 100644
--- a/actionpack/lib/action_dispatch/middleware/request_id.rb
+++ b/actionpack/lib/action_dispatch/middleware/request_id.rb
@@ -3,7 +3,7 @@ require 'active_support/core_ext/string/access'
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.
+ # ActionDispatch::Request#uuid or the alias ActionDispatch::Request#request_id) and sends the same id to the client via the X-Request-Id header.
#
# 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
@@ -12,19 +12,23 @@ module ActionDispatch
# The unique request id can be used to trace a request end-to-end and would typically end up being part of log files
# from multiple pieces of the stack.
class RequestId
+ X_REQUEST_ID = "X-Request-Id".freeze # :nodoc:
+ ACTION_DISPATCH_REQUEST_ID = "action_dispatch.request_id".freeze # :nodoc:
+ HTTP_X_REQUEST_ID = "HTTP_X_REQUEST_ID".freeze # :nodoc:
+
def initialize(app)
@app = app
end
def call(env)
- env["action_dispatch.request_id"] = external_request_id(env) || internal_request_id
- @app.call(env).tap { |_status, headers, _body| headers["X-Request-Id"] = env["action_dispatch.request_id"] }
+ env[ACTION_DISPATCH_REQUEST_ID] = external_request_id(env) || internal_request_id
+ @app.call(env).tap { |_status, headers, _body| headers[X_REQUEST_ID] = env[ACTION_DISPATCH_REQUEST_ID] }
end
private
def external_request_id(env)
- if request_id = env["HTTP_X_REQUEST_ID"].presence
- request_id.gsub(/[^\w\-]/, "").first(255)
+ if request_id = env[HTTP_X_REQUEST_ID].presence
+ request_id.gsub(/[^\w\-]/, "".freeze).first(255)
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/static.rb b/actionpack/lib/action_dispatch/middleware/static.rb
index 002bf8b11a..2e1bd45c3d 100644
--- a/actionpack/lib/action_dispatch/middleware/static.rb
+++ b/actionpack/lib/action_dispatch/middleware/static.rb
@@ -23,10 +23,9 @@ module ActionDispatch
def match?(path)
path = URI.parser.unescape(path)
return false unless path.valid_encoding?
+ path = Rack::Utils.clean_path_info path
- paths = [path, "#{path}#{ext}", "#{path}/index#{ext}"].map { |v|
- Rack::Utils.clean_path_info v
- }
+ paths = [path, "#{path}#{ext}", "#{path}/index#{ext}"]
if match = paths.detect { |p|
path = File.join(@root, p)
diff --git a/actionpack/lib/action_dispatch/middleware/templates/routes/_route.html.erb b/actionpack/lib/action_dispatch/middleware/templates/routes/_route.html.erb
index 24e44f31ac..6e995c85c1 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/routes/_route.html.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/routes/_route.html.erb
@@ -4,13 +4,13 @@
<%= route[:name] %><span class='helper'>_path</span>
<% end %>
</td>
- <td data-route-verb='<%= route[:verb] %>'>
+ <td>
<%= route[:verb] %>
</td>
- <td data-route-path='<%= route[:path] %>' data-regexp='<%= route[:regexp] %>'>
+ <td data-route-path='<%= route[:path] %>'>
<%= route[:path] %>
</td>
- <td data-route-reqs='<%= route[:reqs] %>'>
- <%= route[:reqs] %>
+ <td>
+ <%=simple_format 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
index 5cee0b5932..429ea7057c 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/routes/_table.html.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/routes/_table.html.erb
@@ -81,92 +81,87 @@
</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;
- }
+ // support forEarch iterator on NodeList
+ NodeList.prototype.forEach = Array.prototype.forEach;
// 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 there are any matched results in a section
+ function checkNoMatch(section, noMatchText) {
+ if (section.children.length <= 1) {
+ section.innerHTML += noMatchText;
+ }
}
- // 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);
+ // get JSON from url and invoke callback with result
+ function getJSON(url, success) {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', url);
+ xhr.onload = function() {
+ if (this.status == 200)
+ success(JSON.parse(this.response));
+ };
+ xhr.send();
}
- // 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));
+ function delayedKeyup(input, callback) {
+ var timeout;
+ input.onkeyup = function(){
+ if (timeout) clearTimeout(timeout);
+ timeout = setTimeout(callback, 300);
}
}
- // 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
+ // remove params or fragments
function sanitizePath(path) {
- var path = path.charAt(0) == '/' ? path : "/" + path;
- return path.replace(/\#.*|\?.*/, '');
+ 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');
+ var pathElements = document.querySelectorAll('#route_table [data-route-path]'),
+ searchElem = document.querySelector('#search'),
+ exactSection = document.querySelector('#exact_matches'),
+ fuzzySection = document.querySelector('#fuzzy_matches');
// Remove matches when no search value is present
searchElem.onblur = function(e) {
if (searchElem.value === "") {
- setContent(exactMatches, "");
- setContent(fuzzyMatches, "");
+ exactSection.innerHTML = "";
+ fuzzySection.innerHTML = "";
}
}
// 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>',
+ delayedKeyup(searchElem, function() {
+ var path = sanitizePath(searchElem.value),
+ defaultExactMatch = '<tr><th colspan="4">Paths Matching (' + path +'):</th></tr>',
+ defaultFuzzyMatch = '<tr><th colspan="4">Paths Containing (' + path +'):</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);
+ if (!path)
+ return searchElem.onblur();
- // Display exact matches and fuzzy matches
- each(regexpElems, function(elem) {
- checkExactMatch(exactMatches, elem, userInput);
- checkFuzzyMatch(fuzzyMatches, elem, userInput);
- })
+ getJSON('/rails/info/routes?path=' + path, function(matches){
+ // Clear out results section
+ exactSection.innerHTML = defaultExactMatch;
+ fuzzySection.innerHTML = defaultFuzzyMatch;
- // Display 'No Matches' message when no matches are found
- checkNoMatch(exactMatches, defaultExactMatch, noExactMatch);
- checkNoMatch(fuzzyMatches, defaultFuzzyMatch, noFuzzyMatch);
- }
+ // Display exact matches and fuzzy matches
+ pathElements.forEach(function(elem) {
+ var elemPath = elem.getAttribute('data-route-path');
+
+ if (matches['exact'].indexOf(elemPath) != -1)
+ exactSection.appendChild(elem.parentNode.cloneNode(true));
+
+ if (matches['fuzzy'].indexOf(elemPath) != -1)
+ fuzzySection.appendChild(elem.parentNode.cloneNode(true));
+ })
+
+ // Display 'No Matches' message when no matches are found
+ checkNoMatch(exactSection, noExactMatch);
+ checkNoMatch(fuzzySection, noFuzzyMatch);
+ })
+ })
}
// Enables functionality to toggle between `_path` and `_url` helper suffixes
@@ -174,19 +169,20 @@
// Sets content for each element
function setValOn(elems, val) {
- each(elems, function(elem) {
- setContent(elem, val);
+ elems.forEach(function(elem) {
+ elem.innerHTML = val;
});
}
// Sets onClick event for each element
function onClick(elems, func) {
- each(elems, function(elem) {
+ elems.forEach(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');
diff --git a/actionpack/lib/action_dispatch/routing/inspector.rb b/actionpack/lib/action_dispatch/routing/inspector.rb
index df5ebb6751..c513737fc2 100644
--- a/actionpack/lib/action_dispatch/routing/inspector.rb
+++ b/actionpack/lib/action_dispatch/routing/inspector.rb
@@ -28,23 +28,6 @@ module ActionDispatch
super.to_s
end
- def regexp
- __getobj__.path.to_regexp
- end
-
- def json_regexp
- str = regexp.inspect.
- sub('\\A' , '^').
- sub('\\Z' , '$').
- sub('\\z' , '$').
- sub(/^\// , '').
- sub(/\/[a-z]*$/ , '').
- gsub(/\(\?#.+\)/ , '').
- gsub(/\(\?-\w+:/ , '(').
- gsub(/\s/ , '')
- Regexp.new(str).source
- end
-
def reqs
@reqs ||= begin
reqs = endpoint
@@ -117,11 +100,10 @@ module ActionDispatch
end.reject(&:internal?).collect do |route|
collect_engine_routes(route)
- { name: route.name,
- verb: route.verb,
- path: route.path,
- reqs: route.reqs,
- regexp: route.json_regexp }
+ { name: route.name,
+ verb: route.verb,
+ path: route.path,
+ reqs: route.reqs }
end
end
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index f2c9e7b1a0..34b5b48f3a 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -1504,7 +1504,7 @@ module ActionDispatch
end
def using_match_shorthand?(path, options)
- path && (options[:to] || options[:action]).nil? && path =~ %r{/[\w/]+$}
+ path && (options[:to] || options[:action]).nil? && path =~ %r{^/?[-\w]+/[-\w/]+$}
end
def decomposed_match(path, options) # :nodoc:
diff --git a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb
index 2e116ea9cd..f2ce175cac 100644
--- a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb
+++ b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb
@@ -254,7 +254,7 @@ module ActionDispatch
@key_strategy.call model.model_name
end
- named_route = prefix + "#{name}_#{suffix}"
+ named_route = "#{prefix}#{name}_#{suffix}"
[named_route, args]
end
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index 65d6a5eb1e..ce04f0b08a 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -395,9 +395,11 @@ module ActionDispatch
return if MountedHelpers.method_defined?(name)
routes = self
+ helpers = routes.url_helpers
+
MountedHelpers.class_eval do
define_method "_#{name}" do
- RoutesProxy.new(routes, _routes_context)
+ RoutesProxy.new(routes, _routes_context, helpers)
end
end
diff --git a/actionpack/lib/action_dispatch/routing/routes_proxy.rb b/actionpack/lib/action_dispatch/routing/routes_proxy.rb
index e2393d3799..040ea04046 100644
--- a/actionpack/lib/action_dispatch/routing/routes_proxy.rb
+++ b/actionpack/lib/action_dispatch/routing/routes_proxy.rb
@@ -8,8 +8,9 @@ module ActionDispatch
attr_accessor :scope, :routes
alias :_routes :routes
- def initialize(routes, scope)
+ def initialize(routes, scope, helpers)
@routes, @scope = routes, scope
+ @helpers = helpers
end
def url_options
@@ -19,16 +20,16 @@ module ActionDispatch
end
def respond_to?(method, include_private = false)
- super || routes.url_helpers.respond_to?(method)
+ super || @helpers.respond_to?(method)
end
def method_missing(method, *args)
- if routes.url_helpers.respond_to?(method)
+ if @helpers.respond_to?(method)
self.class.class_eval <<-RUBY, __FILE__, __LINE__ + 1
def #{method}(*args)
options = args.extract_options!
args << url_options.merge((options || {}).symbolize_keys)
- routes.url_helpers.#{method}(*args)
+ @helpers.#{method}(*args)
end
RUBY
send(method, *args)
diff --git a/actionpack/lib/action_dispatch/testing/assertions/routing.rb b/actionpack/lib/action_dispatch/testing/assertions/routing.rb
index a927738b42..c94eea9134 100644
--- a/actionpack/lib/action_dispatch/testing/assertions/routing.rb
+++ b/actionpack/lib/action_dispatch/testing/assertions/routing.rb
@@ -38,18 +38,24 @@ module ActionDispatch
# # Test a custom route
# assert_recognizes({controller: 'items', action: 'show', id: '1'}, 'view/item1')
def assert_recognizes(expected_options, path, extras={}, msg=nil)
- request = recognized_request_for(path, extras, msg)
+ if path.is_a?(Hash) && path[:method].to_s == "all"
+ [:get, :post, :put, :delete].each do |method|
+ assert_recognizes(expected_options, path.merge(method: method), extras, msg)
+ end
+ else
+ request = recognized_request_for(path, extras, msg)
- expected_options = expected_options.clone
+ expected_options = expected_options.clone
- expected_options.stringify_keys!
+ expected_options.stringify_keys!
- msg = message(msg, "") {
- sprintf("The recognized options <%s> did not match <%s>, difference:",
- request.path_parameters, expected_options)
- }
+ msg = message(msg, "") {
+ sprintf("The recognized options <%s> did not match <%s>, difference:",
+ request.path_parameters, expected_options)
+ }
- assert_equal(expected_options, request.path_parameters, msg)
+ assert_equal(expected_options, request.path_parameters, msg)
+ end
end
# Asserts that the provided options can be used to generate the provided path. This is the inverse of +assert_recognizes+.
diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb
index 9b00616968..f7f898288b 100644
--- a/actionpack/lib/action_dispatch/testing/integration.rb
+++ b/actionpack/lib/action_dispatch/testing/integration.rb
@@ -369,7 +369,7 @@ module ActionDispatch
@request_count += 1
@request = ActionDispatch::Request.new(session.last_request.env)
response = _mock_session.last_response
- @response = ActionDispatch::TestResponse.new(response.status, response.headers, response.body)
+ @response = ActionDispatch::TestResponse.from_response(response)
@html_document = nil
@url_options = nil
@@ -388,16 +388,8 @@ module ActionDispatch
APP_SESSIONS = {}
- attr_reader :app
-
- def before_setup
- super
- @app = nil
- @integration_session = nil
- end
-
- def integration_session
- @integration_session ||= create_session(app)
+ def app
+ @app ||= nil
end
# Reset the current session. This is useful for testing multiple sessions
@@ -425,6 +417,8 @@ module ActionDispatch
%w(get post patch put head delete cookies assigns
xml_http_request xhr get_via_redirect post_via_redirect).each do |method|
define_method(method) do |*args|
+ reset! unless integration_session
+
# reset the html_document variable, except for cookies/assigns calls
unless method == 'cookies' || method == 'assigns'
@html_document = nil
@@ -456,16 +450,19 @@ module ActionDispatch
# Copy the instance variables from the current session instance into the
# test instance.
def copy_session_variables! #:nodoc:
+ return unless integration_session
@controller = @integration_session.controller
@response = @integration_session.response
@request = @integration_session.request
end
def default_url_options
+ reset! unless integration_session
integration_session.default_url_options
end
def default_url_options=(options)
+ reset! unless integration_session
integration_session.default_url_options = options
end
@@ -475,6 +472,7 @@ module ActionDispatch
# Delegate unhandled messages to the current session instance.
def method_missing(sym, *args, &block)
+ reset! unless integration_session
if integration_session.respond_to?(sym)
integration_session.__send__(sym, *args, &block).tap do
copy_session_variables!
@@ -483,6 +481,11 @@ module ActionDispatch
super
end
end
+
+ private
+ def integration_session
+ @integration_session ||= nil
+ end
end
end
@@ -659,6 +662,7 @@ module ActionDispatch
end
def url_options
+ reset! unless integration_session
integration_session.url_options
end
diff --git a/actionpack/lib/action_dispatch/testing/test_response.rb b/actionpack/lib/action_dispatch/testing/test_response.rb
index 369ea1467c..a9b88ac5fd 100644
--- a/actionpack/lib/action_dispatch/testing/test_response.rb
+++ b/actionpack/lib/action_dispatch/testing/test_response.rb
@@ -7,11 +7,7 @@ module ActionDispatch
# See Response for more information on controller response objects.
class TestResponse < Response
def self.from_response(response)
- new.tap do |resp|
- resp.status = response.status
- resp.headers = response.headers
- resp.body = response.body
- end
+ new response.status, response.headers, response.body, default_headers: nil
end
# Was the response successful?
@@ -25,12 +21,5 @@ module ActionDispatch
# Was there a server-side error?
alias_method :error?, :server_error?
-
- def merge_default_headers(original, *args)
- # Default headers are already applied, no need to merge them a second time.
- # This makes sure that default headers, removed in controller actions, will
- # not be reapplied to the test response.
- original
- end
end
end