aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack')
-rw-r--r--actionpack/CHANGELOG.md25
-rw-r--r--[-rwxr-xr-x]actionpack/Rakefile1
-rw-r--r--actionpack/lib/action_controller/caching/actions.rb6
-rw-r--r--actionpack/lib/action_controller/metal/data_streaming.rb54
-rw-r--r--actionpack/lib/action_controller/metal/params_wrapper.rb4
-rw-r--r--actionpack/lib/action_controller/metal/redirecting.rb10
-rw-r--r--actionpack/lib/action_controller/metal/renderers.rb11
-rw-r--r--actionpack/lib/action_controller/metal/streaming.rb6
-rw-r--r--actionpack/lib/action_controller/record_identifier.rb7
-rw-r--r--actionpack/lib/action_controller/test_case.rb38
-rw-r--r--actionpack/lib/action_controller/vendor/html-scanner/html/sanitizer.rb2
-rw-r--r--actionpack/lib/action_dispatch/http/headers.rb15
-rw-r--r--actionpack/lib/action_dispatch/http/mime_negotiation.rb2
-rw-r--r--actionpack/lib/action_dispatch/http/mime_type.rb10
-rw-r--r--actionpack/lib/action_dispatch/http/parameters.rb4
-rw-r--r--actionpack/lib/action_dispatch/http/response.rb2
-rw-r--r--actionpack/lib/action_dispatch/http/url.rb47
-rw-r--r--actionpack/lib/action_dispatch/middleware/cookies.rb21
-rw-r--r--actionpack/lib/action_dispatch/middleware/flash.rb12
-rw-r--r--actionpack/lib/action_dispatch/middleware/reloader.rb6
-rw-r--r--actionpack/lib/action_dispatch/middleware/remote_ip.rb90
-rw-r--r--actionpack/lib/action_dispatch/middleware/session/abstract_store.rb23
-rw-r--r--actionpack/lib/action_dispatch/middleware/stack.rb2
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/routing_error.erb4
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb33
-rw-r--r--actionpack/lib/action_dispatch/routing/polymorphic_routes.rb14
-rw-r--r--actionpack/lib/action_dispatch/routing/redirection.rb30
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb121
-rw-r--r--actionpack/lib/action_dispatch/testing/assertions/response.rb33
-rw-r--r--actionpack/lib/action_view/helpers/asset_tag_helper.rb2
-rw-r--r--actionpack/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb1
-rw-r--r--actionpack/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb2
-rw-r--r--actionpack/lib/action_view/helpers/date_helper.rb118
-rw-r--r--actionpack/lib/action_view/helpers/form_helper.rb12
-rw-r--r--actionpack/lib/action_view/helpers/javascript_helper.rb35
-rw-r--r--actionpack/lib/action_view/helpers/number_helper.rb6
-rw-r--r--actionpack/lib/action_view/helpers/record_tag_helper.rb6
-rw-r--r--actionpack/lib/action_view/helpers/tag_helper.rb6
-rw-r--r--actionpack/lib/action_view/helpers/tags/check_box.rb6
-rw-r--r--actionpack/lib/action_view/helpers/text_helper.rb25
-rw-r--r--actionpack/lib/action_view/helpers/translation_helper.rb16
-rw-r--r--actionpack/lib/action_view/renderer/partial_renderer.rb33
-rw-r--r--actionpack/test/abstract_unit.rb4
-rw-r--r--actionpack/test/activerecord/active_record_store_test.rb9
-rw-r--r--actionpack/test/activerecord/render_partial_with_record_identification_test.rb4
-rw-r--r--actionpack/test/controller/action_pack_assertions_test.rb24
-rw-r--r--actionpack/test/controller/base_test.rb14
-rw-r--r--actionpack/test/controller/caching_test.rb39
-rw-r--r--actionpack/test/controller/flash_test.rb2
-rw-r--r--actionpack/test/controller/integration_test.rb8
-rw-r--r--actionpack/test/controller/mime_responds_test.rb2
-rw-r--r--actionpack/test/controller/new_base/content_type_test.rb2
-rw-r--r--actionpack/test/controller/new_base/render_template_test.rb2
-rw-r--r--actionpack/test/controller/new_base/render_test.rb4
-rw-r--r--actionpack/test/controller/new_base/render_text_test.rb4
-rw-r--r--actionpack/test/controller/redirect_test.rb4
-rw-r--r--actionpack/test/controller/render_json_test.rb2
-rw-r--r--actionpack/test/controller/render_test.rb2
-rw-r--r--actionpack/test/controller/render_xml_test.rb2
-rw-r--r--actionpack/test/controller/rescue_test.rb11
-rw-r--r--actionpack/test/controller/resources_test.rb4
-rw-r--r--actionpack/test/controller/routing_test.rb354
-rw-r--r--actionpack/test/controller/send_file_test.rb11
-rw-r--r--actionpack/test/controller/test_case_test.rb93
-rw-r--r--actionpack/test/controller/url_for_integration_test.rb32
-rw-r--r--actionpack/test/controller/url_for_test.rb16
-rw-r--r--actionpack/test/controller/url_rewriter_test.rb2
-rw-r--r--actionpack/test/controller/webservice_test.rb2
-rw-r--r--actionpack/test/dispatch/cookies_test.rb44
-rw-r--r--actionpack/test/dispatch/header_test.rb5
-rw-r--r--actionpack/test/dispatch/mapper_test.rb19
-rw-r--r--actionpack/test/dispatch/prefix_generation_test.rb26
-rw-r--r--actionpack/test/dispatch/request/json_params_parsing_test.rb4
-rw-r--r--actionpack/test/dispatch/request/multipart_params_parsing_test.rb2
-rw-r--r--actionpack/test/dispatch/request/query_string_parsing_test.rb2
-rw-r--r--actionpack/test/dispatch/request/url_encoded_params_parsing_test.rb2
-rw-r--r--actionpack/test/dispatch/request/xml_params_parsing_test.rb4
-rw-r--r--actionpack/test/dispatch/request_id_test.rb4
-rw-r--r--actionpack/test/dispatch/request_test.rb134
-rw-r--r--actionpack/test/dispatch/routing_test.rb185
-rw-r--r--actionpack/test/dispatch/session/cache_store_test.rb2
-rw-r--r--actionpack/test/dispatch/session/cookie_store_test.rb2
-rw-r--r--actionpack/test/dispatch/session/mem_cache_store_test.rb2
-rw-r--r--actionpack/test/dispatch/url_generation_test.rb2
-rw-r--r--actionpack/test/fixtures/test/_b_layout_for_partial_with_object.html.erb1
-rw-r--r--actionpack/test/fixtures/test/_b_layout_for_partial_with_object_counter.html.erb1
-rw-r--r--actionpack/test/fixtures/translations/templates/default.erb1
-rw-r--r--actionpack/test/template/date_helper_i18n_test.rb41
-rw-r--r--actionpack/test/template/date_helper_test.rb138
-rw-r--r--actionpack/test/template/form_helper_test.rb119
-rw-r--r--actionpack/test/template/javascript_helper_test.rb30
-rw-r--r--actionpack/test/template/render_test.rb74
-rw-r--r--actionpack/test/template/tag_helper_test.rb5
-rw-r--r--actionpack/test/template/test_test.rb2
-rw-r--r--actionpack/test/template/translation_helper_test.rb25
-rw-r--r--actionpack/test/template/url_helper_test.rb18
96 files changed, 1570 insertions, 878 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index 32630e5ded..96dee33f7b 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,5 +1,28 @@
## Rails 4.0.0 (unreleased) ##
+* Allows `assert_redirected_to` to match against a regular expression. *Andy Lindeman*
+
+* Add backtrace to development routing error page. *Richard Schneeman*
+
+* Replace `include_seconds` boolean argument with `:include_seconds => true` option
+ in `distance_of_time_in_words` and `time_ago_in_words` signature. *Dmitriy Kiriyenko*
+
+* Remove `button_to_function` and `link_to_function` helpers. *Rafael Mendonça França*
+
+* Make current object and counter (when it applies) variables accessible when
+ rendering templates with :object / :collection. *Carlos Antonio da Silva*
+
+* JSONP now uses mimetype application/javascript instead of application/json *omjokine*
+
+* Allow to lazy load `default_form_builder` by passing a `String` instead of a constant. *Piotr Sarnacki*
+
+* Session arguments passed to `process` calls in functional tests are now merged into
+ the existing session, whereas previously they would replace the existing session.
+ This change may break some existing tests if they are asserting the exact contents of
+ the session but should not break existing tests that only assert individual keys.
+
+ *Andrew White*
+
* Add `index` method to FormBuilder class. *Jorge Bejar*
* Remove the leading \n added by textarea on assert_select. *Santiago Pastorino*
@@ -135,7 +158,7 @@
HTML5 `mark` element. *Brian Cardarella*
-## Rails 3.2.3 (unreleased) ##
+## Rails 3.2.3 (March 30, 2012) ##
* Add `config.action_view.embed_authenticity_token_in_remote_forms` (defaults to true) which allows to set if authenticity token will be included by default in remote forms. If you change it to false, you can still force authenticity token by passing `:authenticity_token => true` in form options *Piotr Sarnacki*
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index bb1e704767..17d95bfd1d 100755..100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -1,4 +1,3 @@
-#!/usr/bin/env rake
require 'rake/testtask'
require 'rake/packagetask'
require 'rubygems/package_task'
diff --git a/actionpack/lib/action_controller/caching/actions.rb b/actionpack/lib/action_controller/caching/actions.rb
index 59ec197347..80901b8bf3 100644
--- a/actionpack/lib/action_controller/caching/actions.rb
+++ b/actionpack/lib/action_controller/caching/actions.rb
@@ -133,6 +133,8 @@ module ActionController #:nodoc:
end
def filter(controller)
+ cache_layout = @cache_layout.respond_to?(:call) ? @cache_layout.call(controller) : @cache_layout
+
path_options = if @cache_path.respond_to?(:call)
controller.instance_exec(controller, &@cache_path)
else
@@ -144,13 +146,13 @@ module ActionController #:nodoc:
body = controller.read_fragment(cache_path.path, @store_options)
unless body
- controller.action_has_layout = false unless @cache_layout
+ controller.action_has_layout = false unless cache_layout
yield
controller.action_has_layout = true
body = controller._save_fragment(cache_path.path, @store_options)
end
- body = controller.render_to_string(:text => body, :layout => true) unless @cache_layout
+ body = controller.render_to_string(:text => body, :layout => true) unless cache_layout
controller.response_body = body
controller.content_type = Mime[cache_path.extension || :html]
diff --git a/actionpack/lib/action_controller/metal/data_streaming.rb b/actionpack/lib/action_controller/metal/data_streaming.rb
index 6f520b1054..379ff97048 100644
--- a/actionpack/lib/action_controller/metal/data_streaming.rb
+++ b/actionpack/lib/action_controller/metal/data_streaming.rb
@@ -8,15 +8,13 @@ module ActionController #:nodoc:
include ActionController::Rendering
- DEFAULT_SEND_FILE_OPTIONS = {
- :type => 'application/octet-stream'.freeze,
- :disposition => 'attachment'.freeze,
- }.freeze
+ DEFAULT_SEND_FILE_TYPE = 'application/octet-stream'.freeze #:nodoc:
+ DEFAULT_SEND_FILE_DISPOSITION = 'attachment'.freeze #:nodoc:
protected
# Sends the file. This uses a server-appropriate method (such as X-Sendfile)
# via the Rack::Sendfile middleware. The header to use is set via
- # config.action_dispatch.x_sendfile_header.
+ # +config.action_dispatch.x_sendfile_header+.
# Your server can also configure this for you by setting the X-Sendfile-Type header.
#
# Be careful to sanitize the path parameter if it is coming from a web
@@ -74,7 +72,27 @@ module ActionController #:nodoc:
self.status = options[:status] || 200
self.content_type = options[:content_type] if options.key?(:content_type)
- self.response_body = File.open(path, "rb")
+ self.response_body = FileBody.new(path)
+ end
+
+ # Avoid having to pass an open file handle as the response body.
+ # Rack::Sendfile will usually intercepts the response and just uses
+ # the path directly, so no reason to open the file.
+ class FileBody #:nodoc:
+ attr_reader :to_path
+
+ def initialize(path)
+ @to_path = path
+ end
+
+ # Stream the file's contents if Rack::Sendfile isn't present.
+ def each
+ File.open(to_path, 'rb') do |file|
+ while chunk = file.read(16384)
+ yield chunk
+ end
+ end
+ end
end
# Sends the given binary data to the browser. This method is similar to
@@ -107,7 +125,7 @@ module ActionController #:nodoc:
#
# See +send_file+ for more information on HTTP Content-* headers and caching.
def send_data(data, options = {}) #:doc:
- send_file_headers! options.dup
+ send_file_headers! options
render options.slice(:status, :content_type).merge(:text => data)
end
@@ -115,15 +133,8 @@ module ActionController #:nodoc:
def send_file_headers!(options)
type_provided = options.has_key?(:type)
- options.update(DEFAULT_SEND_FILE_OPTIONS.merge(options))
- [:type, :disposition].each do |arg|
- raise ArgumentError, ":#{arg} option required" if options[arg].nil?
- end
-
- disposition = options[:disposition]
- disposition += %(; filename="#{options[:filename]}") if options[:filename]
-
- content_type = options[:type]
+ content_type = options.fetch(:type, DEFAULT_SEND_FILE_TYPE)
+ raise ArgumentError, ":type option required" if content_type.nil?
if content_type.is_a?(Symbol)
extension = Mime[content_type]
@@ -137,10 +148,13 @@ module ActionController #:nodoc:
self.content_type = content_type
end
- headers.merge!(
- 'Content-Disposition' => disposition,
- 'Content-Transfer-Encoding' => 'binary'
- )
+ disposition = options.fetch(:disposition, DEFAULT_SEND_FILE_DISPOSITION)
+ unless disposition.nil?
+ disposition += %(; filename="#{options[:filename]}") if options[:filename]
+ headers['Content-Disposition'] = disposition
+ end
+
+ headers['Content-Transfer-Encoding'] = 'binary'
response.sending_file = true
diff --git a/actionpack/lib/action_controller/metal/params_wrapper.rb b/actionpack/lib/action_controller/metal/params_wrapper.rb
index fa760f2658..7e2316d01c 100644
--- a/actionpack/lib/action_controller/metal/params_wrapper.rb
+++ b/actionpack/lib/action_controller/metal/params_wrapper.rb
@@ -48,7 +48,7 @@ module ActionController
# method attribute_names.
#
# If you're going to pass the parameters to an +ActiveModel+ object (such as
- # +User.new(params[:user])+), you might consider passing the model class to
+ # <tt>User.new(params[:user])</tt>), you might consider passing the model class to
# the method instead. The +ParamsWrapper+ will actually try to determine the
# list of attribute names from the model and only wrap those attributes:
#
@@ -66,7 +66,7 @@ module ActionController
# class Admin::UsersController < ApplicationController
# end
#
- # will try to check if +Admin::User+ or +User+ model exists, and use it to
+ # will try to check if <tt>Admin::User</tt> or +User+ model exists, and use it to
# determine the wrapper key respectively. If both models don't exist,
# it will then fallback to use +user+ as the key.
module ParamsWrapper
diff --git a/actionpack/lib/action_controller/metal/redirecting.rb b/actionpack/lib/action_controller/metal/redirecting.rb
index 35ded8a56c..5e7bd44562 100644
--- a/actionpack/lib/action_controller/metal/redirecting.rb
+++ b/actionpack/lib/action_controller/metal/redirecting.rb
@@ -45,6 +45,16 @@ module ActionController
# integer, or a symbol representing the downcased, underscored and symbolized description.
# Note that the status code must be a 3xx HTTP code, or redirection will not occur.
#
+ # If you are using XHR requests other than GET or POST and redirecting after the
+ # request then some browsers will follow the redirect using the original request
+ # method. This may lead to undesirable behavior such as a double DELETE. To work
+ # around this you can return a <tt>303 See Other</tt> status code which will be
+ # followed using a GET request.
+ #
+ # Examples:
+ # redirect_to posts_url, :status => :see_other
+ # redirect_to :action => 'index', :status => 303
+ #
# It is also possible to assign a flash message as part of the redirection. There are two special accessors for the commonly used flash names
# +alert+ and +notice+ as well as a general purpose +flash+ bucket.
#
diff --git a/actionpack/lib/action_controller/metal/renderers.rb b/actionpack/lib/action_controller/metal/renderers.rb
index 6e9ce450ac..4a0c1c7dd7 100644
--- a/actionpack/lib/action_controller/metal/renderers.rb
+++ b/actionpack/lib/action_controller/metal/renderers.rb
@@ -91,9 +91,14 @@ module ActionController
add :json do |json, options|
json = json.to_json(options) unless json.kind_of?(String)
- json = "#{options[:callback]}(#{json})" unless options[:callback].blank?
- self.content_type ||= Mime::JSON
- json
+
+ if options[:callback].present?
+ self.content_type ||= Mime::JS
+ "#{options[:callback]}(#{json})"
+ else
+ self.content_type ||= Mime::JSON
+ json
+ end
end
add :js do |js, options|
diff --git a/actionpack/lib/action_controller/metal/streaming.rb b/actionpack/lib/action_controller/metal/streaming.rb
index 52aaed0ed4..eeb37db2e7 100644
--- a/actionpack/lib/action_controller/metal/streaming.rb
+++ b/actionpack/lib/action_controller/metal/streaming.rb
@@ -139,17 +139,17 @@ module ActionController #:nodoc:
# session or flash after the template starts rendering will not propagate
# to the client.
#
- # If you try to modify cookies, session or flash, an +ActionDispatch::ClosedError+
+ # If you try to modify cookies, session or flash, an <tt>ActionDispatch::ClosedError</tt>
# will be raised, showing those objects are closed for modification.
#
# == Middlewares
#
# Middlewares that need to manipulate the body won't work with streaming.
# You should disable those middlewares whenever streaming in development
- # or production. For instance, +Rack::Bug+ won't work when streaming as it
+ # or production. For instance, <tt>Rack::Bug</tt> won't work when streaming as it
# needs to inject contents in the HTML body.
#
- # Also +Rack::Cache+ won't work with streaming as it does not support
+ # Also <tt>Rack::Cache</tt> won't work with streaming as it does not support
# streaming bodies yet. Whenever streaming Cache-Control is automatically
# set to "no-cache".
#
diff --git a/actionpack/lib/action_controller/record_identifier.rb b/actionpack/lib/action_controller/record_identifier.rb
index 5c40889f6b..e7af3f5b8d 100644
--- a/actionpack/lib/action_controller/record_identifier.rb
+++ b/actionpack/lib/action_controller/record_identifier.rb
@@ -75,12 +75,7 @@ module ActionController
def record_key_for_dom_id(record)
record = record.to_model if record.respond_to?(:to_model)
key = record.to_key
- key ? sanitize_dom_id(key.join('_')) : key
- end
-
- # Replaces characters that are invalid in HTML DOM ids with valid ones.
- def sanitize_dom_id(candidate_id)
- candidate_id # TODO implement conversion to valid DOM id values
+ key ? key.join('_') : key
end
end
end
diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb
index 9bd2e622ad..21997c4d79 100644
--- a/actionpack/lib/action_controller/test_case.rb
+++ b/actionpack/lib/action_controller/test_case.rb
@@ -27,13 +27,13 @@ module ActionController
path = payload[:virtual_path]
next unless path
partial = path =~ /^.*\/_[^\/]*$/
+
if partial
@partials[path] += 1
@partials[path.split("/").last] += 1
- @templates[path] += 1
- else
- @templates[path] += 1
end
+
+ @templates[path] += 1
end
end
@@ -140,9 +140,6 @@ module ActionController
class Result < ::Array #:nodoc:
def to_s() join '/' end
- def self.new_escaped(strings)
- new strings.collect {|str| uri_parser.unescape str}
- end
end
def assign_parameters(routes, controller_path, action, parameters = {})
@@ -150,17 +147,23 @@ module ActionController
extra_keys = routes.extra_keys(parameters)
non_path_parameters = get? ? query_parameters : request_parameters
parameters.each do |key, value|
- if value.is_a? Fixnum
- value = value.to_s
- elsif value.is_a? Array
- value = Result.new(value.map { |v| v.is_a?(String) ? v.dup : v })
- elsif value.is_a? String
+ if value.is_a?(Array) && (value.frozen? || value.any?(&:frozen?))
+ value = value.map{ |v| v.duplicable? ? v.dup : v }
+ elsif value.is_a?(Hash) && (value.frozen? || value.any?{ |k,v| v.frozen? })
+ value = Hash[value.map{ |k,v| [k, v.duplicable? ? v.dup : v] }]
+ elsif value.frozen? && value.duplicable?
value = value.dup
end
if extra_keys.include?(key.to_sym)
non_path_parameters[key] = value
else
+ if value.is_a?(Array)
+ value = Result.new(value.map(&:to_param))
+ else
+ value = value.to_param
+ end
+
path_parameters[key.to_s] = value
end
end
@@ -456,7 +459,7 @@ module ActionController
# Ensure that numbers and symbols passed as params are converted to
# proper params, as is the case when engaging rack.
- parameters = paramify_values(parameters)
+ parameters = paramify_values(parameters) if html_format?(parameters)
@request.recycle!
@response.recycle!
@@ -469,14 +472,13 @@ module ActionController
parameters ||= {}
controller_class_name = @controller.class.anonymous? ?
- "anonymous_controller" :
+ "anonymous" :
@controller.class.name.underscore.sub(/_controller$/, '')
@request.assign_parameters(@routes, controller_class_name, action.to_s, parameters)
- @request.session = ActionController::TestSession.new(session) if session
+ @request.session.update(session) if session
@request.session["flash"] = @request.flash.update(flash || {})
- @request.session["flash"].sweep
@controller.request = @request
build_request_uri(action, parameters)
@@ -549,6 +551,12 @@ module ActionController
@request.env["QUERY_STRING"] = query_string || ""
end
end
+
+ def html_format?(parameters)
+ return true unless parameters.is_a?(Hash)
+ format = Mime[parameters[:format]]
+ format.nil? || format.html?
+ end
end
# When the request.remote_addr remains the default for testing, which is 0.0.0.0, the exception is simply raised inline
diff --git a/actionpack/lib/action_controller/vendor/html-scanner/html/sanitizer.rb b/actionpack/lib/action_controller/vendor/html-scanner/html/sanitizer.rb
index e9b50ff8ce..114b0e73c9 100644
--- a/actionpack/lib/action_controller/vendor/html-scanner/html/sanitizer.rb
+++ b/actionpack/lib/action_controller/vendor/html-scanner/html/sanitizer.rb
@@ -99,7 +99,7 @@ module HTML
self.allowed_protocols = Set.new(%w(ed2k ftp http https irc mailto news gopher nntp telnet webcal xmpp callto
feed svn urn aim rsync tag ssh sftp rtsp afs))
- # Specifies the default Set of acceptable css keywords that #sanitize and #sanitize_css will accept.
+ # Specifies the default Set of acceptable css properties that #sanitize and #sanitize_css will accept.
self.allowed_css_properties = Set.new(%w(azimuth background-color border-bottom-color border-collapse
border-color border-left-color border-right-color border-top-color clear color cursor direction display
elevation float font font-family font-size font-style font-variant font-weight height letter-spacing line-height
diff --git a/actionpack/lib/action_dispatch/http/headers.rb b/actionpack/lib/action_dispatch/http/headers.rb
index 040b51e040..a3bb25f75a 100644
--- a/actionpack/lib/action_dispatch/http/headers.rb
+++ b/actionpack/lib/action_dispatch/http/headers.rb
@@ -14,17 +14,18 @@ module ActionDispatch
end
def [](header_name)
- if include?(header_name)
- super
- else
- super(env_name(header_name))
- end
+ super env_name(header_name)
+ end
+
+ def fetch(header_name, default=nil, &block)
+ super env_name(header_name), default, &block
end
private
- # Converts a HTTP header name to an environment variable name.
+ # Converts a HTTP header name to an environment variable name if it is
+ # not contained within the headers hash.
def env_name(header_name)
- @@env_cache[header_name]
+ include?(header_name) ? header_name : @@env_cache[header_name]
end
end
end
diff --git a/actionpack/lib/action_dispatch/http/mime_negotiation.rb b/actionpack/lib/action_dispatch/http/mime_negotiation.rb
index 5c48a60469..e31f3b823d 100644
--- a/actionpack/lib/action_dispatch/http/mime_negotiation.rb
+++ b/actionpack/lib/action_dispatch/http/mime_negotiation.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/module/attribute_accessors'
+
module ActionDispatch
module Http
module MimeNegotiation
diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb
index 26f4c16218..0eaae80461 100644
--- a/actionpack/lib/action_dispatch/http/mime_type.rb
+++ b/actionpack/lib/action_dispatch/http/mime_type.rb
@@ -179,11 +179,11 @@ module Mime
end
end
- # input: 'text'
- # returned value: [Mime::JSON, Mime::XML, Mime::ICS, Mime::HTML, Mime::CSS, Mime::CSV, Mime::JS, Mime::YAML, Mime::TEXT]
+ # For an input of <tt>'text'</tt>, returns <tt>[Mime::JSON, Mime::XML, Mime::ICS,
+ # Mime::HTML, Mime::CSS, Mime::CSV, Mime::JS, Mime::YAML, Mime::TEXT]</tt>.
#
- # input: 'application'
- # returned value: [Mime::HTML, Mime::JS, Mime::XML, Mime::YAML, Mime::ATOM, Mime::JSON, Mime::RSS, Mime::URL_ENCODED_FORM]
+ # For an input of <tt>'application'</tt>, returns <tt>[Mime::HTML, Mime::JS,
+ # Mime::XML, Mime::YAML, Mime::ATOM, Mime::JSON, Mime::RSS, Mime::URL_ENCODED_FORM]</tt>.
def parse_data_with_trailing_star(input)
Mime::SET.select { |m| m =~ input }
end
@@ -192,7 +192,7 @@ module Mime
#
# Usage:
#
- # Mime::Type.unregister(:mobile)
+ # Mime::Type.unregister(:mobile)
def unregister(symbol)
symbol = symbol.to_s.upcase
mime = Mime.const_get(symbol)
diff --git a/actionpack/lib/action_dispatch/http/parameters.rb b/actionpack/lib/action_dispatch/http/parameters.rb
index d9b63faf5e..bcfd0b0d00 100644
--- a/actionpack/lib/action_dispatch/http/parameters.rb
+++ b/actionpack/lib/action_dispatch/http/parameters.rb
@@ -35,6 +35,10 @@ module ActionDispatch
@env["action_dispatch.request.path_parameters"] ||= {}
end
+ def reset_parameters #:nodoc:
+ @env.delete("action_dispatch.request.parameters")
+ end
+
private
# TODO: Validate that the characters are UTF-8. If they aren't,
diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb
index 078229efd2..cc46f9983c 100644
--- a/actionpack/lib/action_dispatch/http/response.rb
+++ b/actionpack/lib/action_dispatch/http/response.rb
@@ -29,7 +29,7 @@ module ActionDispatch # :nodoc:
# class DemoControllerTest < ActionDispatch::IntegrationTest
# def test_print_root_path_to_console
# get('/')
- # puts @response.body
+ # puts response.body
# end
# end
class Response
diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb
index f9dae5dad7..4266ec042e 100644
--- a/actionpack/lib/action_dispatch/http/url.rb
+++ b/actionpack/lib/action_dispatch/http/url.rb
@@ -23,23 +23,6 @@ module ActionDispatch
end
def url_for(options = {})
- if options[:host].blank? && options[:only_path].blank?
- raise ArgumentError, 'Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true'
- end
-
- rewritten_url = ""
-
- unless options[:only_path]
- unless options[:protocol] == false
- rewritten_url << (options[:protocol] || "http")
- rewritten_url << ":" unless rewritten_url.match(%r{:|//})
- end
- rewritten_url << "//" unless rewritten_url.match("//")
- rewritten_url << rewrite_authentication(options)
- rewritten_url << host_or_subdomain_and_domain(options)
- rewritten_url << ":#{options.delete(:port)}" if options[:port]
- end
-
path = ""
path << options.delete(:script_name).to_s.chomp("/")
path << options.delete(:path).to_s
@@ -47,14 +30,36 @@ module ActionDispatch
params = options[:params] || {}
params.reject! {|k,v| v.to_param.nil? }
- rewritten_url << (options[:trailing_slash] ? path.sub(/\?|\z/) { "/" + $& } : path)
- rewritten_url << "?#{params.to_query}" unless params.empty?
- rewritten_url << "##{Journey::Router::Utils.escape_fragment(options[:anchor].to_param.to_s)}" if options[:anchor]
- rewritten_url
+ result = build_host_url(options)
+
+ result << (options[:trailing_slash] ? path.sub(/\?|\z/) { "/" + $& } : path)
+ result << "?#{params.to_query}" unless params.empty?
+ result << "##{Journey::Router::Utils.escape_fragment(options[:anchor].to_param.to_s)}" if options[:anchor]
+ result
end
private
+ def build_host_url(options)
+ if options[:host].blank? && options[:only_path].blank?
+ 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 = ""
+
+ unless options[:only_path]
+ unless options[:protocol] == false
+ result << (options[:protocol] || "http")
+ result << ":" unless result.match(%r{:|//})
+ end
+ result << "//" unless result.match("//")
+ result << rewrite_authentication(options)
+ result << host_or_subdomain_and_domain(options)
+ result << ":#{options.delete(:port)}" if options[:port]
+ end
+ result
+ end
+
def named_host?(host)
host && IP_HOST_REGEXP !~ host
end
diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb
index 0c717c8503..2c0c31de9d 100644
--- a/actionpack/lib/action_dispatch/middleware/cookies.rb
+++ b/actionpack/lib/action_dispatch/middleware/cookies.rb
@@ -82,7 +82,7 @@ module ActionDispatch
TOKEN_KEY = "action_dispatch.secret_token".freeze
# Raised when storing more than 4K of session data.
- class CookieOverflow < StandardError; end
+ CookieOverflow = Class.new StandardError
class CookieJar #:nodoc:
include Enumerable
@@ -117,7 +117,6 @@ module ActionDispatch
@delete_cookies = {}
@host = host
@secure = secure
- @closed = false
@cookies = {}
end
@@ -154,7 +153,7 @@ module ActionDispatch
end
elsif options[:domain].is_a? Array
# if host matches one of the supplied domains without a dot in front of it
- options[:domain] = options[:domain].find {|domain| @host.include? domain[/^\.?(.*)$/, 1] }
+ options[:domain] = options[:domain].find {|domain| @host.include? domain.sub(/^\./, '') }
end
end
@@ -169,12 +168,14 @@ module ActionDispatch
options = { :value => value }
end
- @cookies[key.to_s] = value
-
handle_options(options)
- @set_cookies[key.to_s] = options
- @delete_cookies.delete(key.to_s)
+ if @cookies[key.to_s] != value or options[:expires]
+ @cookies[key.to_s] = value
+ @set_cookies[key.to_s] = options
+ @delete_cookies.delete(key.to_s)
+ end
+
value
end
@@ -182,8 +183,9 @@ module ActionDispatch
# and setting its expiration date into the past. Like <tt>[]=</tt>, you can pass in
# an options hash to delete cookies with extra data such as a <tt>:path</tt>.
def delete(key, options = {})
- options.symbolize_keys!
+ return unless @cookies.has_key? key.to_s
+ options.symbolize_keys!
handle_options(options)
value = @cookies.delete(key.to_s)
@@ -225,7 +227,7 @@ module ActionDispatch
# cookie was tampered with by the user (or a 3rd party), an ActiveSupport::MessageVerifier::InvalidSignature exception will
# be raised.
#
- # This jar requires that you set a suitable secret for the verification on your app's config.secret_token.
+ # This jar requires that you set a suitable secret for the verification on your app's +config.secret_token+.
#
# Example:
#
@@ -339,7 +341,6 @@ module ActionDispatch
end
def call(env)
- cookie_jar = nil
status, headers, body = @app.call(env)
if cookie_jar = env['action_dispatch.cookies']
diff --git a/actionpack/lib/action_dispatch/middleware/flash.rb b/actionpack/lib/action_dispatch/middleware/flash.rb
index cff0877030..fd0ce62a3b 100644
--- a/actionpack/lib/action_dispatch/middleware/flash.rb
+++ b/actionpack/lib/action_dispatch/middleware/flash.rb
@@ -4,7 +4,7 @@ module ActionDispatch
# read a notice you put there or <tt>flash["notice"] = "hello"</tt>
# to put a new one.
def flash
- @env[Flash::KEY] ||= (session["flash"] || Flash::FlashHash.new)
+ @env[Flash::KEY] ||= (session["flash"] || Flash::FlashHash.new).tap(&:sweep)
end
end
@@ -17,7 +17,7 @@ module ActionDispatch
# def create
# # save post
# flash[:notice] = "Post successfully created"
- # redirect_to posts_path(@post)
+ # redirect_to @post
# end
#
# def show
@@ -79,7 +79,6 @@ module ActionDispatch
def initialize #:nodoc:
@discard = Set.new
- @closed = false
@flashes = {}
@now = nil
end
@@ -217,10 +216,6 @@ module ActionDispatch
end
def call(env)
- if (session = env['rack.session']) && (flash = session['flash'])
- flash.sweep
- end
-
@app.call(env)
ensure
session = env['rack.session'] || {}
@@ -237,7 +232,8 @@ module ActionDispatch
env[KEY] = new_hash
end
- if session.key?('flash') && session['flash'].empty?
+ if (!session.respond_to?(:loaded?) || session.loaded?) && # (reset_session uses {}, which doesn't implement #loaded?)
+ session.key?('flash') && session['flash'].empty?
session.delete('flash')
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/reloader.rb b/actionpack/lib/action_dispatch/middleware/reloader.rb
index a0388e0e13..2f6968eb2e 100644
--- a/actionpack/lib/action_dispatch/middleware/reloader.rb
+++ b/actionpack/lib/action_dispatch/middleware/reloader.rb
@@ -18,10 +18,10 @@ module ActionDispatch
# classes before they are unloaded.
#
# By default, ActionDispatch::Reloader is included in the middleware stack
- # only in the development environment; specifically, when config.cache_classes
+ # only in the development environment; specifically, when +config.cache_classes+
# is false. Callbacks may be registered even when it is not included in the
- # middleware stack, but are executed only when +ActionDispatch::Reloader.prepare!+
- # or +ActionDispatch::Reloader.cleanup!+ are called manually.
+ # middleware stack, but are executed only when <tt>ActionDispatch::Reloader.prepare!</tt>
+ # or <tt>ActionDispatch::Reloader.cleanup!</tt> are called manually.
#
class Reloader
include ActiveSupport::Callbacks
diff --git a/actionpack/lib/action_dispatch/middleware/remote_ip.rb b/actionpack/lib/action_dispatch/middleware/remote_ip.rb
index d924f21fad..ec15a2a715 100644
--- a/actionpack/lib/action_dispatch/middleware/remote_ip.rb
+++ b/actionpack/lib/action_dispatch/middleware/remote_ip.rb
@@ -5,11 +5,14 @@ module ActionDispatch
# IP addresses that are "trusted proxies" that can be stripped from
# the comma-delimited list in the X-Forwarded-For header. See also:
# http://en.wikipedia.org/wiki/Private_network#Private_IPv4_address_spaces
+ # http://en.wikipedia.org/wiki/Private_network#Private_IPv6_addresses.
TRUSTED_PROXIES = %r{
^127\.0\.0\.1$ | # localhost
+ ^::1$ |
^(10 | # private IP 10.x.x.x
172\.(1[6-9]|2[0-9]|3[0-1]) | # private IP in the range 172.16.0.0 .. 172.31.255.255
- 192\.168 # private IP 192.168.x.x
+ 192\.168 | # private IP 192.168.x.x
+ fc00:: # private IP fc00
)\.
}x
@@ -19,13 +22,13 @@ module ActionDispatch
@app = app
@check_ip = check_ip_spoofing
@proxies = case custom_proxies
- when Regexp
- custom_proxies
- when nil
- TRUSTED_PROXIES
- else
- Regexp.union(TRUSTED_PROXIES, custom_proxies)
- end
+ when Regexp
+ custom_proxies
+ when nil
+ TRUSTED_PROXIES
+ else
+ Regexp.union(TRUSTED_PROXIES, custom_proxies)
+ end
end
def call(env)
@@ -34,6 +37,31 @@ module ActionDispatch
end
class GetIp
+
+ # IP v4 and v6 (with compression) validation regexp
+ # https://gist.github.com/1289635
+ VALID_IP = %r{
+ (^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9]{1,2})(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9]{1,2})){3}$) | # ip v4
+ (^(
+ (([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4}) | # ip v6 not abbreviated
+ (([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4}) | # ip v6 with double colon in the end
+ (([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4}) | # - ip addresses v6
+ (([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4}) | # - with
+ (([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4}) | # - double colon
+ (([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4}) | # - in the middle
+ (([0-9A-Fa-f]{1,4}:){6} ((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3} (\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)) | # ip v6 with compatible to v4
+ (([0-9A-Fa-f]{1,4}:){1,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)) | # ip v6 with compatible to v4
+ (([0-9A-Fa-f]{1,4}:){1}:([0-9A-Fa-f]{1,4}:){0,4}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)) | # ip v6 with compatible to v4
+ (([0-9A-Fa-f]{1,4}:){0,2}:([0-9A-Fa-f]{1,4}:){0,3}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)) | # ip v6 with compatible to v4
+ (([0-9A-Fa-f]{1,4}:){0,3}:([0-9A-Fa-f]{1,4}:){0,2}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)) | # ip v6 with compatible to v4
+ (([0-9A-Fa-f]{1,4}:){0,4}:([0-9A-Fa-f]{1,4}:){1}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)) | # ip v6 with compatible to v4
+ (::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d) |(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)) | # ip v6 with compatible to v4
+ ([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4}) | # ip v6 with compatible to v4
+ (::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4}) | # ip v6 with double colon at the begining
+ (([0-9A-Fa-f]{1,4}:){1,7}:) # ip v6 without ending
+ )$)
+ }x
+
def initialize(env, middleware)
@env = env
@middleware = middleware
@@ -44,25 +72,31 @@ module ActionDispatch
# but will be wrong if the user is behind a proxy. Proxies will set
# HTTP_CLIENT_IP and/or HTTP_X_FORWARDED_FOR, so we prioritize those.
# HTTP_X_FORWARDED_FOR may be a comma-delimited list in the case of
- # multiple chained proxies. The last address which is not a known proxy
- # will be the originating IP.
+ # multiple chained proxies. The first address which is in this list
+ # if it's not a known proxy will be the originating IP.
+ # Format of HTTP_X_FORWARDED_FOR:
+ # client_ip, proxy_ip1, proxy_ip2...
+ # http://en.wikipedia.org/wiki/X-Forwarded-For
def calculate_ip
- client_ip = @env['HTTP_CLIENT_IP']
- forwarded_ips = ips_from('HTTP_X_FORWARDED_FOR')
- remote_addrs = ips_from('REMOTE_ADDR')
+ client_ip = @env['HTTP_CLIENT_IP']
+ forwarded_ip = ips_from('HTTP_X_FORWARDED_FOR').first
+ remote_addrs = ips_from('REMOTE_ADDR')
check_ip = client_ip && @middleware.check_ip
- if check_ip && !forwarded_ips.include?(client_ip)
+ if check_ip && forwarded_ip != client_ip
# We don't know which came from the proxy, and which from the user
raise IpSpoofAttackError, "IP spoofing attack?!" \
"HTTP_CLIENT_IP=#{@env['HTTP_CLIENT_IP'].inspect}" \
"HTTP_X_FORWARDED_FOR=#{@env['HTTP_X_FORWARDED_FOR'].inspect}"
end
- not_proxy = client_ip || forwarded_ips.first || remote_addrs.first
-
- # Return first REMOTE_ADDR if there are no other options
- not_proxy || ips_from('REMOTE_ADDR', :allow_proxies).first
+ client_ips = remove_proxies [client_ip, forwarded_ip, remote_addrs].flatten
+ if client_ips.present?
+ client_ips.first
+ else
+ # If there is no client ip we can return first valid proxy ip from REMOTE_ADDR
+ remote_addrs.find { |ip| valid_ip? ip }
+ end
end
def to_s
@@ -71,12 +105,24 @@ module ActionDispatch
@ip = calculate_ip
end
- protected
+ private
- def ips_from(header, allow_proxies = false)
- ips = @env[header] ? @env[header].strip.split(/[,\s]+/) : []
- allow_proxies ? ips : ips.reject{|ip| ip =~ @middleware.proxies }
+ def ips_from(header)
+ @env[header] ? @env[header].strip.split(/[,\s]+/) : []
end
+
+ def valid_ip?(ip)
+ ip =~ VALID_IP
+ end
+
+ def not_a_proxy?(ip)
+ ip !~ @middleware.proxies
+ end
+
+ def remove_proxies(ips)
+ ips.select { |ip| valid_ip?(ip) && not_a_proxy?(ip) }
+ end
+
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb
index 6a8e690d18..e82132b445 100644
--- a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb
+++ b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb
@@ -7,6 +7,15 @@ require 'active_support/core_ext/object/blank'
module ActionDispatch
module Session
class SessionRestoreError < StandardError #:nodoc:
+ attr_reader :original_exception
+
+ def initialize(const_error)
+ @original_exception = const_error
+
+ super("Session contains objects whose class definition isn't available.\n" +
+ "Remember to require the classes for all objects kept in the session.\n" +
+ "(Original exception: #{const_error.message} [#{const_error.class}])\n")
+ end
end
module DestroyableSession
@@ -58,11 +67,8 @@ module ActionDispatch
begin
# Note that the regexp does not allow $1 to end with a ':'
$1.constantize
- rescue LoadError, NameError => const_error
- raise ActionDispatch::Session::SessionRestoreError,
- "Session contains objects whose class definition isn't available.\n" +
- "Remember to require the classes for all objects kept in the session.\n" +
- "(Original exception: #{const_error.message} [#{const_error.class}])\n"
+ rescue LoadError, NameError => e
+ raise ActionDispatch::Session::SessionRestoreError, e, e.backtrace
end
retry
else
@@ -74,6 +80,13 @@ module ActionDispatch
class AbstractStore < Rack::Session::Abstract::ID
include Compatibility
include StaleSessionCheck
+
+ private
+
+ def set_cookie(env, session_id, cookie)
+ request = ActionDispatch::Request.new(env)
+ request.cookie_jar[key] = cookie
+ end
end
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/stack.rb b/actionpack/lib/action_dispatch/middleware/stack.rb
index 28e8fbdab8..12bc438be3 100644
--- a/actionpack/lib/action_dispatch/middleware/stack.rb
+++ b/actionpack/lib/action_dispatch/middleware/stack.rb
@@ -110,7 +110,7 @@ module ActionDispatch
def build(app = nil, &block)
app ||= block
raise "MiddlewareStack#build requires an app" unless app
- middlewares.reverse.inject(app) { |a, e| e.build(a) }
+ middlewares.freeze.reverse.inject(app) { |a, e| e.build(a) }
end
protected
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/routing_error.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/routing_error.erb
index f06c07daa5..177d383e94 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/routing_error.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/routing_error.erb
@@ -12,4 +12,6 @@
<% end %>
<p>
Try running <code>rake routes</code> for more information on available routes.
-</p> \ No newline at end of file
+</p>
+
+<%= render :template => "rescues/_trace" %>
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index ba4cfb482d..4ea3937057 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -1,4 +1,5 @@
require 'active_support/core_ext/hash/except'
+require 'active_support/core_ext/hash/reverse_merge'
require 'active_support/core_ext/object/blank'
require 'active_support/core_ext/enumerable'
require 'active_support/inflector'
@@ -34,6 +35,8 @@ module ActionDispatch
}
return true
+ ensure
+ req.reset_parameters
end
def call(env)
@@ -58,6 +61,16 @@ module ActionDispatch
@options = (@scope[:options] || {}).merge(options)
@path = normalize_path(path)
normalize_options!
+
+ via_all = @options.delete(:via) if @options[:via] == :all
+
+ if !via_all && request_method_condition.empty?
+ msg = "You should not use the `match` method in your router without specifying an HTTP method.\n" \
+ "If you want to expose your action to GET, use `get` in the router:\n\n" \
+ " Instead of: match \"controller#action\"\n" \
+ " Do: get \"controller#action\""
+ raise msg
+ end
end
def to_route
@@ -263,7 +276,7 @@ module ActionDispatch
# of most Rails applications, this is beneficial.
def root(options = {})
options = { :to => options } if options.is_a?(String)
- match '/', { :as => :root }.merge(options)
+ match '/', { :as => :root, :via => :get }.merge(options)
end
# Matches a url pattern to one or more routes. Any symbols in a pattern
@@ -416,7 +429,7 @@ module ActionDispatch
options[:as] ||= app_name(app)
- match(path, options.merge(:to => app, :anchor => false, :format => false))
+ match(path, options.merge(:to => app, :anchor => false, :format => false, :via => :all))
define_generate_prefix(app, options[:as])
self
@@ -1294,6 +1307,21 @@ module ActionDispatch
parent_resource.instance_of?(Resource) && @scope[:shallow]
end
+ def draw(name)
+ path = @draw_paths.find do |_path|
+ _path.join("#{name}.rb").file?
+ end
+
+ unless path
+ msg = "Your router tried to #draw the external file #{name}.rb,\n" \
+ "but the file was not found in:\n\n"
+ msg += @draw_paths.map { |_path| " * #{_path}" }.join("\n")
+ raise msg
+ end
+
+ instance_eval(path.join("#{name}.rb").read)
+ end
+
# match 'path' => 'controller#action'
# match 'path', to: 'controller#action'
# match 'path', 'otherpath', on: :member, via: :get
@@ -1543,6 +1571,7 @@ module ActionDispatch
def initialize(set) #:nodoc:
@set = set
+ @draw_paths = set.draw_paths
@scope = { :path_names => @set.resources_path_names }
end
diff --git a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb
index 013cf93dbc..8fde667108 100644
--- a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb
+++ b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb
@@ -43,16 +43,14 @@ module ActionDispatch
# edit_polymorphic_path(@post) # => "/posts/1/edit"
# polymorphic_path(@post, :format => :pdf) # => "/posts/1.pdf"
#
- # == Using with mounted engines
+ # == Usage with mounted engines
#
- # If you use mounted engine, there is a possibility that you will need to use
- # polymorphic_url pointing at engine's routes. To do that, just pass proxy used
- # to reach engine's routes as a first argument:
+ # If you are using a mounted engine and you need to use a polymorphic_url
+ # pointing at the engine's routes, pass in the engine's route proxy as the first
+ # argument to the method. For example:
#
- # For example:
- #
- # polymorphic_url([blog, @post]) # it will call blog.post_path(@post)
- # form_for([blog, @post]) # => "/blog/posts/1
+ # polymorphic_url([blog, @post]) # calls blog.post_path(@post)
+ # form_for([blog, @post]) # => "/blog/posts/1"
#
module PolymorphicRoutes
# Constructs a call to a named RESTful route for the given record and returns the
diff --git a/actionpack/lib/action_dispatch/routing/redirection.rb b/actionpack/lib/action_dispatch/routing/redirection.rb
index 617b24b46a..95c588c00a 100644
--- a/actionpack/lib/action_dispatch/routing/redirection.rb
+++ b/actionpack/lib/action_dispatch/routing/redirection.rb
@@ -1,4 +1,7 @@
require 'action_dispatch/http/request'
+require 'active_support/core_ext/uri'
+require 'active_support/core_ext/array/extract_options'
+require 'rack/utils'
module ActionDispatch
module Routing
@@ -46,8 +49,17 @@ module ActionDispatch
:params => request.query_parameters
}.merge options
+ if !params.empty? && url_options[:path].match(/%\{\w*\}/)
+ url_options[:path] = (url_options[:path] % escape_path(params))
+ end
+
ActionDispatch::Http::URL.url_for url_options
end
+
+ private
+ def escape_path(params)
+ Hash[params.map{ |k,v| [k, URI.parser.escape(v)] }]
+ end
end
module Redirection
@@ -67,10 +79,13 @@ module ActionDispatch
# params, depending of how many arguments your block accepts. A string is required as a
# return value.
#
- # match 'jokes/:number', :to => redirect do |params, request|
- # path = (params[:number].to_i.even? ? "/wheres-the-beef" : "/i-love-lamp")
+ # match 'jokes/:number', :to => redirect { |params, request|
+ # path = (params[:number].to_i.even? ? "wheres-the-beef" : "i-love-lamp")
# "http://#{request.host_with_port}/#{path}"
- # end
+ # }
+ #
+ # Note that the +do end+ syntax for the redirect block wouldn't work, as Ruby would pass
+ # the block to +match+ instead of +redirect+. Use <tt>{ ... }</tt> instead.
#
# The options version of redirect allows you to supply only the parts of the url which need
# to change, it also supports interpolation of the path similar to the first example.
@@ -85,7 +100,7 @@ module ActionDispatch
# match 'accounts/:name' => redirect(SubdomainRedirector.new('api'))
#
def redirect(*args, &block)
- options = args.last.is_a?(Hash) ? args.pop : {}
+ options = args.extract_options!
status = options.delete(:status) || 301
return OptionRedirect.new(status, options) if options.any?
@@ -93,13 +108,18 @@ module ActionDispatch
path = args.shift
block = lambda { |params, request|
- (params.empty? || !path.match(/%\{\w*\}/)) ? path : (path % params)
+ (params.empty? || !path.match(/%\{\w*\}/)) ? path : (path % escape(params))
} if String === path
block = path if path.respond_to? :call
raise ArgumentError, "redirection argument not supported" unless block
Redirect.new status, block
end
+
+ private
+ def escape(params)
+ Hash[params.map{ |k,v| [k, Rack::Utils.escape(v)] }]
+ end
end
end
end
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index 45075050eb..7abd7bd008 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -96,7 +96,25 @@ module ActionDispatch
def initialize
@routes = {}
@helpers = []
- @module = Module.new
+ @module = Module.new do
+ protected
+
+ def handle_positional_args(args, options, segment_keys)
+ inner_options = args.extract_options!
+ result = options.dup
+
+ if args.any?
+ keys = segment_keys
+ if args.size < keys.size - 1 # take format into account
+ keys -= self.url_options.keys if self.respond_to?(:url_options)
+ keys -= options.keys
+ end
+ result.merge!(Hash[keys.zip(args)])
+ end
+
+ result.merge!(inner_options)
+ end
+ end
end
def helper_names
@@ -135,43 +153,19 @@ module ActionDispatch
end
private
- def url_helper_name(name, kind = :url)
- :"#{name}_#{kind}"
- end
-
- def hash_access_name(name, kind = :url)
- :"hash_for_#{name}_#{kind}"
- end
-
- def define_named_route_methods(name, route)
- {:url => {:only_path => false}, :path => {:only_path => true}}.each do |kind, opts|
- hash = route.defaults.merge(:use_route => name).merge(opts)
- define_hash_access route, name, kind, hash
- define_url_helper route, name, kind, hash
+ def url_helper_name(name, only_path)
+ if only_path
+ :"#{name}_path"
+ else
+ :"#{name}_url"
end
end
- def define_hash_access(route, name, kind, options)
- selector = hash_access_name(name, kind)
-
- @module.module_eval do
- remove_possible_method selector
-
- define_method(selector) do |*args|
- inner_options = args.extract_options!
- result = options.dup
-
- if args.any?
- result[:_positional_args] = args
- result[:_positional_keys] = route.segment_keys
- end
-
- result.merge(inner_options)
- end
-
- protected selector
+ def define_named_route_methods(name, route)
+ [true, false].each do |only_path|
+ hash = route.defaults.merge(:use_route => name, :only_path => only_path)
+ define_url_helper route, name, hash
end
- helpers << selector
end
# Create a url helper allowing ordered parameters to be associated
@@ -187,38 +181,28 @@ module ActionDispatch
#
# foo_url(bar, baz, bang, :sort_by => 'baz')
#
- def define_url_helper(route, name, kind, options)
- selector = url_helper_name(name, kind)
- hash_access_method = hash_access_name(name, kind)
-
- if optimize_helper?(route)
- @module.module_eval <<-END_EVAL, __FILE__, __LINE__ + 1
- remove_possible_method :#{selector}
- def #{selector}(*args)
- if args.size == #{route.required_parts.size} && !args.last.is_a?(Hash) && optimize_routes_generation?
- options = #{options.inspect}.merge!(url_options)
- options[:path] = "#{optimized_helper(route)}"
- ActionDispatch::Http::URL.url_for(options)
- else
- url_for(#{hash_access_method}(*args))
- end
- end
- END_EVAL
- else
- @module.module_eval <<-END_EVAL, __FILE__, __LINE__ + 1
- remove_possible_method :#{selector}
- def #{selector}(*args)
- url_for(#{hash_access_method}(*args))
+ def define_url_helper(route, name, options)
+ selector = url_helper_name(name, options[:only_path])
+
+ @module.module_eval <<-END_EVAL, __FILE__, __LINE__ + 1
+ remove_possible_method :#{selector}
+ def #{selector}(*args)
+ if #{optimize_helper?(route)} && args.size == #{route.required_parts.size} && !args.last.is_a?(Hash) && optimize_routes_generation?
+ options = #{options.inspect}.merge!(url_options)
+ options[:path] = "#{optimized_helper(route)}"
+ ActionDispatch::Http::URL.url_for(options)
+ else
+ url_for(handle_positional_args(args, #{options.inspect}, #{route.segment_keys.inspect}))
end
- END_EVAL
- end
+ end
+ END_EVAL
helpers << selector
end
# Clause check about when we need to generate an optimized helper.
def optimize_helper?(route) #:nodoc:
- route.ast.grep(Journey::Nodes::Star).empty? && route.requirements.except(:controller, :action).empty?
+ route.requirements.except(:controller, :action).empty?
end
# Generates the interpolation to be used in the optimized helper.
@@ -230,7 +214,10 @@ module ActionDispatch
end
route.required_parts.each_with_index do |part, i|
- string_route.gsub!(part.inspect, "\#{Journey::Router::Utils.escape_fragment(args[#{i}].to_param)}")
+ # Replace each route parameter
+ # e.g. :id for regular parameter or *path for globbing
+ # with ruby string interpolation code
+ string_route.gsub!(/(\*|:)#{part}/, "\#{Journey::Router::Utils.escape_fragment(args[#{i}].to_param)}")
end
string_route
@@ -240,6 +227,7 @@ module ActionDispatch
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, :valid_conditions
+ attr_accessor :draw_paths
alias :routes :set
@@ -251,6 +239,7 @@ module ActionDispatch
self.named_routes = NamedRouteCollection.new
self.resources_path_names = self.class.default_resources_path_names.dup
self.default_url_options = {}
+ self.draw_paths = []
self.request_class = request_class
@valid_conditions = {}
@@ -609,8 +598,6 @@ module ActionDispatch
def url_for(options)
options = default_url_options.merge(options || {})
- handle_positional_args(options)
-
user, password = extract_authentication(options)
path_segments = options.delete(:_path_segments)
script_name = options.delete(:script_name).presence || _generate_prefix(options)
@@ -680,16 +667,6 @@ module ActionDispatch
end
end
- def handle_positional_args(options)
- return unless args = options.delete(:_positional_args)
-
- keys = options.delete(:_positional_keys)
- keys -= options.keys if args.size < keys.size - 1 # take format into account
-
- # Tell url_for to skip default_url_options
- options.merge!(Hash[args.zip(keys).map { |v, k| [k, v] }])
- end
-
end
end
end
diff --git a/actionpack/lib/action_dispatch/testing/assertions/response.rb b/actionpack/lib/action_dispatch/testing/assertions/response.rb
index 40d38c59d6..8f6fff5d32 100644
--- a/actionpack/lib/action_dispatch/testing/assertions/response.rb
+++ b/actionpack/lib/action_dispatch/testing/assertions/response.rb
@@ -53,15 +53,18 @@ module ActionDispatch
# # assert that the redirection was to the url for @customer
# assert_redirected_to @customer
#
+ # # asserts that the redirection matches the regular expression
+ # assert_redirected_to %r(\Ahttp://example.org)
+ #
def assert_redirected_to(options = {}, message=nil)
assert_response(:redirect, message)
- return true if options == @response.location
+ return true if options === @response.location
redirect_is = normalize_argument_to_redirection(@response.location)
redirect_expected = normalize_argument_to_redirection(options)
message ||= "Expected response to be a redirect to <#{redirect_expected}> but was a redirect to <#{redirect_is}>"
- assert_equal redirect_expected, redirect_is, message
+ assert_operator redirect_expected, :===, redirect_is, message
end
private
@@ -71,17 +74,21 @@ module ActionDispatch
end
def normalize_argument_to_redirection(fragment)
- case fragment
- when %r{^\w[A-Za-z\d+.-]*:.*}
- fragment
- when String
- @request.protocol + @request.host_with_port + fragment
- when :back
- raise RedirectBackError unless refer = @request.headers["Referer"]
- refer
- else
- @controller.url_for(fragment)
- end.delete("\0\r\n")
+ normalized = case fragment
+ when Regexp
+ fragment
+ when %r{^\w[A-Za-z\d+.-]*:.*}
+ fragment
+ when String
+ @request.protocol + @request.host_with_port + fragment
+ when :back
+ raise RedirectBackError unless refer = @request.headers["Referer"]
+ refer
+ else
+ @controller.url_for(fragment)
+ end
+
+ normalized.respond_to?(:delete) ? normalized.delete("\0\r\n") : normalized
end
end
end
diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
index d4d09e2ee9..7985683a72 100644
--- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
@@ -442,7 +442,7 @@ module ActionView
# <video><source src="/videos/trailer.ogg" /><source src="/videos/trailer.flv" /></video>
# video_tag(["trailer.ogg", "trailer.flv"]) # =>
# <video><source src="/videos/trailer.ogg" /><source src="/videos/trailer.flv" /></video>
- # video_tag(["trailer.ogg", "trailer.flv"] :size => "160x120") # =>
+ # video_tag(["trailer.ogg", "trailer.flv"], :size => "160x120") # =>
# <video height="120" width="160"><source src="/videos/trailer.ogg" /><source src="/videos/trailer.flv" /></video>
def video_tag(*sources)
multiple_sources_tag('video', sources) do |options|
diff --git a/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb b/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb
index dd4e9ae4cc..35f91cec18 100644
--- a/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb
+++ b/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb
@@ -1,5 +1,6 @@
require 'thread'
require 'active_support/core_ext/file'
+require 'active_support/core_ext/module/attribute_accessors'
module ActionView
module Helpers
diff --git a/actionpack/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb b/actionpack/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb
index 60d4af178a..4bcb8b9718 100644
--- a/actionpack/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb
+++ b/actionpack/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb
@@ -113,7 +113,7 @@ module ActionView
# == Caching multiple stylesheets into one
#
# You can also cache multiple stylesheets into one file, which requires less HTTP connections and can better be
- # compressed by gzip (leading to faster transfers). Caching will only happen if config.perform_caching
+ # compressed by gzip (leading to faster transfers). Caching will only happen if +config.perform_caching+
# is set to true (which is the case by default for the Rails production environment, but not for the development
# environment). Examples:
#
diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb
index cb46f26d99..6bd8e62e0d 100644
--- a/actionpack/lib/action_view/helpers/date_helper.rb
+++ b/actionpack/lib/action_view/helpers/date_helper.rb
@@ -12,14 +12,14 @@ module ActionView
# elements. All of the select-type methods share a number of common options that are as follows:
#
# * <tt>:prefix</tt> - overwrites the default prefix of "date" used for the select names. So specifying "birthday"
- # would give birthday[month] instead of date[month] if passed to the <tt>select_month</tt> method.
+ # would give \birthday[month] instead of \date[month] if passed to the <tt>select_month</tt> method.
# * <tt>:include_blank</tt> - set to true if it should be possible to set an empty date.
# * <tt>:discard_type</tt> - set to true if you want to discard the type part of the select name. If set to true,
# the <tt>select_month</tt> method would use simply "date" (which can be overwritten using <tt>:prefix</tt>) instead
- # of "date[month]".
+ # of \date[month].
module DateHelper
# Reports the approximate distance in time between two Time, Date or DateTime objects or integers as seconds.
- # Set <tt>include_seconds</tt> to true if you want more detailed approximations when distance < 1 min, 29 secs.
+ # Pass <tt>:include_seconds => true</tt> if you want more detailed approximations when distance < 1 min, 29 secs.
# Distances are reported based on the following table:
#
# 0 <-> 29 secs # => less than a minute
@@ -29,14 +29,15 @@ module ActionView
# 89 mins, 30 secs <-> 23 hrs, 59 mins, 29 secs # => about [2..24] hours
# 23 hrs, 59 mins, 30 secs <-> 41 hrs, 59 mins, 29 secs # => 1 day
# 41 hrs, 59 mins, 30 secs <-> 29 days, 23 hrs, 59 mins, 29 secs # => [2..29] days
- # 29 days, 23 hrs, 59 mins, 30 secs <-> 59 days, 23 hrs, 59 mins, 29 secs # => about 1 month
+ # 29 days, 23 hrs, 59 mins, 30 secs <-> 44 days, 23 hrs, 59 mins, 29 secs # => about 1 month
+ # 44 days, 23 hrs, 59 mins, 30 secs <-> 59 days, 23 hrs, 59 mins, 29 secs # => about 2 months
# 59 days, 23 hrs, 59 mins, 30 secs <-> 1 yr minus 1 sec # => [2..12] months
# 1 yr <-> 1 yr, 3 months # => about 1 year
# 1 yr, 3 months <-> 1 yr, 9 months # => over 1 year
# 1 yr, 9 months <-> 2 yr minus 1 sec # => almost 2 years
# 2 yrs <-> max time or date # => (same rules as 1 yr)
#
- # With <tt>include_seconds</tt> = true and the difference < 1 minute 29 seconds:
+ # With <tt>:include_seconds => true</tt> and the difference < 1 minute 29 seconds:
# 0-4 secs # => less than 5 seconds
# 5-9 secs # => less than 10 seconds
# 10-19 secs # => less than 20 seconds
@@ -46,36 +47,45 @@ module ActionView
#
# ==== Examples
# from_time = Time.now
- # distance_of_time_in_words(from_time, from_time + 50.minutes) # => about 1 hour
- # distance_of_time_in_words(from_time, 50.minutes.from_now) # => about 1 hour
- # distance_of_time_in_words(from_time, from_time + 15.seconds) # => less than a minute
- # distance_of_time_in_words(from_time, from_time + 15.seconds, true) # => less than 20 seconds
- # distance_of_time_in_words(from_time, 3.years.from_now) # => about 3 years
- # distance_of_time_in_words(from_time, from_time + 60.hours) # => 3 days
- # distance_of_time_in_words(from_time, from_time + 45.seconds, true) # => less than a minute
- # distance_of_time_in_words(from_time, from_time - 45.seconds, true) # => less than a minute
- # distance_of_time_in_words(from_time, 76.seconds.from_now) # => 1 minute
- # distance_of_time_in_words(from_time, from_time + 1.year + 3.days) # => about 1 year
- # distance_of_time_in_words(from_time, from_time + 3.years + 6.months) # => over 3 years
+ # distance_of_time_in_words(from_time, from_time + 50.minutes) # => about 1 hour
+ # distance_of_time_in_words(from_time, 50.minutes.from_now) # => about 1 hour
+ # distance_of_time_in_words(from_time, from_time + 15.seconds) # => less than a minute
+ # distance_of_time_in_words(from_time, from_time + 15.seconds, :include_seconds => true) # => less than 20 seconds
+ # distance_of_time_in_words(from_time, 3.years.from_now) # => about 3 years
+ # distance_of_time_in_words(from_time, from_time + 60.hours) # => 3 days
+ # distance_of_time_in_words(from_time, from_time + 45.seconds, :include_seconds => true) # => less than a minute
+ # distance_of_time_in_words(from_time, from_time - 45.seconds, :include_seconds => true) # => less than a minute
+ # distance_of_time_in_words(from_time, 76.seconds.from_now) # => 1 minute
+ # distance_of_time_in_words(from_time, from_time + 1.year + 3.days) # => about 1 year
+ # distance_of_time_in_words(from_time, from_time + 3.years + 6.months) # => over 3 years
# distance_of_time_in_words(from_time, from_time + 4.years + 9.days + 30.minutes + 5.seconds) # => about 4 years
#
# to_time = Time.now + 6.years + 19.days
- # distance_of_time_in_words(from_time, to_time, true) # => about 6 years
- # distance_of_time_in_words(to_time, from_time, true) # => about 6 years
- # distance_of_time_in_words(Time.now, Time.now) # => less than a minute
- #
- def distance_of_time_in_words(from_time, to_time = 0, include_seconds = false, options = {})
+ # distance_of_time_in_words(from_time, to_time, :include_seconds => true) # => about 6 years
+ # distance_of_time_in_words(to_time, from_time, :include_seconds => true) # => about 6 years
+ # distance_of_time_in_words(Time.now, Time.now) # => less than a minute
+ #
+ def distance_of_time_in_words(from_time, to_time = 0, include_seconds_or_options = {}, options = {})
+ unless include_seconds_or_options.is_a?(Hash)
+ ActiveSupport::Deprecation.warn "distance_of_time_in_words and time_ago_in_words now accept :include_seconds " +
+ "as a part of options hash, not a boolean argument", caller
+ options[:include_seconds] ||= !!include_seconds_or_options
+ else
+ options = include_seconds_or_options
+ end
+
from_time = from_time.to_time if from_time.respond_to?(:to_time)
to_time = to_time.to_time if to_time.respond_to?(:to_time)
- distance_in_minutes = (((to_time - from_time).abs)/60).round
- distance_in_seconds = ((to_time - from_time).abs).round
+ from_time, to_time = to_time, from_time if from_time > to_time
+ distance_in_minutes = ((to_time - from_time)/60.0).round
+ distance_in_seconds = (to_time - from_time).round
I18n.with_options :locale => options[:locale], :scope => :'datetime.distance_in_words' do |locale|
case distance_in_minutes
when 0..1
return distance_in_minutes == 0 ?
locale.t(:less_than_x_minutes, :count => 1) :
- locale.t(:x_minutes, :count => distance_in_minutes) unless include_seconds
+ locale.t(:x_minutes, :count => distance_in_minutes) unless options[:include_seconds]
case distance_in_seconds
when 0..4 then locale.t :less_than_x_seconds, :count => 5
@@ -86,26 +96,35 @@ module ActionView
else locale.t :x_minutes, :count => 1
end
- when 2..44 then locale.t :x_minutes, :count => distance_in_minutes
- when 45..89 then locale.t :about_x_hours, :count => 1
- when 90..1439 then locale.t :about_x_hours, :count => (distance_in_minutes.to_f / 60.0).round
- when 1440..2519 then locale.t :x_days, :count => 1
- when 2520..43199 then locale.t :x_days, :count => (distance_in_minutes.to_f / 1440.0).round
- when 43200..86399 then locale.t :about_x_months, :count => 1
- when 86400..525599 then locale.t :x_months, :count => (distance_in_minutes.to_f / 43200.0).round
+ when 2...45 then locale.t :x_minutes, :count => distance_in_minutes
+ when 45...90 then locale.t :about_x_hours, :count => 1
+ # 90 mins up to 24 hours
+ when 90...1440 then locale.t :about_x_hours, :count => (distance_in_minutes.to_f / 60.0).round
+ # 24 hours up to 42 hours
+ when 1440...2520 then locale.t :x_days, :count => 1
+ # 42 hours up to 30 days
+ when 2520...43200 then locale.t :x_days, :count => (distance_in_minutes.to_f / 1440.0).round
+ # 30 days up to 60 days
+ when 43200...86400 then locale.t :about_x_months, :count => (distance_in_minutes.to_f / 43200.0).round
+ # 60 days up to 365 days
+ when 86400...525600 then locale.t :x_months, :count => (distance_in_minutes.to_f / 43200.0).round
else
- fyear = from_time.year
- fyear += 1 if from_time.month >= 3
- tyear = to_time.year
- tyear -= 1 if to_time.month < 3
- leap_years = (fyear > tyear) ? 0 : (fyear..tyear).count{|x| Date.leap?(x)}
- minute_offset_for_leap_year = leap_years * 1440
- # Discount the leap year days when calculating year distance.
- # e.g. if there are 20 leap year days between 2 dates having the same day
- # and month then the based on 365 days calculation
- # the distance in years will come out to over 80 years when in written
- # english it would read better as about 80 years.
- minutes_with_offset = distance_in_minutes - minute_offset_for_leap_year
+ if from_time.acts_like?(:time) && to_time.acts_like?(:time)
+ fyear = from_time.year
+ fyear += 1 if from_time.month >= 3
+ tyear = to_time.year
+ tyear -= 1 if to_time.month < 3
+ leap_years = (fyear > tyear) ? 0 : (fyear..tyear).count{|x| Date.leap?(x)}
+ minute_offset_for_leap_year = leap_years * 1440
+ # Discount the leap year days when calculating year distance.
+ # e.g. if there are 20 leap year days between 2 dates having the same day
+ # and month then the based on 365 days calculation
+ # the distance in years will come out to over 80 years when in written
+ # english it would read better as about 80 years.
+ minutes_with_offset = distance_in_minutes - minute_offset_for_leap_year
+ else
+ minutes_with_offset = distance_in_minutes
+ end
remainder = (minutes_with_offset % 525600)
distance_in_years = (minutes_with_offset / 525600)
if remainder < 131400
@@ -122,15 +141,16 @@ module ActionView
# Like <tt>distance_of_time_in_words</tt>, but where <tt>to_time</tt> is fixed to <tt>Time.now</tt>.
#
# ==== Examples
- # time_ago_in_words(3.minutes.from_now) # => 3 minutes
- # time_ago_in_words(Time.now - 15.hours) # => about 15 hours
- # time_ago_in_words(Time.now) # => less than a minute
+ # time_ago_in_words(3.minutes.from_now) # => 3 minutes
+ # time_ago_in_words(Time.now - 15.hours) # => about 15 hours
+ # time_ago_in_words(Time.now) # => less than a minute
+ # time_ago_in_words(Time.now, :include_seconds => true) # => less than 5 seconds
#
# from_time = Time.now - 3.days - 14.minutes - 25.seconds
# time_ago_in_words(from_time) # => 3 days
#
- def time_ago_in_words(from_time, include_seconds = false)
- distance_of_time_in_words(from_time, Time.now, include_seconds)
+ def time_ago_in_words(from_time, include_seconds_or_options = {})
+ distance_of_time_in_words(from_time, Time.now, include_seconds_or_options)
end
alias_method :distance_of_time_in_words_to_now, :time_ago_in_words
@@ -997,6 +1017,8 @@ module ActionView
# Returns the separator for a given datetime component.
def separator(type)
+ return "" if @options[:use_hidden]
+
case type
when :year, :month, :day
@options[:"discard_#{type}"] ? "" : @options[:date_separator]
diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb
index 3f5829d86a..67f2abe509 100644
--- a/actionpack/lib/action_view/helpers/form_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_helper.rb
@@ -10,6 +10,7 @@ require 'active_support/core_ext/object/blank'
require 'active_support/core_ext/string/output_safety'
require 'active_support/core_ext/array/extract_options'
require 'active_support/deprecation'
+require 'active_support/core_ext/string/inflections'
module ActionView
# = Action View Form Helpers
@@ -184,7 +185,7 @@ module ActionView
# First name: <%= f.text_field :first_name %>
# Last name : <%= f.text_field :last_name %>
# Biography : <%= text_area :person, :biography %>
- # Admin? : <%= check_box_tag "person[admin]", @person.company.admin? %>
+ # Admin? : <%= check_box_tag "person[admin]", "1", @person.company.admin? %>
# <%= f.submit %>
# <% end %>
#
@@ -902,7 +903,7 @@ module ActionView
# # Let's say that @post.validated? is 1:
# check_box("post", "validated")
# # => <input name="post[validated]" type="hidden" value="0" />
- # # <input type="checkbox" id="post_validated" name="post[validated]" value="1" />
+ # # <input checked="checked" type="checkbox" id="post_validated" name="post[validated]" value="1" />
#
# # Let's say that @puppy.gooddog is "no":
# check_box("puppy", "gooddog", {}, "yes", "no")
@@ -1039,9 +1040,14 @@ module ActionView
object_name = ActiveModel::Naming.param_key(object)
end
- builder = options[:builder] || ActionView::Base.default_form_builder
+ builder = options[:builder] || default_form_builder
builder.new(object_name, object, self, options)
end
+
+ def default_form_builder
+ builder = ActionView::Base.default_form_builder
+ builder.respond_to?(:constantize) ? builder.constantize : builder
+ end
end
class FormBuilder
diff --git a/actionpack/lib/action_view/helpers/javascript_helper.rb b/actionpack/lib/action_view/helpers/javascript_helper.rb
index 5a869d6303..cc20518b93 100644
--- a/actionpack/lib/action_view/helpers/javascript_helper.rb
+++ b/actionpack/lib/action_view/helpers/javascript_helper.rb
@@ -15,7 +15,6 @@ module ActionView
JS_ESCAPE_MAP["\342\200\250".force_encoding('UTF-8').encode!] = '&#x2028;'
JS_ESCAPE_MAP["\342\200\251".force_encoding('UTF-8').encode!] = '&#x2029;'
-
# Escapes carriage returns and single and double quotes for JavaScript segments.
#
@@ -68,40 +67,6 @@ module ActionView
def javascript_cdata_section(content) #:nodoc:
"\n//#{cdata_section("\n#{content}\n//")}\n".html_safe
end
-
- # Returns a button whose +onclick+ handler triggers the passed JavaScript.
- #
- # The helper receives a name, JavaScript code, and an optional hash of HTML options. The
- # name is used as button label and the JavaScript code goes into its +onclick+ attribute.
- # If +html_options+ has an <tt>:onclick</tt>, that one is put before +function+.
- #
- # button_to_function "Greeting", "alert('Hello world!')", :class => "ok"
- # # => <input class="ok" onclick="alert('Hello world!');" type="button" value="Greeting" />
- #
- def button_to_function(name, function=nil, html_options={})
- onclick = "#{"#{html_options[:onclick]}; " if html_options[:onclick]}#{function};"
-
- tag(:input, html_options.merge(:type => 'button', :value => name, :onclick => onclick))
- end
-
- # Returns a link whose +onclick+ handler triggers the passed JavaScript.
- #
- # The helper receives a name, JavaScript code, and an optional hash of HTML options. The
- # name is used as the link text and the JavaScript code goes into the +onclick+ attribute.
- # If +html_options+ has an <tt>:onclick</tt>, that one is put before +function+. Once all
- # the JavaScript is set, the helper appends "; return false;".
- #
- # The +href+ attribute of the tag is set to "#" unless +html_options+ has one.
- #
- # link_to_function "Greeting", "alert('Hello world!')", :class => "nav_link"
- # # => <a class="nav_link" href="#" onclick="alert('Hello world!'); return false;">Greeting</a>
- #
- def link_to_function(name, function, html_options={})
- onclick = "#{"#{html_options[:onclick]}; " if html_options[:onclick]}#{function}; return false;"
- href = html_options[:href] || '#'
-
- content_tag(:a, name, html_options.merge(:href => href, :onclick => onclick))
- end
end
end
end
diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb
index d3a7a1bb96..2011351bd2 100644
--- a/actionpack/lib/action_view/helpers/number_helper.rb
+++ b/actionpack/lib/action_view/helpers/number_helper.rb
@@ -233,7 +233,7 @@ module ActionView
parts = number.to_s.to_str.split('.')
parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{options[:delimiter]}")
- parts.join(options[:separator]).html_safe
+ safe_join(parts, options[:separator])
end
# Formats a +number+ with the specified level of <tt>:precision</tt> (e.g., 112.32 has a precision
@@ -392,10 +392,10 @@ module ActionView
# * *integers*: <tt>:unit</tt>, <tt>:ten</tt>, <tt>:hundred</tt>, <tt>:thousand</tt>, <tt>:million</tt>, <tt>:billion</tt>, <tt>:trillion</tt>, <tt>:quadrillion</tt>
# * *fractionals*: <tt>:deci</tt>, <tt>:centi</tt>, <tt>:mili</tt>, <tt>:micro</tt>, <tt>:nano</tt>, <tt>:pico</tt>, <tt>:femto</tt>
# * <tt>:format</tt> - Sets the format of the output string (defaults to "%n %u"). The field types are:
- # * <tt>:raise</tt> - If true, raises +InvalidNumberError+ when the argument is invalid.
- #
# %u The quantifier (ex.: 'thousand')
# %n The number
+ # * <tt>:raise</tt> - If true, raises +InvalidNumberError+ when the argument is invalid.
+ #
#
# ==== Examples
# number_to_human(123) # => "123"
diff --git a/actionpack/lib/action_view/helpers/record_tag_helper.rb b/actionpack/lib/action_view/helpers/record_tag_helper.rb
index 1a15459406..9b35f076e5 100644
--- a/actionpack/lib/action_view/helpers/record_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/record_tag_helper.rb
@@ -94,10 +94,10 @@ module ActionView
# for each record.
def content_tag_for_single_record(tag_name, record, prefix, options, &block)
options = options ? options.dup : {}
- options.merge!(:class => "#{dom_class(record, prefix)} #{options[:class]}".rstrip, :id => dom_id(record, prefix))
+ options[:class] = "#{dom_class(record, prefix)} #{options[:class]}".rstrip
+ options[:id] = dom_id(record, prefix)
- content = block.arity == 0 ? capture(&block) : capture(record, &block)
- content_tag(tag_name, content, options)
+ content_tag(tag_name, capture(record, &block), options)
end
end
end
diff --git a/actionpack/lib/action_view/helpers/tag_helper.rb b/actionpack/lib/action_view/helpers/tag_helper.rb
index 23777721f6..f7afa48256 100644
--- a/actionpack/lib/action_view/helpers/tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/tag_helper.rb
@@ -109,8 +109,12 @@ module ActionView
#
# cdata_section(File.read("hello_world.txt"))
# # => <![CDATA[<hello from a text file]]>
+ #
+ # cdata_section("hello]]>world")
+ # # => <![CDATA[hello]]]]><![CDATA[>world]]>
def cdata_section(content)
- "<![CDATA[#{content}]]>".html_safe
+ splitted = content.gsub(']]>', ']]]]><![CDATA[>')
+ "<![CDATA[#{splitted}]]>".html_safe
end
# Returns an escaped version of +html+ without affecting existing escaped entities.
diff --git a/actionpack/lib/action_view/helpers/tags/check_box.rb b/actionpack/lib/action_view/helpers/tags/check_box.rb
index 1a4aebb936..9d17a1dde3 100644
--- a/actionpack/lib/action_view/helpers/tags/check_box.rb
+++ b/actionpack/lib/action_view/helpers/tags/check_box.rb
@@ -41,17 +41,15 @@ module ActionView
def checked?(value)
case value
when TrueClass, FalseClass
- value
+ value == !!@checked_value
when NilClass
false
- when Integer
- value != 0
when String
value == @checked_value
when Array
value.include?(@checked_value)
else
- value.to_i != 0
+ value.to_i == @checked_value.to_i
end
end
diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb
index eb806f44cf..12bb162da2 100644
--- a/actionpack/lib/action_view/helpers/text_helper.rb
+++ b/actionpack/lib/action_view/helpers/text_helper.rb
@@ -112,9 +112,9 @@ module ActionView
def highlight(text, phrases, *args)
options = args.extract_options!
unless args.empty?
- options[:highlighter] = args[0] || '<mark>\1</mark>'
+ options[:highlighter] = args[0]
end
- options.reverse_merge!(:highlighter => '<mark>\1</mark>')
+ options[:highlighter] ||= '<mark>\1</mark>'
text = sanitize(text) unless options[:sanitize] == false
if text.blank? || phrases.blank?
@@ -157,19 +157,20 @@ module ActionView
options = args.extract_options!
unless args.empty?
- options[:radius] = args[0] || 100
- options[:omission] = args[1] || "..."
+ options[:radius] = args[0]
+ options[:omission] = args[1]
end
- options.reverse_merge!(:radius => 100, :omission => "...")
+ radius = options[:radius] || 100
+ omission = options[:omission] || "..."
phrase = Regexp.escape(phrase)
return unless found_pos = text =~ /(#{phrase})/i
- start_pos = [ found_pos - options[:radius], 0 ].max
- end_pos = [ [ found_pos + phrase.length + options[:radius] - 1, 0].max, text.length ].min
+ start_pos = [ found_pos - radius, 0 ].max
+ end_pos = [ [ found_pos + phrase.length + radius - 1, 0].max, text.length ].min
- prefix = start_pos > 0 ? options[:omission] : ""
- postfix = end_pos < text.length - 1 ? options[:omission] : ""
+ prefix = start_pos > 0 ? omission : ""
+ postfix = end_pos < text.length - 1 ? omission : ""
prefix + text[start_pos..end_pos].strip + postfix
end
@@ -218,12 +219,12 @@ module ActionView
def word_wrap(text, *args)
options = args.extract_options!
unless args.blank?
- options[:line_width] = args[0] || 80
+ options[:line_width] = args[0]
end
- options.reverse_merge!(:line_width => 80)
+ line_width = options[:line_width] || 80
text.split("\n").collect do |line|
- line.length > options[:line_width] ? line.gsub(/(.{1,#{options[:line_width]}})(\s+|$)/, "\\1\n").strip : line
+ line.length > line_width ? line.gsub(/(.{1,#{line_width}})(\s+|$)/, "\\1\n").strip : line
end * "\n"
end
diff --git a/actionpack/lib/action_view/helpers/translation_helper.rb b/actionpack/lib/action_view/helpers/translation_helper.rb
index cc74eff53a..fd06bfa2a8 100644
--- a/actionpack/lib/action_view/helpers/translation_helper.rb
+++ b/actionpack/lib/action_view/helpers/translation_helper.rb
@@ -45,6 +45,7 @@ module ActionView
# you know what kind of output to expect when you call translate in a template.
def translate(key, options = {})
options.merge!(:rescue_format => :html) unless options.key?(:rescue_format)
+ options[:default] = wrap_translate_defaults(options[:default]) if options[:default]
if html_safe_translation_key?(key)
html_safe_options = options.dup
options.except(*I18n::RESERVED_KEYS).each do |name, value|
@@ -83,6 +84,21 @@ module ActionView
def html_safe_translation_key?(key)
key.to_s =~ /(\b|_|\.)html$/
end
+
+ def wrap_translate_defaults(defaults)
+ new_defaults = []
+ defaults = Array(defaults)
+ while key = defaults.shift
+ if key.is_a?(Symbol)
+ new_defaults << lambda { |_, options| translate key, options.merge(:default => defaults) }
+ break
+ else
+ new_defautls << key
+ end
+ end
+
+ new_defaults
+ end
end
end
end
diff --git a/actionpack/lib/action_view/renderer/partial_renderer.rb b/actionpack/lib/action_view/renderer/partial_renderer.rb
index 8b53867aea..c5d5540510 100644
--- a/actionpack/lib/action_view/renderer/partial_renderer.rb
+++ b/actionpack/lib/action_view/renderer/partial_renderer.rb
@@ -158,8 +158,8 @@ module ActionView
# Name: <%= user.name %>
# </div>
#
- # If a collection is given, the layout will be rendered once for each item in the collection. Just think
- # these two snippets have the same output:
+ # If a collection is given, the layout will be rendered once for each item in
+ # the collection. Just think these two snippets have the same output:
#
# <%# app/views/users/_user.html.erb %>
# Name: <%= user.name %>
@@ -184,7 +184,7 @@ module ActionView
# <%= render :partial => "user", :layout => "li_layout", :collection => users %>
# </ul>
#
- # Given two users whose names are Alice and Bob, these snippets return:
+ # Given two users whose names are Alice and Bob, these snippets return:
#
# <ul>
# <li>
@@ -195,6 +195,10 @@ module ActionView
# </li>
# </ul>
#
+ # The current object being rendered, as well as the object_counter, will be
+ # available as local variables inside the layout template under the same names
+ # as available in the partial.
+ #
# You can also apply a layout to a block within any template:
#
# <%# app/views/users/_chief.html.erb &>
@@ -282,14 +286,7 @@ module ActionView
spacer = find_template(@options[:spacer_template]).render(@view, @locals)
end
- if layout = @options[:layout]
- layout = find_template(layout)
- end
-
result = @template ? collection_with_template : collection_without_template
-
- result.map!{|content| layout.render(@view, @locals) { content } } if layout
-
result.join(spacer).html_safe
end
@@ -298,7 +295,7 @@ module ActionView
object, as = @object, @variable
if !block && (layout = @options[:layout])
- layout = find_template(layout)
+ layout = find_template(layout, @locals.keys + [@variable])
end
object ||= locals[as]
@@ -384,17 +381,23 @@ module ActionView
segments, locals, template = [], @locals, @template
as, counter = @variable, @variable_counter
+ if layout = @options[:layout]
+ layout = find_template(layout, @locals.keys + [@variable, @variable_counter])
+ end
+
locals[counter] = -1
@collection.each do |object|
locals[counter] += 1
locals[as] = object
- segments << template.render(@view, locals)
+
+ content = template.render(@view, locals)
+ content = layout.render(@view, locals) { content } if layout
+ segments << content
end
-
+
segments
end
-
def collection_without_template
segments, locals, collection_data = [], @locals, @collection_data
@@ -451,7 +454,7 @@ module ActionView
end
def retrieve_variable(path)
- variable = @options[:as].try(:to_sym) || path[%r'_?(\w+)(\.\w+)*$', 1].to_sym
+ variable = @options.fetch(:as) { path[%r'_?(\w+)(\.\w+)*$', 1] }.try(:to_sym)
variable_counter = :"#{variable}_counter" if @collection
[variable, variable_counter]
end
diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb
index b1a5356ddd..22ba047328 100644
--- a/actionpack/test/abstract_unit.rb
+++ b/actionpack/test/abstract_unit.rb
@@ -125,11 +125,11 @@ module ActiveSupport
# have been loaded.
setup_once do
SharedTestRoutes.draw do
- match ':controller(/:action)'
+ get ':controller(/:action)'
end
ActionDispatch::IntegrationTest.app.routes.draw do
- match ':controller(/:action)'
+ get ':controller(/:action)'
end
end
end
diff --git a/actionpack/test/activerecord/active_record_store_test.rb b/actionpack/test/activerecord/active_record_store_test.rb
index 2fe7959f5a..275f25f597 100644
--- a/actionpack/test/activerecord/active_record_store_test.rb
+++ b/actionpack/test/activerecord/active_record_store_test.rb
@@ -254,12 +254,19 @@ class ActiveRecordStoreTest < ActionDispatch::IntegrationTest
end
end
+ def test_session_store_with_all_domains
+ with_test_route_set(:domain => :all) do
+ get '/set_session_value'
+ assert_response :success
+ end
+ end
+
private
def with_test_route_set(options = {})
with_routing do |set|
set.draw do
- match ':action', :to => 'active_record_store_test/test'
+ get ':action', :to => 'active_record_store_test/test'
end
@app = self.class.build_app(set) do |middleware|
diff --git a/actionpack/test/activerecord/render_partial_with_record_identification_test.rb b/actionpack/test/activerecord/render_partial_with_record_identification_test.rb
index 8187eb72d5..409370104d 100644
--- a/actionpack/test/activerecord/render_partial_with_record_identification_test.rb
+++ b/actionpack/test/activerecord/render_partial_with_record_identification_test.rb
@@ -16,7 +16,7 @@ class RenderPartialWithRecordIdentificationController < ActionController::Base
end
def render_with_has_many_through_association
- @developer = Developer.find(:first)
+ @developer = Developer.first
render :partial => @developer.topics
end
@@ -31,7 +31,7 @@ class RenderPartialWithRecordIdentificationController < ActionController::Base
end
def render_with_record
- @developer = Developer.find(:first)
+ @developer = Developer.first
render :partial => @developer
end
diff --git a/actionpack/test/controller/action_pack_assertions_test.rb b/actionpack/test/controller/action_pack_assertions_test.rb
index 01cafe1aca..f5f397c9c0 100644
--- a/actionpack/test/controller/action_pack_assertions_test.rb
+++ b/actionpack/test/controller/action_pack_assertions_test.rb
@@ -162,7 +162,7 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase
def test_string_constraint
with_routing do |set|
set.draw do
- match "photos", :to => 'action_pack_assertions#nothing', :constraints => {:subdomain => "admin"}
+ get "photos", :to => 'action_pack_assertions#nothing', :constraints => {:subdomain => "admin"}
end
end
end
@@ -170,15 +170,18 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase
def test_assert_redirect_to_named_route_failure
with_routing do |set|
set.draw do
- match 'route_one', :to => 'action_pack_assertions#nothing', :as => :route_one
- match 'route_two', :to => 'action_pack_assertions#nothing', :id => 'two', :as => :route_two
- match ':controller/:action'
+ get 'route_one', :to => 'action_pack_assertions#nothing', :as => :route_one
+ get 'route_two', :to => 'action_pack_assertions#nothing', :id => 'two', :as => :route_two
+ get ':controller/:action'
end
process :redirect_to_named_route
assert_raise(ActiveSupport::TestCase::Assertion) do
assert_redirected_to 'http://test.host/route_two'
end
assert_raise(ActiveSupport::TestCase::Assertion) do
+ assert_redirected_to %r(^http://test.host/route_two)
+ end
+ assert_raise(ActiveSupport::TestCase::Assertion) do
assert_redirected_to :controller => 'action_pack_assertions', :action => 'nothing', :id => 'two'
end
assert_raise(ActiveSupport::TestCase::Assertion) do
@@ -192,8 +195,8 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase
with_routing do |set|
set.draw do
- match 'admin/inner_module', :to => 'admin/inner_module#index', :as => :admin_inner_module
- match ':controller/:action'
+ get 'admin/inner_module', :to => 'admin/inner_module#index', :as => :admin_inner_module
+ get ':controller/:action'
end
process :redirect_to_index
# redirection is <{"action"=>"index", "controller"=>"admin/admin/inner_module"}>
@@ -206,12 +209,13 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase
with_routing do |set|
set.draw do
- match '/action_pack_assertions/:id', :to => 'action_pack_assertions#index', :as => :top_level
- match ':controller/:action'
+ get '/action_pack_assertions/:id', :to => 'action_pack_assertions#index', :as => :top_level
+ get ':controller/:action'
end
process :redirect_to_top_level_named_route
# assert_redirected_to "http://test.host/action_pack_assertions/foo" would pass because of exact match early return
assert_redirected_to "/action_pack_assertions/foo"
+ assert_redirected_to %r(/action_pack_assertions/foo)
end
end
@@ -221,8 +225,8 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase
with_routing do |set|
set.draw do
# this controller exists in the admin namespace as well which is the only difference from previous test
- match '/user/:id', :to => 'user#index', :as => :top_level
- match ':controller/:action'
+ get '/user/:id', :to => 'user#index', :as => :top_level
+ get ':controller/:action'
end
process :redirect_to_top_level_named_route
# assert_redirected_to top_level_url('foo') would pass because of exact match early return
diff --git a/actionpack/test/controller/base_test.rb b/actionpack/test/controller/base_test.rb
index 2032aca52e..b9513ccff4 100644
--- a/actionpack/test/controller/base_test.rb
+++ b/actionpack/test/controller/base_test.rb
@@ -158,7 +158,7 @@ class UrlOptionsTest < ActionController::TestCase
def test_url_for_query_params_included
rs = ActionDispatch::Routing::RouteSet.new
rs.draw do
- match 'home' => 'pages#home'
+ get 'home' => 'pages#home'
end
options = {
@@ -174,8 +174,8 @@ class UrlOptionsTest < ActionController::TestCase
def test_url_options_override
with_routing do |set|
set.draw do
- match 'from_view', :to => 'url_options#from_view', :as => :from_view
- match ':controller/:action'
+ get 'from_view', :to => 'url_options#from_view', :as => :from_view
+ get ':controller/:action'
end
get :from_view, :route => "from_view_url"
@@ -189,7 +189,7 @@ class UrlOptionsTest < ActionController::TestCase
def test_url_helpers_does_not_become_actions
with_routing do |set|
set.draw do
- match "account/overview"
+ get "account/overview"
end
assert !@controller.class.action_methods.include?("account_overview_path")
@@ -208,8 +208,8 @@ class DefaultUrlOptionsTest < ActionController::TestCase
def test_default_url_options_override
with_routing do |set|
set.draw do
- match 'from_view', :to => 'default_url_options#from_view', :as => :from_view
- match ':controller/:action'
+ get 'from_view', :to => 'default_url_options#from_view', :as => :from_view
+ get ':controller/:action'
end
get :from_view, :route => "from_view_url"
@@ -226,7 +226,7 @@ class DefaultUrlOptionsTest < ActionController::TestCase
scope("/:locale") do
resources :descriptions
end
- match ':controller/:action'
+ get ':controller/:action'
end
get :from_view, :route => "description_path(1)"
diff --git a/actionpack/test/controller/caching_test.rb b/actionpack/test/controller/caching_test.rb
index a42c68a628..9efe328d62 100644
--- a/actionpack/test/controller/caching_test.rb
+++ b/actionpack/test/controller/caching_test.rb
@@ -102,8 +102,8 @@ class PageCachingTest < ActionController::TestCase
def test_page_caching_resources_saves_to_correct_path_with_extension_even_if_default_route
with_routing do |set|
set.draw do
- match 'posts.:format', :to => 'posts#index', :as => :formatted_posts
- match '/', :to => 'posts#index', :as => :main
+ get 'posts.:format', :to => 'posts#index', :as => :formatted_posts
+ get '/', :to => 'posts#index', :as => :main
end
@params[:format] = 'rss'
assert_equal '/posts.rss', @routes.url_for(@params)
@@ -236,6 +236,7 @@ class ActionCachingTestController < CachingController
caches_action :with_layout
caches_action :with_format_and_http_param, :cache_path => Proc.new { |c| { :key => 'value' } }
caches_action :layout_false, :layout => false
+ caches_action :with_layout_proc_param, :layout => Proc.new { |c| c.params[:layout] }
caches_action :record_not_found, :four_oh_four, :simple_runtime_error
caches_action :streaming
@@ -282,6 +283,7 @@ class ActionCachingTestController < CachingController
alias_method :edit, :index
alias_method :destroy, :index
alias_method :layout_false, :with_layout
+ alias_method :with_layout_proc_param, :with_layout
def expire
expire_action :controller => 'action_caching_test', :action => 'index'
@@ -403,11 +405,40 @@ class ActionCacheTest < ActionController::TestCase
get :layout_false
assert_response :success
assert_not_equal cached_time, @response.body
-
body = body_to_string(read_fragment('hostname.com/action_caching_test/layout_false'))
assert_equal cached_time, body
end
+ def test_action_cache_with_layout_and_layout_cache_false_via_proc
+ get :with_layout_proc_param, :layout => false
+ assert_response :success
+ cached_time = content_to_cache
+ assert_not_equal cached_time, @response.body
+ assert fragment_exist?('hostname.com/action_caching_test/with_layout_proc_param')
+ reset!
+
+ get :with_layout_proc_param, :layout => false
+ assert_response :success
+ assert_not_equal cached_time, @response.body
+ body = body_to_string(read_fragment('hostname.com/action_caching_test/with_layout_proc_param'))
+ assert_equal cached_time, body
+ end
+
+ def test_action_cache_with_layout_and_layout_cache_true_via_proc
+ get :with_layout_proc_param, :layout => true
+ assert_response :success
+ cached_time = content_to_cache
+ assert_not_equal cached_time, @response.body
+ assert fragment_exist?('hostname.com/action_caching_test/with_layout_proc_param')
+ reset!
+
+ get :with_layout_proc_param, :layout => true
+ assert_response :success
+ assert_not_equal cached_time, @response.body
+ body = body_to_string(read_fragment('hostname.com/action_caching_test/with_layout_proc_param'))
+ assert_equal @response.body, body
+ end
+
def test_action_cache_conditional_options
@request.env['HTTP_ACCEPT'] = 'application/json'
get :index
@@ -560,7 +591,7 @@ class ActionCacheTest < ActionController::TestCase
def test_xml_version_of_resource_is_treated_as_different_cache
with_routing do |set|
set.draw do
- match ':controller(/:action(.:format))'
+ get ':controller(/:action(.:format))'
end
get :index, :format => 'xml'
diff --git a/actionpack/test/controller/flash_test.rb b/actionpack/test/controller/flash_test.rb
index 37ccc7a4a5..e4b34125ad 100644
--- a/actionpack/test/controller/flash_test.rb
+++ b/actionpack/test/controller/flash_test.rb
@@ -277,7 +277,7 @@ class FlashIntegrationTest < ActionDispatch::IntegrationTest
def with_test_route_set
with_routing do |set|
set.draw do
- match ':action', :to => FlashIntegrationTest::TestController
+ get ':action', :to => FlashIntegrationTest::TestController
end
@app = self.class.build_app(set) do |middleware|
diff --git a/actionpack/test/controller/integration_test.rb b/actionpack/test/controller/integration_test.rb
index 44f033119d..877b91b563 100644
--- a/actionpack/test/controller/integration_test.rb
+++ b/actionpack/test/controller/integration_test.rb
@@ -466,7 +466,7 @@ class IntegrationProcessTest < ActionDispatch::IntegrationTest
end
set.draw do
- match ':action', :to => controller
+ match ':action', :to => controller, :via => [:get, :post]
get 'get/:action', :to => controller
end
@@ -530,10 +530,10 @@ class ApplicationIntegrationTest < ActionDispatch::IntegrationTest
end
routes.draw do
- match '', :to => 'application_integration_test/test#index', :as => :empty_string
+ get '', :to => 'application_integration_test/test#index', :as => :empty_string
- match 'foo', :to => 'application_integration_test/test#index', :as => :foo
- match 'bar', :to => 'application_integration_test/test#index', :as => :bar
+ get 'foo', :to => 'application_integration_test/test#index', :as => :foo
+ get 'bar', :to => 'application_integration_test/test#index', :as => :bar
end
def app
diff --git a/actionpack/test/controller/mime_responds_test.rb b/actionpack/test/controller/mime_responds_test.rb
index 0e4099ddc6..ac056319fc 100644
--- a/actionpack/test/controller/mime_responds_test.rb
+++ b/actionpack/test/controller/mime_responds_test.rb
@@ -1118,7 +1118,7 @@ class RespondWithControllerTest < ActionController::TestCase
resources :quiz_stores do
resources :customers
end
- match ":controller/:action"
+ get ":controller/:action"
end
yield
end
diff --git a/actionpack/test/controller/new_base/content_type_test.rb b/actionpack/test/controller/new_base/content_type_test.rb
index 4b70031c90..9b57641e75 100644
--- a/actionpack/test/controller/new_base/content_type_test.rb
+++ b/actionpack/test/controller/new_base/content_type_test.rb
@@ -43,7 +43,7 @@ module ContentType
test "default response is HTML and UTF8" do
with_routing do |set|
set.draw do
- match ':controller', :action => 'index'
+ get ':controller', :action => 'index'
end
get "/content_type/base"
diff --git a/actionpack/test/controller/new_base/render_template_test.rb b/actionpack/test/controller/new_base/render_template_test.rb
index ade204c387..00c7df2af8 100644
--- a/actionpack/test/controller/new_base/render_template_test.rb
+++ b/actionpack/test/controller/new_base/render_template_test.rb
@@ -164,7 +164,7 @@ module RenderTemplate
test "rendering with implicit layout" do
with_routing do |set|
- set.draw { match ':controller', :action => :index }
+ set.draw { get ':controller', :action => :index }
get "/render_template/with_layout"
diff --git a/actionpack/test/controller/new_base/render_test.rb b/actionpack/test/controller/new_base/render_test.rb
index 60468bf5c7..cc7f12ac6d 100644
--- a/actionpack/test/controller/new_base/render_test.rb
+++ b/actionpack/test/controller/new_base/render_test.rb
@@ -57,7 +57,7 @@ module Render
test "render with blank" do
with_routing do |set|
set.draw do
- match ":controller", :action => 'index'
+ get ":controller", :action => 'index'
end
get "/render/blank_render"
@@ -70,7 +70,7 @@ module Render
test "rendering more than once raises an exception" do
with_routing do |set|
set.draw do
- match ":controller", :action => 'index'
+ get ":controller", :action => 'index'
end
assert_raises(AbstractController::DoubleRenderError) do
diff --git a/actionpack/test/controller/new_base/render_text_test.rb b/actionpack/test/controller/new_base/render_text_test.rb
index 06d500cca7..e0b38b29fa 100644
--- a/actionpack/test/controller/new_base/render_text_test.rb
+++ b/actionpack/test/controller/new_base/render_text_test.rb
@@ -67,7 +67,7 @@ module RenderText
test "rendering text from a action with default options renders the text with the layout" do
with_routing do |set|
- set.draw { match ':controller', :action => 'index' }
+ set.draw { get ':controller', :action => 'index' }
get "/render_text/simple"
assert_body "hello david"
@@ -77,7 +77,7 @@ module RenderText
test "rendering text from a action with default options renders the text without the layout" do
with_routing do |set|
- set.draw { match ':controller', :action => 'index' }
+ set.draw { get ':controller', :action => 'index' }
get "/render_text/with_layout"
diff --git a/actionpack/test/controller/redirect_test.rb b/actionpack/test/controller/redirect_test.rb
index 6dab42d75d..4331333b98 100644
--- a/actionpack/test/controller/redirect_test.rb
+++ b/actionpack/test/controller/redirect_test.rb
@@ -262,7 +262,7 @@ class RedirectTest < ActionController::TestCase
with_routing do |set|
set.draw do
resources :workshops
- match ':controller/:action'
+ get ':controller/:action'
end
get :redirect_to_existing_record
@@ -296,7 +296,7 @@ class RedirectTest < ActionController::TestCase
def test_redirect_to_with_block_and_accepted_options
with_routing do |set|
set.draw do
- match ':controller/:action'
+ get ':controller/:action'
end
get :redirect_to_with_block_and_options
diff --git a/actionpack/test/controller/render_json_test.rb b/actionpack/test/controller/render_json_test.rb
index 75fed8e933..7c0a6bd67e 100644
--- a/actionpack/test/controller/render_json_test.rb
+++ b/actionpack/test/controller/render_json_test.rb
@@ -102,7 +102,7 @@ class RenderJsonTest < ActionController::TestCase
def test_render_json_with_callback
get :render_json_hello_world_with_callback
assert_equal 'alert({"hello":"world"})', @response.body
- assert_equal 'application/json', @response.content_type
+ assert_equal 'text/javascript', @response.content_type
end
def test_render_json_with_custom_content_type
diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb
index fce13d096c..10f62dad65 100644
--- a/actionpack/test/controller/render_test.rb
+++ b/actionpack/test/controller/render_test.rb
@@ -1188,7 +1188,7 @@ class RenderTest < ActionController::TestCase
with_routing do |set|
set.draw do
resources :customers
- match ':controller/:action'
+ get ':controller/:action'
end
get :head_with_location_object
diff --git a/actionpack/test/controller/render_xml_test.rb b/actionpack/test/controller/render_xml_test.rb
index 8b4f2f5349..4f280c4bec 100644
--- a/actionpack/test/controller/render_xml_test.rb
+++ b/actionpack/test/controller/render_xml_test.rb
@@ -72,7 +72,7 @@ class RenderXmlTest < ActionController::TestCase
with_routing do |set|
set.draw do
resources :customers
- match ':controller/:action'
+ get ':controller/:action'
end
get :render_with_object_location
diff --git a/actionpack/test/controller/rescue_test.rb b/actionpack/test/controller/rescue_test.rb
index 9c51db135b..48e2d6491e 100644
--- a/actionpack/test/controller/rescue_test.rb
+++ b/actionpack/test/controller/rescue_test.rb
@@ -60,11 +60,6 @@ class RescueController < ActionController::Base
render :text => exception.message
end
- # This is a Dispatcher exception and should be in ApplicationController.
- rescue_from ActionController::RoutingError do
- render :text => 'no way'
- end
-
rescue_from ActionView::TemplateError do
render :text => 'action_view templater error'
end
@@ -343,9 +338,9 @@ class RescueTest < ActionDispatch::IntegrationTest
def with_test_routing
with_routing do |set|
set.draw do
- match 'foo', :to => ::RescueTest::TestController.action(:foo)
- match 'invalid', :to => ::RescueTest::TestController.action(:invalid)
- match 'b00m', :to => ::RescueTest::TestController.action(:b00m)
+ get 'foo', :to => ::RescueTest::TestController.action(:foo)
+ get 'invalid', :to => ::RescueTest::TestController.action(:invalid)
+ get 'b00m', :to => ::RescueTest::TestController.action(:b00m)
end
yield
end
diff --git a/actionpack/test/controller/resources_test.rb b/actionpack/test/controller/resources_test.rb
index 3c0a5d36ca..9fc875014c 100644
--- a/actionpack/test/controller/resources_test.rb
+++ b/actionpack/test/controller/resources_test.rb
@@ -680,7 +680,7 @@ class ResourcesTest < ActionController::TestCase
scope '/threads/:thread_id' do
resources :messages, :as => 'thread_messages' do
get :search, :on => :collection
- match :preview, :on => :new
+ get :preview, :on => :new
end
end
end
@@ -698,7 +698,7 @@ class ResourcesTest < ActionController::TestCase
scope '/admin' do
resource :account, :as => :admin_account do
get :login, :on => :member
- match :preview, :on => :new
+ get :preview, :on => :new
end
end
end
diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb
index 272a7da8c5..bcb4e6a766 100644
--- a/actionpack/test/controller/routing_test.rb
+++ b/actionpack/test/controller/routing_test.rb
@@ -17,7 +17,7 @@ class UriReservedCharactersRoutingTest < ActiveSupport::TestCase
def setup
@set = ActionDispatch::Routing::RouteSet.new
@set.draw do
- match ':controller/:action/:variable/*additional'
+ get ':controller/:action/:variable/*additional'
end
safe, unsafe = %w(: @ & = + $ , ;), %w(^ ? # [ ])
@@ -85,7 +85,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_symbols_with_dashes
rs.draw do
- match '/:artist/:song-omg', :to => lambda { |env|
+ get '/:artist/:song-omg', :to => lambda { |env|
resp = JSON.dump env[ActionDispatch::Routing::RouteSet::PARAMETERS_KEY]
[200, {}, [resp]]
}
@@ -97,7 +97,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_id_with_dash
rs.draw do
- match '/journey/:id', :to => lambda { |env|
+ get '/journey/:id', :to => lambda { |env|
resp = JSON.dump env[ActionDispatch::Routing::RouteSet::PARAMETERS_KEY]
[200, {}, [resp]]
}
@@ -109,7 +109,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_dash_with_custom_regexp
rs.draw do
- match '/:artist/:song-omg', :constraints => { :song => /\d+/ }, :to => lambda { |env|
+ get '/:artist/:song-omg', :constraints => { :song => /\d+/ }, :to => lambda { |env|
resp = JSON.dump env[ActionDispatch::Routing::RouteSet::PARAMETERS_KEY]
[200, {}, [resp]]
}
@@ -122,7 +122,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_pre_dash
rs.draw do
- match '/:artist/omg-:song', :to => lambda { |env|
+ get '/:artist/omg-:song', :to => lambda { |env|
resp = JSON.dump env[ActionDispatch::Routing::RouteSet::PARAMETERS_KEY]
[200, {}, [resp]]
}
@@ -134,7 +134,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_pre_dash_with_custom_regexp
rs.draw do
- match '/:artist/omg-:song', :constraints => { :song => /\d+/ }, :to => lambda { |env|
+ get '/:artist/omg-:song', :constraints => { :song => /\d+/ }, :to => lambda { |env|
resp = JSON.dump env[ActionDispatch::Routing::RouteSet::PARAMETERS_KEY]
[200, {}, [resp]]
}
@@ -147,7 +147,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_star_paths_are_greedy
rs.draw do
- match "/*path", :to => lambda { |env|
+ get "/*path", :to => lambda { |env|
x = env["action_dispatch.request.path_parameters"][:path]
[200, {}, [x]]
}, :format => false
@@ -159,7 +159,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_star_paths_are_greedy_but_not_too_much
rs.draw do
- match "/*path", :to => lambda { |env|
+ get "/*path", :to => lambda { |env|
x = JSON.dump env["action_dispatch.request.path_parameters"]
[200, {}, [x]]
}
@@ -172,7 +172,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_optional_star_paths_are_greedy
rs.draw do
- match "/(*filters)", :to => lambda { |env|
+ get "/(*filters)", :to => lambda { |env|
x = env["action_dispatch.request.path_parameters"][:filters]
[200, {}, [x]]
}, :format => false
@@ -184,7 +184,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_optional_star_paths_are_greedy_but_not_too_much
rs.draw do
- match "/(*filters)", :to => lambda { |env|
+ get "/(*filters)", :to => lambda { |env|
x = JSON.dump env["action_dispatch.request.path_parameters"]
[200, {}, [x]]
}
@@ -198,11 +198,11 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_regexp_precidence
@rs.draw do
- match '/whois/:domain', :constraints => {
+ get '/whois/:domain', :constraints => {
:domain => /\w+\.[\w\.]+/ },
:to => lambda { |env| [200, {}, %w{regexp}] }
- match '/whois/:id', :to => lambda { |env| [200, {}, %w{id}] }
+ get '/whois/:id', :to => lambda { |env| [200, {}, %w{id}] }
end
assert_equal 'regexp', get(URI('http://example.org/whois/example.org'))
@@ -217,9 +217,9 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
}
@rs.draw do
- match '/', :constraints => subdomain.new,
+ get '/', :constraints => subdomain.new,
:to => lambda { |env| [200, {}, %w{default}] }
- match '/', :constraints => { :subdomain => 'clients' },
+ get '/', :constraints => { :subdomain => 'clients' },
:to => lambda { |env| [200, {}, %w{clients}] }
end
@@ -229,11 +229,11 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_lambda_constraints
@rs.draw do
- match '/', :constraints => lambda { |req|
+ get '/', :constraints => lambda { |req|
req.subdomain.present? and req.subdomain != "clients" },
:to => lambda { |env| [200, {}, %w{default}] }
- match '/', :constraints => lambda { |req|
+ get '/', :constraints => lambda { |req|
req.subdomain.present? && req.subdomain == "clients" },
:to => lambda { |env| [200, {}, %w{clients}] }
end
@@ -271,7 +271,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
end
def test_default_setup
- @rs.draw { match '/:controller(/:action(/:id))' }
+ @rs.draw { get '/:controller(/:action(/:id))' }
assert_equal({:controller => "content", :action => 'index'}, rs.recognize_path("/content"))
assert_equal({:controller => "content", :action => 'list'}, rs.recognize_path("/content/list"))
assert_equal({:controller => "content", :action => 'show', :id => '10'}, rs.recognize_path("/content/show/10"))
@@ -289,21 +289,21 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_ignores_leading_slash
@rs.clear!
- @rs.draw { match '/:controller(/:action(/:id))'}
+ @rs.draw { get '/:controller(/:action(/:id))'}
test_default_setup
end
def test_route_with_colon_first
rs.draw do
- match '/:controller/:action/:id', :action => 'index', :id => nil
- match ':url', :controller => 'tiny_url', :action => 'translate'
+ get '/:controller/:action/:id', :action => 'index', :id => nil
+ get ':url', :controller => 'tiny_url', :action => 'translate'
end
end
def test_route_with_regexp_for_controller
rs.draw do
- match ':controller/:admintoken(/:action(/:id))', :controller => /admin\/.+/
- match '/:controller(/:action(/:id))'
+ get ':controller/:admintoken(/:action(/:id))', :controller => /admin\/.+/
+ get '/:controller(/:action(/:id))'
end
assert_equal({:controller => "admin/user", :admintoken => "foo", :action => "index"},
@@ -317,7 +317,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_route_with_regexp_and_captures_for_controller
rs.draw do
- match '/:controller(/:action(/:id))', :controller => /admin\/(accounts|users)/
+ get '/:controller(/:action(/:id))', :controller => /admin\/(accounts|users)/
end
assert_equal({:controller => "admin/accounts", :action => "index"}, rs.recognize_path("/admin/accounts"))
assert_equal({:controller => "admin/users", :action => "index"}, rs.recognize_path("/admin/users"))
@@ -326,7 +326,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_route_with_regexp_and_dot
rs.draw do
- match ':controller/:action/:file',
+ get ':controller/:action/:file',
:controller => /admin|user/,
:action => /upload|download/,
:defaults => {:file => nil},
@@ -356,7 +356,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_named_route_with_option
rs.draw do
- match 'page/:title' => 'content#show_page', :as => 'page'
+ get 'page/:title' => 'content#show_page', :as => 'page'
end
assert_equal("http://test.host/page/new%20stuff",
@@ -365,7 +365,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_named_route_with_default
rs.draw do
- match 'page/:title' => 'content#show_page', :title => 'AboutPage', :as => 'page'
+ get 'page/:title' => 'content#show_page', :title => 'AboutPage', :as => 'page'
end
assert_equal("http://test.host/page/AboutRails",
@@ -375,7 +375,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_named_route_with_path_prefix
rs.draw do
scope "my" do
- match 'page' => 'content#show_page', :as => 'page'
+ get 'page' => 'content#show_page', :as => 'page'
end
end
@@ -386,7 +386,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_named_route_with_blank_path_prefix
rs.draw do
scope "" do
- match 'page' => 'content#show_page', :as => 'page'
+ get 'page' => 'content#show_page', :as => 'page'
end
end
@@ -396,7 +396,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_named_route_with_nested_controller
rs.draw do
- match 'admin/user' => 'admin/user#index', :as => "users"
+ get 'admin/user' => 'admin/user#index', :as => "users"
end
assert_equal("http://test.host/admin/user",
@@ -405,7 +405,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_optimised_named_route_with_host
rs.draw do
- match 'page' => 'content#show_page', :as => 'pages', :host => 'foo.com'
+ get 'page' => 'content#show_page', :as => 'pages', :host => 'foo.com'
end
routes = setup_for_named_route
routes.expects(:url_for).with({
@@ -424,7 +424,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_named_route_without_hash
rs.draw do
- match ':controller/:action/:id', :as => 'normal'
+ get ':controller/:action/:id', :as => 'normal'
end
end
@@ -448,9 +448,9 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_named_route_with_regexps
rs.draw do
- match 'page/:year/:month/:day/:title' => 'page#show', :as => 'article',
+ get 'page/:year/:month/:day/:title' => 'page#show', :as => 'article',
:year => /\d+/, :month => /\d+/, :day => /\d+/
- match ':controller/:action/:id'
+ get ':controller/:action/:id'
end
routes = setup_for_named_route
@@ -460,7 +460,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
end
def test_changing_controller
- @rs.draw { match ':controller/:action/:id' }
+ @rs.draw { get ':controller/:action/:id' }
assert_equal '/admin/stuff/show/10',
url_for(rs, {:controller => 'stuff', :action => 'show', :id => 10},
@@ -469,8 +469,8 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_paths_escaped
rs.draw do
- match 'file/*path' => 'content#show_file', :as => 'path'
- match ':controller/:action/:id'
+ get 'file/*path' => 'content#show_file', :as => 'path'
+ get ':controller/:action/:id'
end
# No + to space in URI escaping, only for query params.
@@ -486,7 +486,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_paths_slashes_unescaped_with_ordered_parameters
rs.draw do
- match '/file/*path' => 'content#index', :as => 'path'
+ get '/file/*path' => 'content#index', :as => 'path'
end
# No / to %2F in URI, only for query params.
@@ -495,14 +495,14 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_non_controllers_cannot_be_matched
rs.draw do
- match ':controller/:action/:id'
+ get ':controller/:action/:id'
end
assert_raise(ActionController::RoutingError) { rs.recognize_path("/not_a/show/10") }
end
def test_should_list_options_diff_when_routing_constraints_dont_match
rs.draw do
- match 'post/:id' => 'post#show', :constraints => { :id => /\d+/ }, :as => 'post'
+ get 'post/:id' => 'post#show', :constraints => { :id => /\d+/ }, :as => 'post'
end
assert_raise(ActionController::RoutingError) do
url_for(rs, { :controller => 'post', :action => 'show', :bad_param => "foo", :use_route => "post" })
@@ -511,7 +511,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_dynamic_path_allowed
rs.draw do
- match '*path' => 'content#show_file'
+ get '*path' => 'content#show_file'
end
assert_equal '/pages/boo',
@@ -520,7 +520,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_dynamic_recall_paths_allowed
rs.draw do
- match '*path' => 'content#show_file'
+ get '*path' => 'content#show_file'
end
assert_equal '/pages/boo',
@@ -529,8 +529,8 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_backwards
rs.draw do
- match 'page/:id(/:action)' => 'pages#show'
- match ':controller(/:action(/:id))'
+ get 'page/:id(/:action)' => 'pages#show'
+ get ':controller(/:action(/:id))'
end
assert_equal '/page/20', url_for(rs, { :id => 20 }, { :controller => 'pages', :action => 'show' })
@@ -540,8 +540,8 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_route_with_fixnum_default
rs.draw do
- match 'page(/:id)' => 'content#show_page', :id => 1
- match ':controller/:action/:id'
+ get 'page(/:id)' => 'content#show_page', :id => 1
+ get ':controller/:action/:id'
end
assert_equal '/page', url_for(rs, { :controller => 'content', :action => 'show_page' })
@@ -557,8 +557,8 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
# For newer revision
def test_route_with_text_default
rs.draw do
- match 'page/:id' => 'content#show_page', :id => 1
- match ':controller/:action/:id'
+ get 'page/:id' => 'content#show_page', :id => 1
+ get ':controller/:action/:id'
end
assert_equal '/page/foo', url_for(rs, { :controller => 'content', :action => 'show_page', :id => 'foo' })
@@ -573,13 +573,13 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
end
def test_action_expiry
- @rs.draw { match ':controller(/:action(/:id))' }
+ @rs.draw { get ':controller(/:action(/:id))' }
assert_equal '/content', url_for(rs, { :controller => 'content' }, { :controller => 'content', :action => 'show' })
end
def test_requirement_should_prevent_optional_id
rs.draw do
- match 'post/:id' => 'post#show', :constraints => {:id => /\d+/}, :as => 'post'
+ get 'post/:id' => 'post#show', :constraints => {:id => /\d+/}, :as => 'post'
end
assert_equal '/post/10', url_for(rs, { :controller => 'post', :action => 'show', :id => 10 })
@@ -591,11 +591,11 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_both_requirement_and_optional
rs.draw do
- match('test(/:year)' => 'post#show', :as => 'blog',
+ get('test(/:year)' => 'post#show', :as => 'blog',
:defaults => { :year => nil },
:constraints => { :year => /\d{4}/ }
)
- match ':controller/:action/:id'
+ get ':controller/:action/:id'
end
assert_equal '/test', url_for(rs, { :controller => 'post', :action => 'show' })
@@ -606,8 +606,8 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_set_to_nil_forgets
rs.draw do
- match 'pages(/:year(/:month(/:day)))' => 'content#list_pages', :month => nil, :day => nil
- match ':controller/:action/:id'
+ get 'pages(/:year(/:month(/:day)))' => 'content#list_pages', :month => nil, :day => nil
+ get ':controller/:action/:id'
end
assert_equal '/pages/2005',
@@ -649,8 +649,8 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_named_route_method
rs.draw do
- match 'categories' => 'content#categories', :as => 'categories'
- match ':controller(/:action(/:id))'
+ get 'categories' => 'content#categories', :as => 'categories'
+ get ':controller(/:action(/:id))'
end
assert_equal '/categories', url_for(rs, { :controller => 'content', :action => 'categories' })
@@ -664,9 +664,9 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_nil_defaults
rs.draw do
- match 'journal' => 'content#list_journal',
+ get 'journal' => 'content#list_journal',
:date => nil, :user_id => nil
- match ':controller/:action/:id'
+ get ':controller/:action/:id'
end
assert_equal '/journal', url_for(rs, {
@@ -698,7 +698,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_recognize_array_of_methods
rs.draw do
match '/match' => 'books#get_or_post', :via => [:get, :post]
- match '/match' => 'books#not_get_or_post'
+ put '/match' => 'books#not_get_or_post'
end
params = rs.recognize_path("/match", :method => :post)
@@ -710,10 +710,10 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_subpath_recognized
rs.draw do
- match '/books/:id/edit' => 'subpath_books#edit'
- match '/items/:id/:action' => 'subpath_books'
- match '/posts/new/:action' => 'subpath_books'
- match '/posts/:id' => 'subpath_books#show'
+ get '/books/:id/edit' => 'subpath_books#edit'
+ get '/items/:id/:action' => 'subpath_books'
+ get '/posts/new/:action' => 'subpath_books'
+ get '/posts/:id' => 'subpath_books#show'
end
hash = rs.recognize_path "/books/17/edit"
@@ -735,9 +735,9 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_subpath_generated
rs.draw do
- match '/books/:id/edit' => 'subpath_books#edit'
- match '/items/:id/:action' => 'subpath_books'
- match '/posts/new/:action' => 'subpath_books'
+ get '/books/:id/edit' => 'subpath_books#edit'
+ get '/items/:id/:action' => 'subpath_books'
+ get '/posts/new/:action' => 'subpath_books'
end
assert_equal "/books/7/edit", url_for(rs, { :controller => "subpath_books", :id => 7, :action => "edit" })
@@ -747,7 +747,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_failed_constraints_raises_exception_with_violated_constraints
rs.draw do
- match 'foos/:id' => 'foos#show', :as => 'foo_with_requirement', :constraints => { :id => /\d+/ }
+ get 'foos/:id' => 'foos#show', :as => 'foo_with_requirement', :constraints => { :id => /\d+/ }
end
assert_raise(ActionController::RoutingError) do
@@ -758,11 +758,11 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_routes_changed_correctly_after_clear
rs = ::ActionDispatch::Routing::RouteSet.new
rs.draw do
- match 'ca' => 'ca#aa'
- match 'cb' => 'cb#ab'
- match 'cc' => 'cc#ac'
- match ':controller/:action/:id'
- match ':controller/:action/:id.:format'
+ get 'ca' => 'ca#aa'
+ get 'cb' => 'cb#ab'
+ get 'cc' => 'cc#ac'
+ get ':controller/:action/:id'
+ get ':controller/:action/:id.:format'
end
hash = rs.recognize_path "/cc"
@@ -771,10 +771,10 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
assert_equal %w(cc ac), [hash[:controller], hash[:action]]
rs.draw do
- match 'cb' => 'cb#ab'
- match 'cc' => 'cc#ac'
- match ':controller/:action/:id'
- match ':controller/:action/:id.:format'
+ get 'cb' => 'cb#ab'
+ get 'cc' => 'cc#ac'
+ get ':controller/:action/:id'
+ get ':controller/:action/:id.:format'
end
hash = rs.recognize_path "/cc"
@@ -799,29 +799,29 @@ class RouteSetTest < ActiveSupport::TestCase
@default_route_set ||= begin
set = ROUTING::RouteSet.new
set.draw do
- match '/:controller(/:action(/:id))'
+ get '/:controller(/:action(/:id))'
end
set
end
end
def test_generate_extras
- set.draw { match ':controller/(:action(/:id))' }
+ set.draw { get ':controller/(:action(/:id))' }
path, extras = set.generate_extras(:controller => "foo", :action => "bar", :id => 15, :this => "hello", :that => "world")
assert_equal "/foo/bar/15", path
assert_equal %w(that this), extras.map { |e| e.to_s }.sort
end
def test_extra_keys
- set.draw { match ':controller/:action/:id' }
+ set.draw { get ':controller/:action/:id' }
extras = set.extra_keys(:controller => "foo", :action => "bar", :id => 15, :this => "hello", :that => "world")
assert_equal %w(that this), extras.map { |e| e.to_s }.sort
end
def test_generate_extras_not_first
set.draw do
- match ':controller/:action/:id.:format'
- match ':controller/:action/:id'
+ get ':controller/:action/:id.:format'
+ get ':controller/:action/:id'
end
path, extras = set.generate_extras(:controller => "foo", :action => "bar", :id => 15, :this => "hello", :that => "world")
assert_equal "/foo/bar/15", path
@@ -830,8 +830,8 @@ class RouteSetTest < ActiveSupport::TestCase
def test_generate_not_first
set.draw do
- match ':controller/:action/:id.:format'
- match ':controller/:action/:id'
+ get ':controller/:action/:id.:format'
+ get ':controller/:action/:id'
end
assert_equal "/foo/bar/15?this=hello",
url_for(set, { :controller => "foo", :action => "bar", :id => 15, :this => "hello" })
@@ -839,8 +839,8 @@ class RouteSetTest < ActiveSupport::TestCase
def test_extra_keys_not_first
set.draw do
- match ':controller/:action/:id.:format'
- match ':controller/:action/:id'
+ get ':controller/:action/:id.:format'
+ get ':controller/:action/:id'
end
extras = set.extra_keys(:controller => "foo", :action => "bar", :id => 15, :this => "hello", :that => "world")
assert_equal %w(that this), extras.map { |e| e.to_s }.sort
@@ -849,7 +849,7 @@ class RouteSetTest < ActiveSupport::TestCase
def test_draw
assert_equal 0, set.routes.size
set.draw do
- match '/hello/world' => 'a#b'
+ get '/hello/world' => 'a#b'
end
assert_equal 1, set.routes.size
end
@@ -857,7 +857,7 @@ class RouteSetTest < ActiveSupport::TestCase
def test_draw_symbol_controller_name
assert_equal 0, set.routes.size
set.draw do
- match '/users/index' => 'users#index'
+ get '/users/index' => 'users#index'
end
set.recognize_path('/users/index', :method => :get)
assert_equal 1, set.routes.size
@@ -866,7 +866,7 @@ class RouteSetTest < ActiveSupport::TestCase
def test_named_draw
assert_equal 0, set.routes.size
set.draw do
- match '/hello/world' => 'a#b', :as => 'hello'
+ get '/hello/world' => 'a#b', :as => 'hello'
end
assert_equal 1, set.routes.size
assert_equal set.routes.first, set.named_routes[:hello]
@@ -874,40 +874,23 @@ class RouteSetTest < ActiveSupport::TestCase
def test_earlier_named_routes_take_precedence
set.draw do
- match '/hello/world' => 'a#b', :as => 'hello'
- match '/hello' => 'a#b', :as => 'hello'
+ get '/hello/world' => 'a#b', :as => 'hello'
+ get '/hello' => 'a#b', :as => 'hello'
end
assert_equal set.routes.first, set.named_routes[:hello]
end
def setup_named_route_test
set.draw do
- match '/people(/:id)' => 'people#show', :as => 'show'
- match '/people' => 'people#index', :as => 'index'
- match '/people/go/:foo/:bar/joe(/:id)' => 'people#multi', :as => 'multi'
- match '/admin/users' => 'admin/users#index', :as => "users"
+ get '/people(/:id)' => 'people#show', :as => 'show'
+ get '/people' => 'people#index', :as => 'index'
+ get '/people/go/:foo/:bar/joe(/:id)' => 'people#multi', :as => 'multi'
+ get '/admin/users' => 'admin/users#index', :as => "users"
end
MockController.build(set.url_helpers).new
end
- def test_named_route_hash_access_method
- controller = setup_named_route_test
-
- assert_equal(
- { :controller => 'people', :action => 'show', :id => 5, :use_route => "show", :only_path => false },
- controller.send(:hash_for_show_url, :id => 5))
-
- assert_equal(
- { :controller => 'people', :action => 'index', :use_route => "index", :only_path => false },
- controller.send(:hash_for_index_url))
-
- assert_equal(
- { :controller => 'people', :action => 'show', :id => 5, :use_route => "show", :only_path => true },
- controller.send(:hash_for_show_path, :id => 5)
- )
- end
-
def test_named_route_url_method
controller = setup_named_route_test
@@ -919,7 +902,6 @@ class RouteSetTest < ActiveSupport::TestCase
assert_equal "http://test.host/admin/users", controller.send(:users_url)
assert_equal '/admin/users', controller.send(:users_path)
- assert_equal '/admin/users', url_for(set, controller.send(:hash_for_users_url), { :controller => 'users', :action => 'index' })
end
def test_named_route_url_method_with_anchor
@@ -985,7 +967,7 @@ class RouteSetTest < ActiveSupport::TestCase
def test_draw_default_route
set.draw do
- match '/:controller/:action/:id'
+ get '/:controller/:action/:id'
end
assert_equal 1, set.routes.size
@@ -999,8 +981,8 @@ class RouteSetTest < ActiveSupport::TestCase
def test_route_with_parameter_shell
set.draw do
- match 'page/:id' => 'pages#show', :id => /\d+/
- match '/:controller(/:action(/:id))'
+ get 'page/:id' => 'pages#show', :id => /\d+/
+ get '/:controller(/:action(/:id))'
end
assert_equal({:controller => 'pages', :action => 'index'}, set.recognize_path('/pages'))
@@ -1014,7 +996,7 @@ class RouteSetTest < ActiveSupport::TestCase
def test_route_constraints_on_request_object_with_anchors_are_valid
assert_nothing_raised do
set.draw do
- match 'page/:id' => 'pages#show', :constraints => { :host => /^foo$/ }
+ get 'page/:id' => 'pages#show', :constraints => { :host => /^foo$/ }
end
end
end
@@ -1022,27 +1004,27 @@ class RouteSetTest < ActiveSupport::TestCase
def test_route_constraints_with_anchor_chars_are_invalid
assert_raise ArgumentError do
set.draw do
- match 'page/:id' => 'pages#show', :id => /^\d+/
+ get 'page/:id' => 'pages#show', :id => /^\d+/
end
end
assert_raise ArgumentError do
set.draw do
- match 'page/:id' => 'pages#show', :id => /\A\d+/
+ get 'page/:id' => 'pages#show', :id => /\A\d+/
end
end
assert_raise ArgumentError do
set.draw do
- match 'page/:id' => 'pages#show', :id => /\d+$/
+ get 'page/:id' => 'pages#show', :id => /\d+$/
end
end
assert_raise ArgumentError do
set.draw do
- match 'page/:id' => 'pages#show', :id => /\d+\Z/
+ get 'page/:id' => 'pages#show', :id => /\d+\Z/
end
end
assert_raise ArgumentError do
set.draw do
- match 'page/:id' => 'pages#show', :id => /\d+\z/
+ get 'page/:id' => 'pages#show', :id => /\d+\z/
end
end
end
@@ -1057,7 +1039,7 @@ class RouteSetTest < ActiveSupport::TestCase
def test_recognize_with_encoded_id_and_regex
set.draw do
- match 'page/:id' => 'pages#show', :id => /[a-zA-Z0-9\+]+/
+ get 'page/:id' => 'pages#show', :id => /[a-zA-Z0-9\+]+/
end
assert_equal({:controller => 'pages', :action => 'show', :id => '10'}, set.recognize_path('/page/10'))
@@ -1128,7 +1110,7 @@ class RouteSetTest < ActiveSupport::TestCase
def test_typo_recognition
set.draw do
- match 'articles/:year/:month/:day/:title' => 'articles#permalink',
+ get 'articles/:year/:month/:day/:title' => 'articles#permalink',
:year => /\d{4}/, :day => /\d{1,2}/, :month => /\d{1,2}/
end
@@ -1143,7 +1125,7 @@ class RouteSetTest < ActiveSupport::TestCase
def test_routing_traversal_does_not_load_extra_classes
assert !Object.const_defined?("Profiler__"), "Profiler should not be loaded"
set.draw do
- match '/profile' => 'profile#index'
+ get '/profile' => 'profile#index'
end
set.recognize_path("/profile") rescue nil
@@ -1177,8 +1159,8 @@ class RouteSetTest < ActiveSupport::TestCase
def test_generate_with_default_action
set.draw do
- match "/people", :controller => "people", :action => "index"
- match "/people/list", :controller => "people", :action => "list"
+ get "/people", :controller => "people", :action => "index"
+ get "/people/list", :controller => "people", :action => "list"
end
url = url_for(set, { :controller => "people", :action => "list" })
@@ -1197,7 +1179,7 @@ class RouteSetTest < ActiveSupport::TestCase
set.draw do
namespace 'api' do
- match 'inventory' => 'products#inventory'
+ get 'inventory' => 'products#inventory'
end
end
@@ -1222,7 +1204,7 @@ class RouteSetTest < ActiveSupport::TestCase
def test_namespace_with_path_prefix
set.draw do
scope :module => "api", :path => "prefix" do
- match 'inventory' => 'products#inventory'
+ get 'inventory' => 'products#inventory'
end
end
@@ -1234,7 +1216,7 @@ class RouteSetTest < ActiveSupport::TestCase
def test_namespace_with_blank_path_prefix
set.draw do
scope :module => "api", :path => "" do
- match 'inventory' => 'products#inventory'
+ get 'inventory' => 'products#inventory'
end
end
@@ -1244,7 +1226,7 @@ class RouteSetTest < ActiveSupport::TestCase
end
def test_generate_changes_controller_module
- set.draw { match ':controller/:action/:id' }
+ set.draw { get ':controller/:action/:id' }
current = { :controller => "bling/bloop", :action => "bap", :id => 9 }
assert_equal "/foo/bar/baz/7",
@@ -1253,7 +1235,7 @@ class RouteSetTest < ActiveSupport::TestCase
def test_id_is_sticky_when_it_ought_to_be
set.draw do
- match ':controller/:id/:action'
+ get ':controller/:id/:action'
end
url = url_for(set, { :action => "destroy" }, { :controller => "people", :action => "show", :id => "7" })
@@ -1262,8 +1244,8 @@ class RouteSetTest < ActiveSupport::TestCase
def test_use_static_path_when_possible
set.draw do
- match 'about' => "welcome#about"
- match ':controller/:action/:id'
+ get 'about' => "welcome#about"
+ get ':controller/:action/:id'
end
url = url_for(set, { :controller => "welcome", :action => "about" },
@@ -1273,7 +1255,7 @@ class RouteSetTest < ActiveSupport::TestCase
end
def test_generate
- set.draw { match ':controller/:action/:id' }
+ set.draw { get ':controller/:action/:id' }
args = { :controller => "foo", :action => "bar", :id => "7", :x => "y" }
assert_equal "/foo/bar/7?x=y", url_for(set, args)
@@ -1284,7 +1266,7 @@ class RouteSetTest < ActiveSupport::TestCase
def test_generate_with_path_prefix
set.draw do
scope "my" do
- match ':controller(/:action(/:id))'
+ get ':controller(/:action(/:id))'
end
end
@@ -1295,7 +1277,7 @@ class RouteSetTest < ActiveSupport::TestCase
def test_generate_with_blank_path_prefix
set.draw do
scope "" do
- match ':controller(/:action(/:id))'
+ get ':controller(/:action(/:id))'
end
end
@@ -1305,9 +1287,9 @@ class RouteSetTest < ActiveSupport::TestCase
def test_named_routes_are_never_relative_to_modules
set.draw do
- match "/connection/manage(/:action)" => 'connection/manage#index'
- match "/connection/connection" => "connection/connection#index"
- match '/connection' => 'connection#index', :as => 'family_connection'
+ get "/connection/manage(/:action)" => 'connection/manage#index'
+ get "/connection/connection" => "connection/connection#index"
+ get '/connection' => 'connection#index', :as => 'family_connection'
end
url = url_for(set, { :controller => "connection" }, { :controller => 'connection/manage' })
@@ -1319,7 +1301,7 @@ class RouteSetTest < ActiveSupport::TestCase
def test_action_left_off_when_id_is_recalled
set.draw do
- match ':controller(/:action(/:id))'
+ get ':controller(/:action(/:id))'
end
assert_equal '/books', url_for(set,
{:controller => 'books', :action => 'index'},
@@ -1329,8 +1311,8 @@ class RouteSetTest < ActiveSupport::TestCase
def test_query_params_will_be_shown_when_recalled
set.draw do
- match 'show_weblog/:parameter' => 'weblog#show'
- match ':controller(/:action(/:id))'
+ get 'show_weblog/:parameter' => 'weblog#show'
+ get ':controller(/:action(/:id))'
end
assert_equal '/weblog/edit?parameter=1', url_for(set,
{:action => 'edit', :parameter => 1},
@@ -1340,7 +1322,7 @@ class RouteSetTest < ActiveSupport::TestCase
def test_format_is_not_inherit
set.draw do
- match '/posts(.:format)' => 'posts#index'
+ get '/posts(.:format)' => 'posts#index'
end
assert_equal '/posts', url_for(set,
@@ -1355,7 +1337,7 @@ class RouteSetTest < ActiveSupport::TestCase
end
def test_expiry_determination_should_consider_values_with_to_param
- set.draw { match 'projects/:project_id/:controller/:action' }
+ set.draw { get 'projects/:project_id/:controller/:action' }
assert_equal '/projects/1/weblog/show', url_for(set,
{ :action => 'show', :project_id => 1 },
{ :controller => 'weblog', :action => 'show', :project_id => '1' })
@@ -1365,7 +1347,7 @@ class RouteSetTest < ActiveSupport::TestCase
set.draw do
resources :projects do
member do
- match 'milestones' => 'milestones#index', :as => 'milestones'
+ get 'milestones' => 'milestones#index', :as => 'milestones'
end
end
end
@@ -1398,7 +1380,7 @@ class RouteSetTest < ActiveSupport::TestCase
def test_route_constraints_with_unsupported_regexp_options_must_error
assert_raise ArgumentError do
set.draw do
- match 'page/:name' => 'pages#show',
+ get 'page/:name' => 'pages#show',
:constraints => { :name => /(david|jamis)/m }
end
end
@@ -1407,13 +1389,13 @@ class RouteSetTest < ActiveSupport::TestCase
def test_route_constraints_with_supported_options_must_not_error
assert_nothing_raised do
set.draw do
- match 'page/:name' => 'pages#show',
+ get 'page/:name' => 'pages#show',
:constraints => { :name => /(david|jamis)/i }
end
end
assert_nothing_raised do
set.draw do
- match 'page/:name' => 'pages#show',
+ get 'page/:name' => 'pages#show',
:constraints => { :name => / # Desperately overcommented regexp
( #Either
david #The Creator
@@ -1427,7 +1409,7 @@ class RouteSetTest < ActiveSupport::TestCase
def test_route_with_subdomain_and_constraints_must_receive_params
name_param = nil
set.draw do
- match 'page/:name' => 'pages#show', :constraints => lambda {|request|
+ get 'page/:name' => 'pages#show', :constraints => lambda {|request|
name_param = request.params[:name]
return true
}
@@ -1439,7 +1421,7 @@ class RouteSetTest < ActiveSupport::TestCase
def test_route_requirement_recognize_with_ignore_case
set.draw do
- match 'page/:name' => 'pages#show',
+ get 'page/:name' => 'pages#show',
:constraints => {:name => /(david|jamis)/i}
end
assert_equal({:controller => 'pages', :action => 'show', :name => 'jamis'}, set.recognize_path('/page/jamis'))
@@ -1451,7 +1433,7 @@ class RouteSetTest < ActiveSupport::TestCase
def test_route_requirement_generate_with_ignore_case
set.draw do
- match 'page/:name' => 'pages#show',
+ get 'page/:name' => 'pages#show',
:constraints => {:name => /(david|jamis)/i}
end
@@ -1466,7 +1448,7 @@ class RouteSetTest < ActiveSupport::TestCase
def test_route_requirement_recognize_with_extended_syntax
set.draw do
- match 'page/:name' => 'pages#show',
+ get 'page/:name' => 'pages#show',
:constraints => {:name => / # Desperately overcommented regexp
( #Either
david #The Creator
@@ -1486,7 +1468,7 @@ class RouteSetTest < ActiveSupport::TestCase
def test_route_requirement_with_xi_modifiers
set.draw do
- match 'page/:name' => 'pages#show',
+ get 'page/:name' => 'pages#show',
:constraints => {:name => / # Desperately overcommented regexp
( #Either
david #The Creator
@@ -1504,8 +1486,8 @@ class RouteSetTest < ActiveSupport::TestCase
def test_routes_with_symbols
set.draw do
- match 'unnamed', :controller => :pages, :action => :show, :name => :as_symbol
- match 'named' , :controller => :pages, :action => :show, :name => :as_symbol, :as => :named
+ get 'unnamed', :controller => :pages, :action => :show, :name => :as_symbol
+ get 'named' , :controller => :pages, :action => :show, :name => :as_symbol, :as => :named
end
assert_equal({:controller => 'pages', :action => 'show', :name => :as_symbol}, set.recognize_path('/unnamed'))
assert_equal({:controller => 'pages', :action => 'show', :name => :as_symbol}, set.recognize_path('/named'))
@@ -1513,8 +1495,8 @@ class RouteSetTest < ActiveSupport::TestCase
def test_regexp_chunk_should_add_question_mark_for_optionals
set.draw do
- match '/' => 'foo#index'
- match '/hello' => 'bar#index'
+ get '/' => 'foo#index'
+ get '/hello' => 'bar#index'
end
assert_equal '/', url_for(set, { :controller => 'foo' })
@@ -1526,7 +1508,7 @@ class RouteSetTest < ActiveSupport::TestCase
def test_assign_route_options_with_anchor_chars
set.draw do
- match '/cars/:action/:person/:car/', :controller => 'cars'
+ get '/cars/:action/:person/:car/', :controller => 'cars'
end
assert_equal '/cars/buy/1/2', url_for(set, { :controller => 'cars', :action => 'buy', :person => '1', :car => '2' })
@@ -1536,7 +1518,7 @@ class RouteSetTest < ActiveSupport::TestCase
def test_segmentation_of_dot_path
set.draw do
- match '/books/:action.rss', :controller => 'books'
+ get '/books/:action.rss', :controller => 'books'
end
assert_equal '/books/list.rss', url_for(set, { :controller => 'books', :action => 'list' })
@@ -1546,7 +1528,7 @@ class RouteSetTest < ActiveSupport::TestCase
def test_segmentation_of_dynamic_dot_path
set.draw do
- match '/books(/:action(.:format))', :controller => 'books'
+ get '/books(/:action(.:format))', :controller => 'books'
end
assert_equal '/books/list.rss', url_for(set, { :controller => 'books', :action => 'list', :format => 'rss' })
@@ -1562,7 +1544,7 @@ class RouteSetTest < ActiveSupport::TestCase
def test_slashes_are_implied
@set = nil
- set.draw { match("/:controller(/:action(/:id))") }
+ set.draw { get("/:controller(/:action(/:id))") }
assert_equal '/content', url_for(set, { :controller => 'content', :action => 'index' })
assert_equal '/content/list', url_for(set, { :controller => 'content', :action => 'list' })
@@ -1647,13 +1629,13 @@ class RouteSetTest < ActiveSupport::TestCase
def test_generate_with_default_params
set.draw do
- match 'dummy/page/:page' => 'dummy#show'
- match 'dummy/dots/page.:page' => 'dummy#dots'
- match 'ibocorp(/:page)' => 'ibocorp#show',
+ get 'dummy/page/:page' => 'dummy#show'
+ get 'dummy/dots/page.:page' => 'dummy#dots'
+ get 'ibocorp(/:page)' => 'ibocorp#show',
:constraints => { :page => /\d+/ },
:defaults => { :page => 1 }
- match ':controller/:action/:id'
+ get ':controller/:action/:id'
end
assert_equal '/ibocorp', url_for(set, { :controller => 'ibocorp', :action => "show", :page => 1 })
@@ -1661,17 +1643,17 @@ class RouteSetTest < ActiveSupport::TestCase
def test_generate_with_optional_params_recalls_last_request
set.draw do
- match "blog/", :controller => "blog", :action => "index"
+ get "blog/", :controller => "blog", :action => "index"
- match "blog(/:year(/:month(/:day)))",
+ get "blog(/:year(/:month(/:day)))",
:controller => "blog",
:action => "show_date",
:constraints => { :year => /(19|20)\d\d/, :month => /[01]?\d/, :day => /[0-3]?\d/ },
:day => nil, :month => nil
- match "blog/show/:id", :controller => "blog", :action => "show", :id => /\d+/
- match "blog/:controller/:action(/:id)"
- match "*anything", :controller => "blog", :action => "unknown_request"
+ get "blog/show/:id", :controller => "blog", :action => "show", :id => /\d+/
+ get "blog/:controller/:action(/:id)"
+ get "*anything", :controller => "blog", :action => "unknown_request"
end
assert_equal({:controller => "blog", :action => "index"}, set.recognize_path("/blog"))
@@ -1719,7 +1701,7 @@ class RackMountIntegrationTests < ActiveSupport::TestCase
root :to => 'users#index'
end
- match '/blog(/:year(/:month(/:day)))' => 'posts#show_date',
+ get '/blog(/:year(/:month(/:day)))' => 'posts#show_date',
:constraints => {
:year => /(19|20)\d\d/,
:month => /[01]?\d/,
@@ -1728,37 +1710,37 @@ class RackMountIntegrationTests < ActiveSupport::TestCase
:day => nil,
:month => nil
- match 'archive/:year', :controller => 'archive', :action => 'index',
+ get 'archive/:year', :controller => 'archive', :action => 'index',
:defaults => { :year => nil },
:constraints => { :year => /\d{4}/ },
:as => "blog"
resources :people
- match 'legacy/people' => "people#index", :legacy => "true"
+ get 'legacy/people' => "people#index", :legacy => "true"
- match 'symbols', :controller => :symbols, :action => :show, :name => :as_symbol
- match 'id_default(/:id)' => "foo#id_default", :id => 1
+ get 'symbols', :controller => :symbols, :action => :show, :name => :as_symbol
+ get 'id_default(/:id)' => "foo#id_default", :id => 1
match 'get_or_post' => "foo#get_or_post", :via => [:get, :post]
- match 'optional/:optional' => "posts#index"
- match 'projects/:project_id' => "project#index", :as => "project"
- match 'clients' => "projects#index"
+ get 'optional/:optional' => "posts#index"
+ get 'projects/:project_id' => "project#index", :as => "project"
+ get 'clients' => "projects#index"
- match 'ignorecase/geocode/:postalcode' => 'geocode#show', :postalcode => /hx\d\d-\d[a-z]{2}/i
- match 'extended/geocode/:postalcode' => 'geocode#show',:constraints => {
+ get 'ignorecase/geocode/:postalcode' => 'geocode#show', :postalcode => /hx\d\d-\d[a-z]{2}/i
+ get 'extended/geocode/:postalcode' => 'geocode#show',:constraints => {
:postalcode => /# Postcode format
\d{5} #Prefix
(-\d{4})? #Suffix
/x
}, :as => "geocode"
- match 'news(.:format)' => "news#index"
+ get 'news(.:format)' => "news#index"
- match 'comment/:id(/:action)' => "comments#show"
- match 'ws/:controller(/:action(/:id))', :ws => true
- match 'account(/:action)' => "account#subscription"
- match 'pages/:page_id/:controller(/:action(/:id))'
- match ':controller/ping', :action => 'ping'
- match ':controller(/:action(/:id))(.:format)'
+ get 'comment/:id(/:action)' => "comments#show"
+ get 'ws/:controller(/:action(/:id))', :ws => true
+ get 'account(/:action)' => "account#subscription"
+ get 'pages/:page_id/:controller(/:action(/:id))'
+ get ':controller/ping', :action => 'ping'
+ match ':controller(/:action(/:id))(.:format)', :via => :all
root :to => "news#index"
}
diff --git a/actionpack/test/controller/send_file_test.rb b/actionpack/test/controller/send_file_test.rb
index 3af17f495c..6fc3556e31 100644
--- a/actionpack/test/controller/send_file_test.rb
+++ b/actionpack/test/controller/send_file_test.rb
@@ -154,6 +154,17 @@ class SendFileTest < ActionController::TestCase
end
end
+ def test_send_file_with_default_content_disposition_header
+ process('data')
+ assert_equal 'attachment', @controller.headers['Content-Disposition']
+ end
+
+ def test_send_file_without_content_disposition_header
+ @controller.options = {:disposition => nil}
+ process('data')
+ assert_nil @controller.headers['Content-Disposition']
+ end
+
%w(file data).each do |method|
define_method "test_send_#{method}_status" do
@controller.options = { :stream => false, :status => 500 }
diff --git a/actionpack/test/controller/test_case_test.rb b/actionpack/test/controller/test_case_test.rb
index ecba9fed22..0d6d303b51 100644
--- a/actionpack/test/controller/test_case_test.rb
+++ b/actionpack/test/controller/test_case_test.rb
@@ -45,6 +45,10 @@ class TestCaseTest < ActionController::TestCase
render :text => request.fullpath
end
+ def test_format
+ render :text => request.format
+ end
+
def test_query_string
render :text => request.query_string
end
@@ -138,7 +142,7 @@ XML
@request.env['PATH_INFO'] = nil
@routes = ActionDispatch::Routing::RouteSet.new.tap do |r|
r.draw do
- match ':controller(/:action(/:id))'
+ get ':controller(/:action(/:id))'
end
end
end
@@ -224,6 +228,26 @@ XML
assert_equal 'value2', session[:symbol]
end
+ def test_process_merges_session_arg
+ session[:foo] = 'bar'
+ get :no_op, nil, { :bar => 'baz' }
+ assert_equal 'bar', session[:foo]
+ assert_equal 'baz', session[:bar]
+ end
+
+ def test_merged_session_arg_is_retained_across_requests
+ get :no_op, nil, { :foo => 'bar' }
+ assert_equal 'bar', session[:foo]
+ get :no_op
+ assert_equal 'bar', session[:foo]
+ end
+
+ def test_process_overwrites_existing_session_arg
+ session[:foo] = 'bar'
+ get :no_op, nil, { :foo => 'baz' }
+ assert_equal 'baz', session[:foo]
+ end
+
def test_session_is_cleared_from_controller_after_reset_session
process :set_session
process :reset_the_session
@@ -524,7 +548,7 @@ XML
with_routing do |set|
set.draw do
namespace :admin do
- match 'user' => 'user#index'
+ get 'user' => 'user#index'
end
end
@@ -534,7 +558,7 @@ XML
def test_assert_routing_with_glob
with_routing do |set|
- set.draw { match('*path' => "pages#show") }
+ set.draw { get('*path' => "pages#show") }
assert_routing('/company/about', { :controller => 'pages', :action => 'show', :path => 'company/about' })
end
end
@@ -559,14 +583,34 @@ XML
)
end
+ def test_params_passing_with_fixnums_when_not_html_request
+ get :test_params, :format => 'json', :count => 999
+ parsed_params = eval(@response.body)
+ assert_equal(
+ {'controller' => 'test_case_test/test', 'action' => 'test_params',
+ 'format' => 'json', 'count' => 999 },
+ parsed_params
+ )
+ end
+
+ def test_params_passing_path_parameter_is_string_when_not_html_request
+ get :test_params, :format => 'json', :id => 1
+ parsed_params = eval(@response.body)
+ assert_equal(
+ {'controller' => 'test_case_test/test', 'action' => 'test_params',
+ 'format' => 'json', 'id' => '1' },
+ parsed_params
+ )
+ end
+
def test_params_passing_with_frozen_values
assert_nothing_raised do
- get :test_params, :frozen => 'icy'.freeze, :frozens => ['icy'.freeze].freeze
+ get :test_params, :frozen => 'icy'.freeze, :frozens => ['icy'.freeze].freeze, :deepfreeze => { :frozen => 'icy'.freeze }.freeze
end
parsed_params = eval(@response.body)
assert_equal(
{'controller' => 'test_case_test/test', 'action' => 'test_params',
- 'frozen' => 'icy', 'frozens' => ['icy']},
+ 'frozen' => 'icy', 'frozens' => ['icy'], 'deepfreeze' => { 'frozen' => 'icy' }},
parsed_params
)
end
@@ -585,8 +629,8 @@ XML
def test_array_path_parameter_handled_properly
with_routing do |set|
set.draw do
- match 'file/*path', :to => 'test_case_test/test#test_params'
- match ':controller/:action'
+ get 'file/*path', :to => 'test_case_test/test#test_params'
+ get ':controller/:action'
end
get :test_params, :path => ['hello', 'world']
@@ -667,6 +711,20 @@ XML
assert_equal "http://", @response.body
end
+ def test_request_format
+ get :test_format, :format => 'html'
+ assert_equal 'text/html', @response.body
+
+ get :test_format, :format => 'json'
+ assert_equal 'application/json', @response.body
+
+ get :test_format, :format => 'xml'
+ assert_equal 'application/xml', @response.body
+
+ get :test_format
+ assert_equal 'text/html', @response.body
+ end
+
def test_should_have_knowledge_of_client_side_cookie_state_even_if_they_are_not_set
cookies['foo'] = 'bar'
get :no_op
@@ -828,3 +886,24 @@ class NamedRoutesControllerTest < ActionController::TestCase
end
end
end
+
+class AnonymousControllerTest < ActionController::TestCase
+ def setup
+ @controller = Class.new(ActionController::Base) do
+ def index
+ render :text => params[:controller]
+ end
+ end.new
+
+ @routes = ActionDispatch::Routing::RouteSet.new.tap do |r|
+ r.draw do
+ get ':controller(/:action(/:id))'
+ end
+ end
+ end
+
+ def test_controller_name
+ get :index
+ assert_equal 'anonymous', @response.body
+ end
+end \ No newline at end of file
diff --git a/actionpack/test/controller/url_for_integration_test.rb b/actionpack/test/controller/url_for_integration_test.rb
index 451ea6027d..6c2311e7a5 100644
--- a/actionpack/test/controller/url_for_integration_test.rb
+++ b/actionpack/test/controller/url_for_integration_test.rb
@@ -18,7 +18,7 @@ module ActionPack
root :to => 'users#index'
end
- match '/blog(/:year(/:month(/:day)))' => 'posts#show_date',
+ get '/blog(/:year(/:month(/:day)))' => 'posts#show_date',
:constraints => {
:year => /(19|20)\d\d/,
:month => /[01]?\d/,
@@ -27,7 +27,7 @@ module ActionPack
:day => nil,
:month => nil
- match 'archive/:year', :controller => 'archive', :action => 'index',
+ get 'archive/:year', :controller => 'archive', :action => 'index',
:defaults => { :year => nil },
:constraints => { :year => /\d{4}/ },
:as => "blog"
@@ -35,29 +35,29 @@ module ActionPack
resources :people
#match 'legacy/people' => "people#index", :legacy => "true"
- match 'symbols', :controller => :symbols, :action => :show, :name => :as_symbol
- match 'id_default(/:id)' => "foo#id_default", :id => 1
+ get 'symbols', :controller => :symbols, :action => :show, :name => :as_symbol
+ get 'id_default(/:id)' => "foo#id_default", :id => 1
match 'get_or_post' => "foo#get_or_post", :via => [:get, :post]
- match 'optional/:optional' => "posts#index"
- match 'projects/:project_id' => "project#index", :as => "project"
- match 'clients' => "projects#index"
+ get 'optional/:optional' => "posts#index"
+ get 'projects/:project_id' => "project#index", :as => "project"
+ get 'clients' => "projects#index"
- match 'ignorecase/geocode/:postalcode' => 'geocode#show', :postalcode => /hx\d\d-\d[a-z]{2}/i
- match 'extended/geocode/:postalcode' => 'geocode#show',:constraints => {
+ get 'ignorecase/geocode/:postalcode' => 'geocode#show', :postalcode => /hx\d\d-\d[a-z]{2}/i
+ get 'extended/geocode/:postalcode' => 'geocode#show',:constraints => {
:postalcode => /# Postcode format
\d{5} #Prefix
(-\d{4})? #Suffix
/x
}, :as => "geocode"
- match 'news(.:format)' => "news#index"
+ get 'news(.:format)' => "news#index"
- match 'comment/:id(/:action)' => "comments#show"
- match 'ws/:controller(/:action(/:id))', :ws => true
- match 'account(/:action)' => "account#subscription"
- match 'pages/:page_id/:controller(/:action(/:id))'
- match ':controller/ping', :action => 'ping'
- match ':controller(/:action(/:id))(.:format)'
+ get 'comment/:id(/:action)' => "comments#show"
+ get 'ws/:controller(/:action(/:id))', :ws => true
+ get 'account(/:action)' => "account#subscription"
+ get 'pages/:page_id/:controller(/:action(/:id))'
+ get ':controller/ping', :action => 'ping'
+ get ':controller(/:action(/:id))(.:format)'
root :to => "news#index"
}
diff --git a/actionpack/test/controller/url_for_test.rb b/actionpack/test/controller/url_for_test.rb
index aa233d6135..b2cb5f80d5 100644
--- a/actionpack/test/controller/url_for_test.rb
+++ b/actionpack/test/controller/url_for_test.rb
@@ -5,7 +5,7 @@ module AbstractController
class UrlForTests < ActionController::TestCase
class W
- include ActionDispatch::Routing::RouteSet.new.tap { |r| r.draw { match ':controller(/:action(/:id(.:format)))' } }.url_helpers
+ include ActionDispatch::Routing::RouteSet.new.tap { |r| r.draw { get ':controller(/:action(/:id(.:format)))' } }.url_helpers
end
def teardown
@@ -210,8 +210,8 @@ module AbstractController
def test_named_routes
with_routing do |set|
set.draw do
- match 'this/is/verbose', :to => 'home#index', :as => :no_args
- match 'home/sweet/home/:user', :to => 'home#index', :as => :home
+ get 'this/is/verbose', :to => 'home#index', :as => :no_args
+ get 'home/sweet/home/:user', :to => 'home#index', :as => :home
end
# We need to create a new class in order to install the new named route.
@@ -231,7 +231,7 @@ module AbstractController
def test_relative_url_root_is_respected_for_named_routes
with_routing do |set|
set.draw do
- match '/home/sweet/home/:user', :to => 'home#index', :as => :home
+ get '/home/sweet/home/:user', :to => 'home#index', :as => :home
end
kls = Class.new { include set.url_helpers }
@@ -245,8 +245,8 @@ module AbstractController
def test_only_path
with_routing do |set|
set.draw do
- match 'home/sweet/home/:user', :to => 'home#index', :as => :home
- match ':controller/:action/:id'
+ get 'home/sweet/home/:user', :to => 'home#index', :as => :home
+ get ':controller/:action/:id'
end
# We need to create a new class in order to install the new named route.
@@ -313,8 +313,8 @@ module AbstractController
def test_named_routes_with_nil_keys
with_routing do |set|
set.draw do
- match 'posts.:format', :to => 'posts#index', :as => :posts
- match '/', :to => 'posts#index', :as => :main
+ get 'posts.:format', :to => 'posts#index', :as => :posts
+ get '/', :to => 'posts#index', :as => :main
end
# We need to create a new class in order to install the new named route.
diff --git a/actionpack/test/controller/url_rewriter_test.rb b/actionpack/test/controller/url_rewriter_test.rb
index f88903b10e..cc3706aeee 100644
--- a/actionpack/test/controller/url_rewriter_test.rb
+++ b/actionpack/test/controller/url_rewriter_test.rb
@@ -21,7 +21,7 @@ class UrlRewriterTests < ActionController::TestCase
@rewriter = Rewriter.new(@request) #.new(@request, @params)
@routes = ActionDispatch::Routing::RouteSet.new.tap do |r|
r.draw do
- match ':controller(/:action(/:id))'
+ get ':controller(/:action(/:id))'
end
end
end
diff --git a/actionpack/test/controller/webservice_test.rb b/actionpack/test/controller/webservice_test.rb
index 351e61eeae..c0b9833603 100644
--- a/actionpack/test/controller/webservice_test.rb
+++ b/actionpack/test/controller/webservice_test.rb
@@ -254,7 +254,7 @@ class WebServiceTest < ActionDispatch::IntegrationTest
def with_test_route_set
with_routing do |set|
set.draw do
- match '/', :to => 'web_service_test/test#assign_parameters'
+ match '/', :to => 'web_service_test/test#assign_parameters', :via => :all
end
yield
end
diff --git a/actionpack/test/dispatch/cookies_test.rb b/actionpack/test/dispatch/cookies_test.rb
index 3e48d97e67..2467654a70 100644
--- a/actionpack/test/dispatch/cookies_test.rb
+++ b/actionpack/test/dispatch/cookies_test.rb
@@ -38,6 +38,8 @@ class CookiesTest < ActionController::TestCase
head :ok
end
+ alias delete_cookie logout
+
def delete_cookie_with_path
cookies.delete("user_name", :path => '/beaten')
head :ok
@@ -179,6 +181,18 @@ class CookiesTest < ActionController::TestCase
assert_equal({"user_name" => "david"}, @response.cookies)
end
+ def test_setting_the_same_value_to_cookie
+ request.cookies[:user_name] = 'david'
+ get :authenticate
+ assert response.cookies.empty?
+ end
+
+ def test_setting_the_same_value_to_permanent_cookie
+ request.cookies[:user_name] = 'Jamie'
+ get :set_permanent_cookie
+ assert response.cookies, 'user_name' => 'Jamie'
+ end
+
def test_setting_with_escapable_characters
get :set_with_with_escapable_characters
assert_cookie_header "that+%26+guy=foo+%26+bar+%3D%3E+baz; path=/"
@@ -235,23 +249,33 @@ class CookiesTest < ActionController::TestCase
end
def test_expiring_cookie
+ request.cookies[:user_name] = 'Joe'
get :logout
assert_cookie_header "user_name=; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT"
assert_equal({"user_name" => nil}, @response.cookies)
end
def test_delete_cookie_with_path
+ request.cookies[:user_name] = 'Joe'
get :delete_cookie_with_path
assert_cookie_header "user_name=; path=/beaten; expires=Thu, 01-Jan-1970 00:00:00 GMT"
end
+ def test_delete_unexisting_cookie
+ request.cookies.clear
+ get :delete_cookie
+ assert @response.cookies.empty?
+ end
+
def test_deleted_cookie_predicate
+ cookies[:user_name] = 'Joe'
cookies.delete("user_name")
assert cookies.deleted?("user_name")
assert_equal false, cookies.deleted?("another")
end
def test_deleted_cookie_predicate_with_mismatching_options
+ cookies[:user_name] = 'Joe'
cookies.delete("user_name", :path => "/path")
assert_equal false, cookies.deleted?("user_name", :path => "/different")
end
@@ -284,6 +308,7 @@ class CookiesTest < ActionController::TestCase
end
def test_delete_and_set_cookie
+ request.cookies[:user_name] = 'Joe'
get :delete_and_set_cookie
assert_cookie_header "user_name=david; path=/; expires=Mon, 10-Oct-2005 05:00:00 GMT"
assert_equal({"user_name" => "david"}, @response.cookies)
@@ -387,6 +412,7 @@ class CookiesTest < ActionController::TestCase
end
def test_deleting_cookie_with_all_domain_option
+ request.cookies[:user_name] = 'Joe'
get :delete_cookie_with_domain
assert_response :success
assert_cookie_header "user_name=; domain=.nextangle.com; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT"
@@ -413,6 +439,7 @@ class CookiesTest < ActionController::TestCase
end
def test_deleting_cookie_with_all_domain_option_and_tld_length
+ request.cookies[:user_name] = 'Joe'
get :delete_cookie_with_domain_and_tld
assert_response :success
assert_cookie_header "user_name=; domain=.nextangle.com; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT"
@@ -441,6 +468,7 @@ class CookiesTest < ActionController::TestCase
def test_deletings_cookie_with_several_preset_domains_using_one_of_these_domains
@request.host = "example2.com"
+ request.cookies[:user_name] = 'Joe'
get :delete_cookie_with_domains
assert_response :success
assert_cookie_header "user_name=; domain=example2.com; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT"
@@ -448,19 +476,19 @@ class CookiesTest < ActionController::TestCase
def test_deletings_cookie_with_several_preset_domains_using_other_domain
@request.host = "other-domain.com"
+ request.cookies[:user_name] = 'Joe'
get :delete_cookie_with_domains
assert_response :success
assert_cookie_header "user_name=; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT"
end
-
def test_cookies_hash_is_indifferent_access
- get :symbol_key
- assert_equal "david", cookies[:user_name]
- assert_equal "david", cookies['user_name']
- get :string_key
- assert_equal "dhh", cookies[:user_name]
- assert_equal "dhh", cookies['user_name']
+ get :symbol_key
+ assert_equal "david", cookies[:user_name]
+ assert_equal "david", cookies['user_name']
+ get :string_key
+ assert_equal "dhh", cookies[:user_name]
+ assert_equal "dhh", cookies['user_name']
end
@@ -575,4 +603,4 @@ class CookiesTest < ActionController::TestCase
assert_not_equal expected.split("\n"), header
end
end
-end \ No newline at end of file
+end
diff --git a/actionpack/test/dispatch/header_test.rb b/actionpack/test/dispatch/header_test.rb
index ec6ba494dc..bc7cad8db5 100644
--- a/actionpack/test/dispatch/header_test.rb
+++ b/actionpack/test/dispatch/header_test.rb
@@ -13,4 +13,9 @@ class HeaderTest < ActiveSupport::TestCase
assert_equal "text/plain", @headers["CONTENT_TYPE"]
assert_equal "text/plain", @headers["HTTP_CONTENT_TYPE"]
end
+
+ test "fetch" do
+ assert_equal "text/plain", @headers.fetch("content-type", nil)
+ assert_equal "not found", @headers.fetch('not-found', 'not found')
+ end
end
diff --git a/actionpack/test/dispatch/mapper_test.rb b/actionpack/test/dispatch/mapper_test.rb
index d3465589c1..bd078d2b21 100644
--- a/actionpack/test/dispatch/mapper_test.rb
+++ b/actionpack/test/dispatch/mapper_test.rb
@@ -4,11 +4,12 @@ module ActionDispatch
module Routing
class MapperTest < ActiveSupport::TestCase
class FakeSet
- attr_reader :routes
+ attr_reader :routes, :draw_paths
alias :set :routes
def initialize
@routes = []
+ @draw_paths = []
end
def resources_path_names
@@ -37,7 +38,7 @@ module ActionDispatch
end
def test_mapping_requirements
- options = { :controller => 'foo', :action => 'bar' }
+ options = { :controller => 'foo', :action => 'bar', :via => :get }
m = Mapper::Mapping.new FakeSet.new, {}, '/store/:name(*rest)', options
_, _, requirements, _ = m.to_route
assert_equal(/.+?/, requirements[:rest])
@@ -46,7 +47,7 @@ module ActionDispatch
def test_map_slash
fakeset = FakeSet.new
mapper = Mapper.new fakeset
- mapper.match '/', :to => 'posts#index', :as => :main
+ mapper.get '/', :to => 'posts#index', :as => :main
assert_equal '/', fakeset.conditions.first[:path_info]
end
@@ -55,14 +56,14 @@ module ActionDispatch
mapper = Mapper.new fakeset
# FIXME: is this a desired behavior?
- mapper.match '/one/two/', :to => 'posts#index', :as => :main
+ mapper.get '/one/two/', :to => 'posts#index', :as => :main
assert_equal '/one/two(.:format)', fakeset.conditions.first[:path_info]
end
def test_map_wildcard
fakeset = FakeSet.new
mapper = Mapper.new fakeset
- mapper.match '/*path', :to => 'pages#show'
+ mapper.get '/*path', :to => 'pages#show'
assert_equal '/*path(.:format)', fakeset.conditions.first[:path_info]
assert_equal(/.+?/, fakeset.requirements.first[:path])
end
@@ -70,7 +71,7 @@ module ActionDispatch
def test_map_wildcard_with_other_element
fakeset = FakeSet.new
mapper = Mapper.new fakeset
- mapper.match '/*path/foo/:bar', :to => 'pages#show'
+ mapper.get '/*path/foo/:bar', :to => 'pages#show'
assert_equal '/*path/foo/:bar(.:format)', fakeset.conditions.first[:path_info]
assert_nil fakeset.requirements.first[:path]
end
@@ -78,7 +79,7 @@ module ActionDispatch
def test_map_wildcard_with_multiple_wildcard
fakeset = FakeSet.new
mapper = Mapper.new fakeset
- mapper.match '/*foo/*bar', :to => 'pages#show'
+ mapper.get '/*foo/*bar', :to => 'pages#show'
assert_equal '/*foo/*bar(.:format)', fakeset.conditions.first[:path_info]
assert_nil fakeset.requirements.first[:foo]
assert_equal(/.+?/, fakeset.requirements.first[:bar])
@@ -87,7 +88,7 @@ module ActionDispatch
def test_map_wildcard_with_format_false
fakeset = FakeSet.new
mapper = Mapper.new fakeset
- mapper.match '/*path', :to => 'pages#show', :format => false
+ mapper.get '/*path', :to => 'pages#show', :format => false
assert_equal '/*path', fakeset.conditions.first[:path_info]
assert_nil fakeset.requirements.first[:path]
end
@@ -95,7 +96,7 @@ module ActionDispatch
def test_map_wildcard_with_format_true
fakeset = FakeSet.new
mapper = Mapper.new fakeset
- mapper.match '/*path', :to => 'pages#show', :format => true
+ mapper.get '/*path', :to => 'pages#show', :format => true
assert_equal '/*path.:format', fakeset.conditions.first[:path_info]
end
end
diff --git a/actionpack/test/dispatch/prefix_generation_test.rb b/actionpack/test/dispatch/prefix_generation_test.rb
index bd5b5edab0..ab2f7612ce 100644
--- a/actionpack/test/dispatch/prefix_generation_test.rb
+++ b/actionpack/test/dispatch/prefix_generation_test.rb
@@ -25,12 +25,12 @@ module TestGenerationPrefix
@routes ||= begin
routes = ActionDispatch::Routing::RouteSet.new
routes.draw do
- match "/posts/:id", :to => "inside_engine_generating#show", :as => :post
- match "/posts", :to => "inside_engine_generating#index", :as => :posts
- match "/url_to_application", :to => "inside_engine_generating#url_to_application"
- match "/polymorphic_path_for_engine", :to => "inside_engine_generating#polymorphic_path_for_engine"
- match "/conflicting_url", :to => "inside_engine_generating#conflicting"
- match "/foo", :to => "never#invoked", :as => :named_helper_that_should_be_invoked_only_in_respond_to_test
+ get "/posts/:id", :to => "inside_engine_generating#show", :as => :post
+ get "/posts", :to => "inside_engine_generating#index", :as => :posts
+ get "/url_to_application", :to => "inside_engine_generating#url_to_application"
+ get "/polymorphic_path_for_engine", :to => "inside_engine_generating#polymorphic_path_for_engine"
+ get "/conflicting_url", :to => "inside_engine_generating#conflicting"
+ get "/foo", :to => "never#invoked", :as => :named_helper_that_should_be_invoked_only_in_respond_to_test
end
routes
@@ -51,12 +51,12 @@ module TestGenerationPrefix
scope "/:omg", :omg => "awesome" do
mount BlogEngine => "/blog", :as => "blog_engine"
end
- match "/posts/:id", :to => "outside_engine_generating#post", :as => :post
- match "/generate", :to => "outside_engine_generating#index"
- match "/polymorphic_path_for_app", :to => "outside_engine_generating#polymorphic_path_for_app"
- match "/polymorphic_path_for_engine", :to => "outside_engine_generating#polymorphic_path_for_engine"
- match "/polymorphic_with_url_for", :to => "outside_engine_generating#polymorphic_with_url_for"
- match "/conflicting_url", :to => "outside_engine_generating#conflicting"
+ get "/posts/:id", :to => "outside_engine_generating#post", :as => :post
+ get "/generate", :to => "outside_engine_generating#index"
+ get "/polymorphic_path_for_app", :to => "outside_engine_generating#polymorphic_path_for_app"
+ get "/polymorphic_path_for_engine", :to => "outside_engine_generating#polymorphic_path_for_engine"
+ get "/polymorphic_with_url_for", :to => "outside_engine_generating#polymorphic_with_url_for"
+ get "/conflicting_url", :to => "outside_engine_generating#conflicting"
root :to => "outside_engine_generating#index"
end
@@ -282,7 +282,7 @@ module TestGenerationPrefix
@routes ||= begin
routes = ActionDispatch::Routing::RouteSet.new
routes.draw do
- match "/posts/:id", :to => "posts#show", :as => :post
+ get "/posts/:id", :to => "posts#show", :as => :post
end
routes
diff --git a/actionpack/test/dispatch/request/json_params_parsing_test.rb b/actionpack/test/dispatch/request/json_params_parsing_test.rb
index ae425dd406..302bff0696 100644
--- a/actionpack/test/dispatch/request/json_params_parsing_test.rb
+++ b/actionpack/test/dispatch/request/json_params_parsing_test.rb
@@ -65,7 +65,7 @@ class JsonParamsParsingTest < ActionDispatch::IntegrationTest
def with_test_routing
with_routing do |set|
set.draw do
- match ':action', :to => ::JsonParamsParsingTest::TestController
+ post ':action', :to => ::JsonParamsParsingTest::TestController
end
yield
end
@@ -118,7 +118,7 @@ class RootLessJSONParamsParsingTest < ActionDispatch::IntegrationTest
def with_test_routing(controller)
with_routing do |set|
set.draw do
- match ':action', :to => controller
+ post ':action', :to => controller
end
yield
end
diff --git a/actionpack/test/dispatch/request/multipart_params_parsing_test.rb b/actionpack/test/dispatch/request/multipart_params_parsing_test.rb
index d144f013f5..63c5ea26a6 100644
--- a/actionpack/test/dispatch/request/multipart_params_parsing_test.rb
+++ b/actionpack/test/dispatch/request/multipart_params_parsing_test.rb
@@ -144,7 +144,7 @@ class MultipartParamsParsingTest < ActionDispatch::IntegrationTest
def with_test_routing
with_routing do |set|
set.draw do
- match ':action', :to => 'multipart_params_parsing_test/test'
+ post ':action', :to => 'multipart_params_parsing_test/test'
end
yield
end
diff --git a/actionpack/test/dispatch/request/query_string_parsing_test.rb b/actionpack/test/dispatch/request/query_string_parsing_test.rb
index f6a1475d04..d14f188e30 100644
--- a/actionpack/test/dispatch/request/query_string_parsing_test.rb
+++ b/actionpack/test/dispatch/request/query_string_parsing_test.rb
@@ -109,7 +109,7 @@ class QueryStringParsingTest < ActionDispatch::IntegrationTest
def assert_parses(expected, actual)
with_routing do |set|
set.draw do
- match ':action', :to => ::QueryStringParsingTest::TestController
+ get ':action', :to => ::QueryStringParsingTest::TestController
end
get "/parse", actual
diff --git a/actionpack/test/dispatch/request/url_encoded_params_parsing_test.rb b/actionpack/test/dispatch/request/url_encoded_params_parsing_test.rb
index 05569561d2..568e220b15 100644
--- a/actionpack/test/dispatch/request/url_encoded_params_parsing_test.rb
+++ b/actionpack/test/dispatch/request/url_encoded_params_parsing_test.rb
@@ -130,7 +130,7 @@ class UrlEncodedParamsParsingTest < ActionDispatch::IntegrationTest
def with_test_routing
with_routing do |set|
set.draw do
- match ':action', :to => ::UrlEncodedParamsParsingTest::TestController
+ post ':action', :to => ::UrlEncodedParamsParsingTest::TestController
end
yield
end
diff --git a/actionpack/test/dispatch/request/xml_params_parsing_test.rb b/actionpack/test/dispatch/request/xml_params_parsing_test.rb
index afd400c2a9..84823e2896 100644
--- a/actionpack/test/dispatch/request/xml_params_parsing_test.rb
+++ b/actionpack/test/dispatch/request/xml_params_parsing_test.rb
@@ -106,7 +106,7 @@ class XmlParamsParsingTest < ActionDispatch::IntegrationTest
def with_test_routing
with_routing do |set|
set.draw do
- match ':action', :to => ::XmlParamsParsingTest::TestController
+ post ':action', :to => ::XmlParamsParsingTest::TestController
end
yield
end
@@ -155,7 +155,7 @@ class RootLessXmlParamsParsingTest < ActionDispatch::IntegrationTest
def with_test_routing
with_routing do |set|
set.draw do
- match ':action', :to => ::RootLessXmlParamsParsingTest::TestController
+ post ':action', :to => ::RootLessXmlParamsParsingTest::TestController
end
yield
end
diff --git a/actionpack/test/dispatch/request_id_test.rb b/actionpack/test/dispatch/request_id_test.rb
index 4b98cd32f2..a8050b4fab 100644
--- a/actionpack/test/dispatch/request_id_test.rb
+++ b/actionpack/test/dispatch/request_id_test.rb
@@ -52,7 +52,7 @@ class RequestIdResponseTest < ActionDispatch::IntegrationTest
def with_test_route_set
with_routing do |set|
set.draw do
- match '/', :to => ::RequestIdResponseTest::TestController.action(:index)
+ get '/', :to => ::RequestIdResponseTest::TestController.action(:index)
end
@app = self.class.build_app(set) do |middleware|
@@ -62,4 +62,4 @@ class RequestIdResponseTest < ActionDispatch::IntegrationTest
yield
end
end
-end \ No newline at end of file
+end
diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb
index 6c8b22c47f..94d0e09842 100644
--- a/actionpack/test/dispatch/request_test.rb
+++ b/actionpack/test/dispatch/request_test.rb
@@ -35,37 +35,40 @@ class RequestTest < ActiveSupport::TestCase
assert_equal '1.2.3.4', request.remote_ip
request = stub_request 'REMOTE_ADDR' => '1.2.3.4',
- 'HTTP_X_FORWARDED_FOR' => '3.4.5.6'
+ 'HTTP_X_FORWARDED_FOR' => '3.4.5.6'
assert_equal '3.4.5.6', request.remote_ip
request = stub_request 'REMOTE_ADDR' => '127.0.0.1',
- 'HTTP_X_FORWARDED_FOR' => '3.4.5.6'
+ 'HTTP_X_FORWARDED_FOR' => '3.4.5.6'
assert_equal '3.4.5.6', request.remote_ip
request = stub_request 'HTTP_X_FORWARDED_FOR' => '3.4.5.6,unknown'
assert_equal '3.4.5.6', request.remote_ip
request = stub_request 'HTTP_X_FORWARDED_FOR' => '172.16.0.1,3.4.5.6'
- assert_equal '3.4.5.6', request.remote_ip
+ assert_equal nil, request.remote_ip
request = stub_request 'HTTP_X_FORWARDED_FOR' => '192.168.0.1,3.4.5.6'
- assert_equal '3.4.5.6', request.remote_ip
+ assert_equal nil, request.remote_ip
request = stub_request 'HTTP_X_FORWARDED_FOR' => '10.0.0.1,3.4.5.6'
- assert_equal '3.4.5.6', request.remote_ip
+ assert_equal nil, request.remote_ip
request = stub_request 'HTTP_X_FORWARDED_FOR' => '10.0.0.1, 10.0.0.1, 3.4.5.6'
- assert_equal '3.4.5.6', request.remote_ip
+ assert_equal nil, request.remote_ip
request = stub_request 'HTTP_X_FORWARDED_FOR' => '127.0.0.1,3.4.5.6'
- assert_equal '3.4.5.6', request.remote_ip
+ assert_equal nil, request.remote_ip
request = stub_request 'HTTP_X_FORWARDED_FOR' => 'unknown,192.168.0.1'
- assert_equal 'unknown', request.remote_ip
+ assert_equal nil, request.remote_ip
request = stub_request 'HTTP_X_FORWARDED_FOR' => '3.4.5.6, 9.9.9.9, 10.0.0.1, 172.31.4.4'
assert_equal '3.4.5.6', request.remote_ip
+ request = stub_request 'HTTP_X_FORWARDED_FOR' => 'not_ip_address'
+ assert_equal nil, request.remote_ip
+
request = stub_request 'HTTP_X_FORWARDED_FOR' => '1.1.1.1',
'HTTP_CLIENT_IP' => '2.2.2.2'
e = assert_raise(ActionDispatch::RemoteIp::IpSpoofAttackError) {
@@ -89,6 +92,68 @@ class RequestTest < ActiveSupport::TestCase
assert_equal '9.9.9.9', request.remote_ip
end
+ test "remote ip v6" do
+ request = stub_request 'REMOTE_ADDR' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334'
+ assert_equal '2001:0db8:85a3:0000:0000:8a2e:0370:7334', request.remote_ip
+
+ request = stub_request 'REMOTE_ADDR' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334,fe80:0000:0000:0000:0202:b3ff:fe1e:8329'
+ assert_equal '2001:0db8:85a3:0000:0000:8a2e:0370:7334', request.remote_ip
+
+ request = stub_request 'REMOTE_ADDR' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334',
+ 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329'
+ assert_equal 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329', request.remote_ip
+
+ request = stub_request 'REMOTE_ADDR' => '::1',
+ 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329'
+ assert_equal 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329', request.remote_ip
+
+ request = stub_request 'HTTP_X_FORWARDED_FOR' => 'unknown,fe80:0000:0000:0000:0202:b3ff:fe1e:8329'
+ assert_equal nil, request.remote_ip
+
+ request = stub_request 'HTTP_X_FORWARDED_FOR' => '::1,fe80:0000:0000:0000:0202:b3ff:fe1e:8329'
+ assert_equal nil, request.remote_ip
+
+ request = stub_request 'HTTP_X_FORWARDED_FOR' => '::1,fe80:0000:0000:0000:0202:b3ff:fe1e:8329'
+ assert_equal nil, request.remote_ip
+
+ request = stub_request 'HTTP_X_FORWARDED_FOR' => '::1,fe80:0000:0000:0000:0202:b3ff:fe1e:8329'
+ assert_equal nil, request.remote_ip
+
+ request = stub_request 'HTTP_X_FORWARDED_FOR' => '::1, ::1, fe80:0000:0000:0000:0202:b3ff:fe1e:8329'
+ assert_equal nil, request.remote_ip
+
+ request = stub_request 'HTTP_X_FORWARDED_FOR' => 'unknown,::1'
+ assert_equal nil, request.remote_ip
+
+ request = stub_request 'HTTP_X_FORWARDED_FOR' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334, fe80:0000:0000:0000:0202:b3ff:fe1e:8329, ::1, fc00::'
+ assert_equal '2001:0db8:85a3:0000:0000:8a2e:0370:7334', request.remote_ip
+
+ request = stub_request 'HTTP_X_FORWARDED_FOR' => 'not_ip_address'
+ assert_equal nil, request.remote_ip
+
+ request = stub_request 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329',
+ 'HTTP_CLIENT_IP' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334'
+ e = assert_raise(ActionDispatch::RemoteIp::IpSpoofAttackError) {
+ request.remote_ip
+ }
+ assert_match(/IP spoofing attack/, e.message)
+ assert_match(/HTTP_X_FORWARDED_FOR="fe80:0000:0000:0000:0202:b3ff:fe1e:8329"/, e.message)
+ assert_match(/HTTP_CLIENT_IP="2001:0db8:85a3:0000:0000:8a2e:0370:7334"/, e.message)
+
+ # Turn IP Spoofing detection off.
+ # This is useful for sites that are aimed at non-IP clients. The typical
+ # example is WAP. Since the cellular network is not IP based, it's a
+ # leap of faith to assume that their proxies are ever going to set the
+ # HTTP_CLIENT_IP/HTTP_X_FORWARDED_FOR headers properly.
+ request = stub_request 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329',
+ 'HTTP_CLIENT_IP' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334',
+ :ip_spoofing_check => false
+ assert_equal '2001:0db8:85a3:0000:0000:8a2e:0370:7334', request.remote_ip
+
+ request = stub_request 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329, 2001:0db8:85a3:0000:0000:8a2e:0370:7334'
+ assert_equal 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329', request.remote_ip
+ end
+
test "remote ip when the remote ip middleware returns nil" do
request = stub_request 'REMOTE_ADDR' => '127.0.0.1'
assert_equal '127.0.0.1', request.remote_ip
@@ -97,29 +162,47 @@ class RequestTest < ActiveSupport::TestCase
test "remote ip with user specified trusted proxies String" do
@trusted_proxies = "67.205.106.73"
- request = stub_request 'REMOTE_ADDR' => '67.205.106.73',
- 'HTTP_X_FORWARDED_FOR' => '3.4.5.6'
+ request = stub_request 'REMOTE_ADDR' => '3.4.5.6',
+ 'HTTP_X_FORWARDED_FOR' => '67.205.106.73'
assert_equal '3.4.5.6', request.remote_ip
request = stub_request 'REMOTE_ADDR' => '172.16.0.1,67.205.106.73',
- 'HTTP_X_FORWARDED_FOR' => '3.4.5.6'
- assert_equal '3.4.5.6', request.remote_ip
+ 'HTTP_X_FORWARDED_FOR' => '67.205.106.73'
+ assert_equal '172.16.0.1', request.remote_ip
- request = stub_request 'REMOTE_ADDR' => '67.205.106.73,172.16.0.1',
- 'HTTP_X_FORWARDED_FOR' => '3.4.5.6'
- assert_equal '3.4.5.6', request.remote_ip
-
- request = stub_request 'REMOTE_ADDR' => '67.205.106.74,172.16.0.1',
- 'HTTP_X_FORWARDED_FOR' => '3.4.5.6'
+ request = stub_request 'REMOTE_ADDR' => '67.205.106.73,3.4.5.6',
+ 'HTTP_X_FORWARDED_FOR' => '67.205.106.73'
assert_equal '3.4.5.6', request.remote_ip
request = stub_request 'HTTP_X_FORWARDED_FOR' => 'unknown,67.205.106.73'
- assert_equal 'unknown', request.remote_ip
+ assert_equal nil, request.remote_ip
request = stub_request 'HTTP_X_FORWARDED_FOR' => '3.4.5.6, 9.9.9.9, 10.0.0.1, 67.205.106.73'
assert_equal '3.4.5.6', request.remote_ip
end
+ test "remote ip v6 with user specified trusted proxies String" do
+ @trusted_proxies = 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329'
+
+ request = stub_request 'REMOTE_ADDR' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334',
+ 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329'
+ assert_equal '2001:0db8:85a3:0000:0000:8a2e:0370:7334', request.remote_ip
+
+ request = stub_request 'REMOTE_ADDR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329,2001:0db8:85a3:0000:0000:8a2e:0370:7334',
+ 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329'
+ assert_equal '2001:0db8:85a3:0000:0000:8a2e:0370:7334', request.remote_ip
+
+ request = stub_request 'REMOTE_ADDR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329,::1',
+ 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329'
+ assert_equal 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329', request.remote_ip
+
+ request = stub_request 'HTTP_X_FORWARDED_FOR' => 'unknown,fe80:0000:0000:0000:0202:b3ff:fe1e:8329'
+ assert_equal nil, request.remote_ip
+
+ request = stub_request 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329,2001:0db8:85a3:0000:0000:8a2e:0370:7334'
+ assert_equal nil, request.remote_ip
+ end
+
test "remote ip with user specified trusted proxies Regexp" do
@trusted_proxies = /^67\.205\.106\.73$/i
@@ -128,7 +211,18 @@ class RequestTest < ActiveSupport::TestCase
assert_equal '3.4.5.6', request.remote_ip
request = stub_request 'HTTP_X_FORWARDED_FOR' => '67.205.106.73, 10.0.0.1, 9.9.9.9, 3.4.5.6'
- assert_equal '10.0.0.1', request.remote_ip
+ assert_equal nil, request.remote_ip
+ end
+
+ test "remote ip v6 with user specified trusted proxies Regexp" do
+ @trusted_proxies = /^fe80:0000:0000:0000:0202:b3ff:fe1e:8329$/i
+
+ request = stub_request 'REMOTE_ADDR' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334',
+ 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329'
+ assert_equal '2001:0db8:85a3:0000:0000:8a2e:0370:7334', request.remote_ip
+
+ request = stub_request 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329, 2001:0db8:85a3:0000:0000:8a2e:0370:7334'
+ assert_equal nil, request.remote_ip
end
test "domains" do
diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb
index cc4279d9dd..a96d2edcf9 100644
--- a/actionpack/test/dispatch/routing_test.rb
+++ b/actionpack/test/dispatch/routing_test.rb
@@ -58,41 +58,46 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
get "remove", :action => :destroy, :as => :remove
end
- match 'account/logout' => redirect("/logout"), :as => :logout_redirect
- match 'account/login', :to => redirect("/login")
- match 'secure', :to => redirect("/secure/login")
+ get 'account/logout' => redirect("/logout"), :as => :logout_redirect
+ get 'account/login', :to => redirect("/login")
+ get 'secure', :to => redirect("/secure/login")
- match 'mobile', :to => redirect(:subdomain => 'mobile')
- match 'super_new_documentation', :to => redirect(:host => 'super-docs.com')
+ get 'mobile', :to => redirect(:subdomain => 'mobile')
+ get 'documentation', :to => redirect(:domain => 'example-documentation.com', :path => '')
+ get 'new_documentation', :to => redirect(:path => '/documentation/new')
+ get 'super_new_documentation', :to => redirect(:host => 'super-docs.com')
- match 'youtube_favorites/:youtube_id/:name', :to => redirect(YoutubeFavoritesRedirector)
+ get 'stores/:name', :to => redirect(:subdomain => 'stores', :path => '/%{name}')
+ get 'stores/:name(*rest)', :to => redirect(:subdomain => 'stores', :path => '/%{name}%{rest}')
+
+ get 'youtube_favorites/:youtube_id/:name', :to => redirect(YoutubeFavoritesRedirector)
constraints(lambda { |req| true }) do
- match 'account/overview'
+ get 'account/overview'
end
- match '/account/nested/overview'
- match 'sign_in' => "sessions#new"
+ get '/account/nested/overview'
+ get 'sign_in' => "sessions#new"
- match 'account/modulo/:name', :to => redirect("/%{name}s")
- match 'account/proc/:name', :to => redirect {|params, req| "/#{params[:name].pluralize}" }
- match 'account/proc_req' => redirect {|params, req| "/#{req.method}" }
+ get 'account/modulo/:name', :to => redirect("/%{name}s")
+ get 'account/proc/:name', :to => redirect {|params, req| "/#{params[:name].pluralize}" }
+ get 'account/proc_req' => redirect {|params, req| "/#{req.method}" }
- match 'account/google' => redirect('http://www.google.com/', :status => 302)
+ get 'account/google' => redirect('http://www.google.com/', :status => 302)
match 'openid/login', :via => [:get, :post], :to => "openid#login"
controller(:global) do
get 'global/hide_notice'
- match 'global/export', :to => :export, :as => :export_request
- match '/export/:id/:file', :to => :export, :as => :export_download, :constraints => { :file => /.*/ }
- match 'global/:action'
+ get 'global/export', :to => :export, :as => :export_request
+ get '/export/:id/:file', :to => :export, :as => :export_download, :constraints => { :file => /.*/ }
+ get 'global/:action'
end
- match "/local/:action", :controller => "local"
+ get "/local/:action", :controller => "local"
- match "/projects/status(.:format)"
- match "/404", :to => lambda { |env| [404, {"Content-Type" => "text/plain"}, ["NOT FOUND"]] }
+ get "/projects/status(.:format)"
+ get "/404", :to => lambda { |env| [404, {"Content-Type" => "text/plain"}, ["NOT FOUND"]] }
constraints(:ip => /192\.168\.1\.\d\d\d/) do
get 'admin' => "queenbee#index"
@@ -277,25 +282,25 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
end
- match 'sprockets.js' => ::TestRoutingMapper::SprocketsApp
+ get 'sprockets.js' => ::TestRoutingMapper::SprocketsApp
- match 'people/:id/update', :to => 'people#update', :as => :update_person
- match '/projects/:project_id/people/:id/update', :to => 'people#update', :as => :update_project_person
+ get 'people/:id/update', :to => 'people#update', :as => :update_person
+ get '/projects/:project_id/people/:id/update', :to => 'people#update', :as => :update_project_person
# misc
- match 'articles/:year/:month/:day/:title', :to => "articles#show", :as => :article
+ get 'articles/:year/:month/:day/:title', :to => "articles#show", :as => :article
# default params
- match 'inline_pages/(:id)', :to => 'pages#show', :id => 'home'
- match 'default_pages/(:id)', :to => 'pages#show', :defaults => { :id => 'home' }
+ get 'inline_pages/(:id)', :to => 'pages#show', :id => 'home'
+ get 'default_pages/(:id)', :to => 'pages#show', :defaults => { :id => 'home' }
defaults :id => 'home' do
- match 'scoped_pages/(:id)', :to => 'pages#show'
+ get 'scoped_pages/(:id)', :to => 'pages#show'
end
namespace :account do
- match 'shorthand'
- match 'description', :to => :description, :as => "description"
- match ':action/callback', :action => /twitter|github/, :to => "callbacks", :as => :callback
+ get 'shorthand'
+ get 'description', :to => :description, :as => "description"
+ get ':action/callback', :action => /twitter|github/, :to => "callbacks", :as => :callback
resource :subscription, :credit, :credit_card
root :to => "account#index"
@@ -318,7 +323,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
controller :articles do
scope '/articles', :as => 'article' do
scope :path => '/:title', :title => /[a-z]+/, :as => :with_title do
- match '/:id', :to => :with_id, :as => ""
+ get '/:id', :to => :with_id, :as => ""
end
end
end
@@ -327,7 +332,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
resources :rooms
end
- match '/info' => 'projects#info', :as => 'info'
+ get '/info' => 'projects#info', :as => 'info'
namespace :admin do
scope '(:locale)', :locale => /en|pl/ do
@@ -361,7 +366,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
scope :path => 'api' do
resource :me
- match '/' => 'mes#index'
+ get '/' => 'mes#index'
end
get "(/:username)/followers" => "followers#index"
@@ -374,7 +379,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
end
- match "whatever/:controller(/:action(/:id))", :id => /\d+/
+ get "whatever/:controller(/:action(/:id))", :id => /\d+/
resource :profile do
get :settings
@@ -407,7 +412,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
namespace :private do
root :to => redirect('/private/index')
- match "index", :to => 'private#index'
+ get "index", :to => 'private#index'
end
scope :only => [:index, :show] do
@@ -489,7 +494,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
get "/forced_collision", :as => :forced_collision, :to => "forced_collision#show"
end
- match '/purchases/:token/:filename',
+ get '/purchases/:token/:filename',
:to => 'purchases#fetch',
:token => /[[:alnum:]]{10}/,
:filename => /(.+)/,
@@ -500,18 +505,18 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
scope '/countries/:country', :constraints => lambda { |params, req| params[:country].in?(["all", "France"]) } do
- match '/', :to => 'countries#index'
- match '/cities', :to => 'countries#cities'
+ get '/', :to => 'countries#index'
+ get '/cities', :to => 'countries#cities'
end
- match '/countries/:country/(*other)', :to => redirect{ |params, req| params[:other] ? "/countries/all/#{params[:other]}" : '/countries/all' }
+ get '/countries/:country/(*other)', :to => redirect{ |params, req| params[:other] ? "/countries/all/#{params[:other]}" : '/countries/all' }
- match '/:locale/*file.:format', :to => 'files#show', :file => /path\/to\/existing\/file/
+ get '/:locale/*file.:format', :to => 'files#show', :file => /path\/to\/existing\/file/
scope '/italians' do
- match '/writers', :to => 'italians#writers', :constraints => ::TestRoutingMapper::IpRestrictor
- match '/sculptors', :to => 'italians#sculptors'
- match '/painters/:painter', :to => 'italians#painters', :constraints => {:painter => /michelangelo/}
+ get '/writers', :to => 'italians#writers', :constraints => ::TestRoutingMapper::IpRestrictor
+ get '/sculptors', :to => 'italians#sculptors'
+ get '/painters/:painter', :to => 'italians#painters', :constraints => {:painter => /michelangelo/}
end
end
end
@@ -627,7 +632,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
self.class.stub_controllers do |routes|
routes.draw do
namespace :admin do
- match '/:controller(/:action(/:id(.:format)))'
+ get '/:controller(/:action(/:id(.:format)))'
end
end
end
@@ -693,11 +698,31 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
verify_redirect 'http://mobile.example.com/mobile'
end
+ def test_redirect_hash_with_domain_and_path
+ get '/documentation'
+ verify_redirect 'http://www.example-documentation.com'
+ end
+
+ def test_redirect_hash_with_path
+ get '/new_documentation'
+ verify_redirect 'http://www.example.com/documentation/new'
+ end
+
def test_redirect_hash_with_host
get '/super_new_documentation?section=top'
verify_redirect 'http://super-docs.com/super_new_documentation?section=top'
end
+ def test_redirect_hash_path_substitution
+ get '/stores/iernest'
+ verify_redirect 'http://stores.example.com/iernest'
+ end
+
+ def test_redirect_hash_path_substitution_with_catch_all
+ get '/stores/iernest/products'
+ verify_redirect 'http://stores.example.com/iernest/products'
+ end
+
def test_redirect_class
get '/youtube_favorites/oHg5SJYRHA0/rick-rolld'
verify_redirect 'http://www.youtube.com/watch?v=oHg5SJYRHA0'
@@ -2231,12 +2256,12 @@ class TestAppendingRoutes < ActionDispatch::IntegrationTest
s = self
@app = ActionDispatch::Routing::RouteSet.new
@app.append do
- match '/hello' => s.simple_app('fail')
- match '/goodbye' => s.simple_app('goodbye')
+ get '/hello' => s.simple_app('fail')
+ get '/goodbye' => s.simple_app('goodbye')
end
@app.draw do
- match '/hello' => s.simple_app('hello')
+ get '/hello' => s.simple_app('hello')
end
end
@@ -2344,12 +2369,12 @@ end
class TestUriPathEscaping < ActionDispatch::IntegrationTest
Routes = ActionDispatch::Routing::RouteSet.new.tap do |app|
app.draw do
- match '/:segment' => lambda { |env|
+ get '/:segment' => lambda { |env|
path_params = env['action_dispatch.request.path_parameters']
[200, { 'Content-Type' => 'text/plain' }, [path_params[:segment]]]
}, :as => :segment
- match '/*splat' => lambda { |env|
+ get '/*splat' => lambda { |env|
path_params = env['action_dispatch.request.path_parameters']
[200, { 'Content-Type' => 'text/plain' }, [path_params[:splat]]]
}, :as => :splat
@@ -2381,7 +2406,7 @@ end
class TestUnicodePaths < ActionDispatch::IntegrationTest
Routes = ActionDispatch::Routing::RouteSet.new.tap do |app|
app.draw do
- match "/#{Rack::Utils.escape("ほげ")}" => lambda { |env|
+ get "/#{Rack::Utils.escape("ほげ")}" => lambda { |env|
[200, { 'Content-Type' => 'text/plain' }, []]
}, :as => :unicode_path
end
@@ -2411,10 +2436,10 @@ class TestMultipleNestedController < ActionDispatch::IntegrationTest
app.draw do
namespace :foo do
namespace :bar do
- match "baz" => "baz#index"
+ get "baz" => "baz#index"
end
end
- match "pooh" => "pooh#index"
+ get "pooh" => "pooh#index"
end
end
@@ -2433,8 +2458,8 @@ class TestTildeAndMinusPaths < ActionDispatch::IntegrationTest
app.draw do
ok = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, []] }
- match "/~user" => ok
- match "/young-and-fine" => ok
+ get "/~user" => ok
+ get "/young-and-fine" => ok
end
end
@@ -2452,3 +2477,57 @@ class TestTildeAndMinusPaths < ActionDispatch::IntegrationTest
end
end
+
+class TestRedirectInterpolation < ActionDispatch::IntegrationTest
+ Routes = ActionDispatch::Routing::RouteSet.new.tap do |app|
+ app.draw do
+ ok = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, []] }
+
+ get "/foo/:id" => redirect("/foo/bar/%{id}")
+ get "/bar/:id" => redirect(:path => "/foo/bar/%{id}")
+ get "/foo/bar/:id" => ok
+ end
+ end
+
+ def app; Routes end
+
+ test "redirect escapes interpolated parameters with redirect proc" do
+ get "/foo/1%3E"
+ verify_redirect "http://www.example.com/foo/bar/1%3E"
+ end
+
+ test "redirect escapes interpolated parameters with option proc" do
+ get "/bar/1%3E"
+ verify_redirect "http://www.example.com/foo/bar/1%3E"
+ end
+
+private
+ def verify_redirect(url, status=301)
+ assert_equal status, @response.status
+ assert_equal url, @response.headers['Location']
+ assert_equal expected_redirect_body(url), @response.body
+ end
+
+ def expected_redirect_body(url)
+ %(<html><body>You are being <a href="#{ERB::Util.h(url)}">redirected</a>.</body></html>)
+ end
+end
+
+class TestConstraintsAccessingParameters < ActionDispatch::IntegrationTest
+ Routes = ActionDispatch::Routing::RouteSet.new.tap do |app|
+ app.draw do
+ ok = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, []] }
+
+ get "/:foo" => ok, :constraints => lambda { |r| r.params[:foo] == 'foo' }
+ get "/:bar" => ok
+ end
+ end
+
+ def app; Routes end
+
+ test "parameters are reset between constraint checks" do
+ get "/bar"
+ assert_equal nil, @request.params[:foo]
+ assert_equal "bar", @request.params[:bar]
+ end
+end
diff --git a/actionpack/test/dispatch/session/cache_store_test.rb b/actionpack/test/dispatch/session/cache_store_test.rb
index 12405bf45d..a74e165826 100644
--- a/actionpack/test/dispatch/session/cache_store_test.rb
+++ b/actionpack/test/dispatch/session/cache_store_test.rb
@@ -164,7 +164,7 @@ class CacheStoreTest < ActionDispatch::IntegrationTest
def with_test_route_set
with_routing do |set|
set.draw do
- match ':action', :to => ::CacheStoreTest::TestController
+ get ':action', :to => ::CacheStoreTest::TestController
end
@app = self.class.build_app(set) do |middleware|
diff --git a/actionpack/test/dispatch/session/cookie_store_test.rb b/actionpack/test/dispatch/session/cookie_store_test.rb
index 19969394cd..631974d6c4 100644
--- a/actionpack/test/dispatch/session/cookie_store_test.rb
+++ b/actionpack/test/dispatch/session/cookie_store_test.rb
@@ -317,7 +317,7 @@ class CookieStoreTest < ActionDispatch::IntegrationTest
def with_test_route_set(options = {})
with_routing do |set|
set.draw do
- match ':action', :to => ::CookieStoreTest::TestController
+ get ':action', :to => ::CookieStoreTest::TestController
end
options = { :key => SessionKey }.merge!(options)
diff --git a/actionpack/test/dispatch/session/mem_cache_store_test.rb b/actionpack/test/dispatch/session/mem_cache_store_test.rb
index 5277c92b55..03234612ab 100644
--- a/actionpack/test/dispatch/session/mem_cache_store_test.rb
+++ b/actionpack/test/dispatch/session/mem_cache_store_test.rb
@@ -173,7 +173,7 @@ class MemCacheStoreTest < ActionDispatch::IntegrationTest
def with_test_route_set
with_routing do |set|
set.draw do
- match ':action', :to => ::MemCacheStoreTest::TestController
+ get ':action', :to => ::MemCacheStoreTest::TestController
end
@app = self.class.build_app(set) do |middleware|
diff --git a/actionpack/test/dispatch/url_generation_test.rb b/actionpack/test/dispatch/url_generation_test.rb
index 2b54bc62b0..985ff2e81a 100644
--- a/actionpack/test/dispatch/url_generation_test.rb
+++ b/actionpack/test/dispatch/url_generation_test.rb
@@ -3,7 +3,7 @@ require 'abstract_unit'
module TestUrlGeneration
class WithMountPoint < ActionDispatch::IntegrationTest
Routes = ActionDispatch::Routing::RouteSet.new
- Routes.draw { match "/foo", :to => "my_route_generating#index", :as => :foo }
+ Routes.draw { get "/foo", :to => "my_route_generating#index", :as => :foo }
class ::MyRouteGeneratingController < ActionController::Base
include Routes.url_helpers
diff --git a/actionpack/test/fixtures/test/_b_layout_for_partial_with_object.html.erb b/actionpack/test/fixtures/test/_b_layout_for_partial_with_object.html.erb
new file mode 100644
index 0000000000..bdd53014cd
--- /dev/null
+++ b/actionpack/test/fixtures/test/_b_layout_for_partial_with_object.html.erb
@@ -0,0 +1 @@
+<b class="<%= customer.name.downcase %>"><%= yield %></b> \ No newline at end of file
diff --git a/actionpack/test/fixtures/test/_b_layout_for_partial_with_object_counter.html.erb b/actionpack/test/fixtures/test/_b_layout_for_partial_with_object_counter.html.erb
new file mode 100644
index 0000000000..44d6121297
--- /dev/null
+++ b/actionpack/test/fixtures/test/_b_layout_for_partial_with_object_counter.html.erb
@@ -0,0 +1 @@
+<b data-counter="<%= customer_counter %>"><%= yield %></b> \ No newline at end of file
diff --git a/actionpack/test/fixtures/translations/templates/default.erb b/actionpack/test/fixtures/translations/templates/default.erb
new file mode 100644
index 0000000000..8b70031071
--- /dev/null
+++ b/actionpack/test/fixtures/translations/templates/default.erb
@@ -0,0 +1 @@
+<%= t('.missing', :default => :'.foo') %>
diff --git a/actionpack/test/template/date_helper_i18n_test.rb b/actionpack/test/template/date_helper_i18n_test.rb
index 82b62e64f3..63066d40cd 100644
--- a/actionpack/test/template/date_helper_i18n_test.rb
+++ b/actionpack/test/template/date_helper_i18n_test.rb
@@ -12,24 +12,24 @@ class DateHelperDistanceOfTimeInWordsI18nTests < ActiveSupport::TestCase
def test_distance_of_time_in_words_calls_i18n
{ # with include_seconds
- [2.seconds, true] => [:'less_than_x_seconds', 5],
- [9.seconds, true] => [:'less_than_x_seconds', 10],
- [19.seconds, true] => [:'less_than_x_seconds', 20],
- [30.seconds, true] => [:'half_a_minute', nil],
- [59.seconds, true] => [:'less_than_x_minutes', 1],
- [60.seconds, true] => [:'x_minutes', 1],
+ [2.seconds, { :include_seconds => true }] => [:'less_than_x_seconds', 5],
+ [9.seconds, { :include_seconds => true }] => [:'less_than_x_seconds', 10],
+ [19.seconds, { :include_seconds => true }] => [:'less_than_x_seconds', 20],
+ [30.seconds, { :include_seconds => true }] => [:'half_a_minute', nil],
+ [59.seconds, { :include_seconds => true }] => [:'less_than_x_minutes', 1],
+ [60.seconds, { :include_seconds => true }] => [:'x_minutes', 1],
# without include_seconds
- [29.seconds, false] => [:'less_than_x_minutes', 1],
- [60.seconds, false] => [:'x_minutes', 1],
- [44.minutes, false] => [:'x_minutes', 44],
- [61.minutes, false] => [:'about_x_hours', 1],
- [24.hours, false] => [:'x_days', 1],
- [30.days, false] => [:'about_x_months', 1],
- [60.days, false] => [:'x_months', 2],
- [1.year, false] => [:'about_x_years', 1],
- [3.years + 6.months, false] => [:'over_x_years', 3],
- [3.years + 10.months, false] => [:'almost_x_years', 4]
+ [29.seconds, { :include_seconds => false }] => [:'less_than_x_minutes', 1],
+ [60.seconds, { :include_seconds => false }] => [:'x_minutes', 1],
+ [44.minutes, { :include_seconds => false }] => [:'x_minutes', 44],
+ [61.minutes, { :include_seconds => false }] => [:'about_x_hours', 1],
+ [24.hours, { :include_seconds => false }] => [:'x_days', 1],
+ [30.days, { :include_seconds => false }] => [:'about_x_months', 1],
+ [60.days, { :include_seconds => false }] => [:'x_months', 2],
+ [1.year, { :include_seconds => false }] => [:'about_x_years', 1],
+ [3.years + 6.months, { :include_seconds => false }] => [:'over_x_years', 3],
+ [3.years + 10.months, { :include_seconds => false }] => [:'almost_x_years', 4]
}.each do |passed, expected|
assert_distance_of_time_in_words_translates_key passed, expected
@@ -37,7 +37,7 @@ class DateHelperDistanceOfTimeInWordsI18nTests < ActiveSupport::TestCase
end
def assert_distance_of_time_in_words_translates_key(passed, expected)
- diff, include_seconds = *passed
+ diff, passed_options = *passed
key, count = *expected
to = @from + diff
@@ -45,7 +45,12 @@ class DateHelperDistanceOfTimeInWordsI18nTests < ActiveSupport::TestCase
options[:count] = count if count
I18n.expects(:t).with(key, options)
- distance_of_time_in_words(@from, to, include_seconds, :locale => 'en')
+ distance_of_time_in_words(@from, to, passed_options.merge(:locale => 'en'))
+ end
+
+ def test_time_ago_in_words_passes_locale
+ I18n.expects(:t).with(:less_than_x_minutes, :scope => :'datetime.distance_in_words', :count => 1, :locale => 'ru')
+ time_ago_in_words(15.seconds.ago, :locale => 'ru')
end
def test_distance_of_time_pluralizations
diff --git a/actionpack/test/template/date_helper_test.rb b/actionpack/test/template/date_helper_test.rb
index c9b8a5bb70..ff85a675a2 100644
--- a/actionpack/test/template/date_helper_test.rb
+++ b/actionpack/test/template/date_helper_test.rb
@@ -21,56 +21,80 @@ class DateHelperTest < ActionView::TestCase
def assert_distance_of_time_in_words(from, to=nil)
to ||= from
- # 0..1 with include_seconds
- assert_equal "less than 5 seconds", distance_of_time_in_words(from, to + 0.seconds, true)
- assert_equal "less than 5 seconds", distance_of_time_in_words(from, to + 4.seconds, true)
- assert_equal "less than 10 seconds", distance_of_time_in_words(from, to + 5.seconds, true)
- assert_equal "less than 10 seconds", distance_of_time_in_words(from, to + 9.seconds, true)
- assert_equal "less than 20 seconds", distance_of_time_in_words(from, to + 10.seconds, true)
- assert_equal "less than 20 seconds", distance_of_time_in_words(from, to + 19.seconds, true)
- assert_equal "half a minute", distance_of_time_in_words(from, to + 20.seconds, true)
- assert_equal "half a minute", distance_of_time_in_words(from, to + 39.seconds, true)
- assert_equal "less than a minute", distance_of_time_in_words(from, to + 40.seconds, true)
- assert_equal "less than a minute", distance_of_time_in_words(from, to + 59.seconds, true)
- assert_equal "1 minute", distance_of_time_in_words(from, to + 60.seconds, true)
- assert_equal "1 minute", distance_of_time_in_words(from, to + 89.seconds, true)
-
- # First case 0..1
+ # 0..1 minute with :include_seconds => true
+ assert_equal "less than 5 seconds", distance_of_time_in_words(from, to + 0.seconds, :include_seconds => true)
+ assert_equal "less than 5 seconds", distance_of_time_in_words(from, to + 4.seconds, :include_seconds => true)
+ assert_equal "less than 10 seconds", distance_of_time_in_words(from, to + 5.seconds, :include_seconds => true)
+ assert_equal "less than 10 seconds", distance_of_time_in_words(from, to + 9.seconds, :include_seconds => true)
+ assert_equal "less than 20 seconds", distance_of_time_in_words(from, to + 10.seconds, :include_seconds => true)
+ assert_equal "less than 20 seconds", distance_of_time_in_words(from, to + 19.seconds, :include_seconds => true)
+ assert_equal "half a minute", distance_of_time_in_words(from, to + 20.seconds, :include_seconds => true)
+ assert_equal "half a minute", distance_of_time_in_words(from, to + 39.seconds, :include_seconds => true)
+ assert_equal "less than a minute", distance_of_time_in_words(from, to + 40.seconds, :include_seconds => true)
+ assert_equal "less than a minute", distance_of_time_in_words(from, to + 59.seconds, :include_seconds => true)
+ assert_equal "1 minute", distance_of_time_in_words(from, to + 60.seconds, :include_seconds => true)
+ assert_equal "1 minute", distance_of_time_in_words(from, to + 89.seconds, :include_seconds => true)
+
+ # 0..1 minute with :include_seconds => false
+ assert_equal "less than a minute", distance_of_time_in_words(from, to + 0.seconds, :include_seconds => false)
+ assert_equal "less than a minute", distance_of_time_in_words(from, to + 4.seconds, :include_seconds => false)
+ assert_equal "less than a minute", distance_of_time_in_words(from, to + 5.seconds, :include_seconds => false)
+ assert_equal "less than a minute", distance_of_time_in_words(from, to + 9.seconds, :include_seconds => false)
+ assert_equal "less than a minute", distance_of_time_in_words(from, to + 10.seconds, :include_seconds => false)
+ assert_equal "less than a minute", distance_of_time_in_words(from, to + 19.seconds, :include_seconds => false)
+ assert_equal "less than a minute", distance_of_time_in_words(from, to + 20.seconds, :include_seconds => false)
+ assert_equal "1 minute", distance_of_time_in_words(from, to + 39.seconds, :include_seconds => false)
+ assert_equal "1 minute", distance_of_time_in_words(from, to + 40.seconds, :include_seconds => false)
+ assert_equal "1 minute", distance_of_time_in_words(from, to + 59.seconds, :include_seconds => false)
+ assert_equal "1 minute", distance_of_time_in_words(from, to + 60.seconds, :include_seconds => false)
+ assert_equal "1 minute", distance_of_time_in_words(from, to + 89.seconds, :include_seconds => false)
+
+ # Note that we are including a 30-second boundary around the interval we
+ # want to test. For instance, "1 minute" is actually 30s to 1m29s. The
+ # reason for doing this is simple -- in `distance_of_time_to_words`, when we
+ # take the distance between our two Time objects in seconds and convert it
+ # to minutes, we round the number. So 29s gets rounded down to 0m, 30s gets
+ # rounded up to 1m, and 1m29s gets rounded down to 1m. A similar thing
+ # happens with the other cases.
+
+ # First case 0..1 minute
assert_equal "less than a minute", distance_of_time_in_words(from, to + 0.seconds)
assert_equal "less than a minute", distance_of_time_in_words(from, to + 29.seconds)
assert_equal "1 minute", distance_of_time_in_words(from, to + 30.seconds)
assert_equal "1 minute", distance_of_time_in_words(from, to + 1.minutes + 29.seconds)
- # 2..44
+ # 2 minutes up to 45 minutes
assert_equal "2 minutes", distance_of_time_in_words(from, to + 1.minutes + 30.seconds)
assert_equal "44 minutes", distance_of_time_in_words(from, to + 44.minutes + 29.seconds)
- # 45..89
+ # 45 minutes up to 90 minutes
assert_equal "about 1 hour", distance_of_time_in_words(from, to + 44.minutes + 30.seconds)
assert_equal "about 1 hour", distance_of_time_in_words(from, to + 89.minutes + 29.seconds)
- # 90..1439
+ # 90 minutes up to 24 hours
assert_equal "about 2 hours", distance_of_time_in_words(from, to + 89.minutes + 30.seconds)
assert_equal "about 24 hours", distance_of_time_in_words(from, to + 23.hours + 59.minutes + 29.seconds)
- # 1440..2519
+ # 24 hours up to 42 hours
assert_equal "1 day", distance_of_time_in_words(from, to + 23.hours + 59.minutes + 30.seconds)
assert_equal "1 day", distance_of_time_in_words(from, to + 41.hours + 59.minutes + 29.seconds)
- # 2520..43199
+ # 42 hours up to 30 days
assert_equal "2 days", distance_of_time_in_words(from, to + 41.hours + 59.minutes + 30.seconds)
assert_equal "3 days", distance_of_time_in_words(from, to + 2.days + 12.hours)
assert_equal "30 days", distance_of_time_in_words(from, to + 29.days + 23.hours + 59.minutes + 29.seconds)
- # 43200..86399
+ # 30 days up to 60 days
assert_equal "about 1 month", distance_of_time_in_words(from, to + 29.days + 23.hours + 59.minutes + 30.seconds)
- assert_equal "about 1 month", distance_of_time_in_words(from, to + 59.days + 23.hours + 59.minutes + 29.seconds)
+ assert_equal "about 1 month", distance_of_time_in_words(from, to + 44.days + 23.hours + 59.minutes + 29.seconds)
+ assert_equal "about 2 months", distance_of_time_in_words(from, to + 44.days + 23.hours + 59.minutes + 30.seconds)
+ assert_equal "about 2 months", distance_of_time_in_words(from, to + 59.days + 23.hours + 59.minutes + 29.seconds)
- # 86400..525599
+ # 60 days up to 365 days
assert_equal "2 months", distance_of_time_in_words(from, to + 59.days + 23.hours + 59.minutes + 30.seconds)
assert_equal "12 months", distance_of_time_in_words(from, to + 1.years - 31.seconds)
- # > 525599
+ # >= 365 days
assert_equal "about 1 year", distance_of_time_in_words(from, to + 1.years - 30.seconds)
assert_equal "about 1 year", distance_of_time_in_words(from, to + 1.years + 3.months - 1.day)
assert_equal "over 1 year", distance_of_time_in_words(from, to + 1.years + 6.months)
@@ -95,7 +119,8 @@ class DateHelperTest < ActionView::TestCase
# test to < from
assert_equal "about 4 hours", distance_of_time_in_words(from + 4.hours, to)
- assert_equal "less than 20 seconds", distance_of_time_in_words(from + 19.seconds, to, true)
+ assert_equal "less than 20 seconds", distance_of_time_in_words(from + 19.seconds, to, :include_seconds => true)
+ assert_equal "less than a minute", distance_of_time_in_words(from + 19.seconds, to, :include_seconds => false)
end
def test_distance_in_words
@@ -103,6 +128,11 @@ class DateHelperTest < ActionView::TestCase
assert_distance_of_time_in_words(from)
end
+ def test_time_ago_in_words_passes_include_seconds
+ assert_equal "less than 20 seconds", time_ago_in_words(15.seconds.ago, :include_seconds => true)
+ assert_equal "less than a minute", time_ago_in_words(15.seconds.ago, :include_seconds => false)
+ end
+
def test_distance_in_words_with_time_zones
from = Time.mktime(2004, 6, 6, 21, 45, 0)
assert_distance_of_time_in_words(from.in_time_zone('Alaska'))
@@ -125,13 +155,33 @@ class DateHelperTest < ActionView::TestCase
start_date = Date.new 1982, 12, 3
end_date = Date.new 2010, 11, 30
assert_equal("almost 28 years", distance_of_time_in_words(start_date, end_date))
+ assert_equal("almost 28 years", distance_of_time_in_words(end_date, start_date))
end
def test_distance_in_words_with_integers
- assert_equal "less than a minute", distance_of_time_in_words(59)
+ assert_equal "1 minute", distance_of_time_in_words(59)
assert_equal "about 1 hour", distance_of_time_in_words(60*60)
- assert_equal "less than a minute", distance_of_time_in_words(0, 59)
+ assert_equal "1 minute", distance_of_time_in_words(0, 59)
assert_equal "about 1 hour", distance_of_time_in_words(60*60, 0)
+ assert_equal "about 3 years", distance_of_time_in_words(10**8)
+ assert_equal "about 3 years", distance_of_time_in_words(0, 10**8)
+ end
+
+ def test_distance_in_words_with_times
+ assert_equal "1 minute", distance_of_time_in_words(30.seconds)
+ assert_equal "1 minute", distance_of_time_in_words(59.seconds)
+ assert_equal "2 minutes", distance_of_time_in_words(119.seconds)
+ assert_equal "2 minutes", distance_of_time_in_words(1.minute + 59.seconds)
+ assert_equal "3 minutes", distance_of_time_in_words(2.minute + 30.seconds)
+ assert_equal "44 minutes", distance_of_time_in_words(44.minutes + 29.seconds)
+ assert_equal "about 1 hour", distance_of_time_in_words(44.minutes + 30.seconds)
+ assert_equal "about 1 hour", distance_of_time_in_words(60.minutes)
+
+ # include seconds
+ assert_equal "half a minute", distance_of_time_in_words(39.seconds, 0, :include_seconds => true)
+ assert_equal "less than a minute", distance_of_time_in_words(40.seconds, 0, :include_seconds => true)
+ assert_equal "less than a minute", distance_of_time_in_words(59.seconds, 0, :include_seconds => true)
+ assert_equal "1 minute", distance_of_time_in_words(60.seconds, 0, :include_seconds => true)
end
def test_time_ago_in_words
@@ -567,7 +617,7 @@ class DateHelperTest < ActionView::TestCase
end
def test_select_minute_with_html_options
- expected = expected = %(<select id="date_minute" name="date[minute]" class="selector" accesskey="M">\n)
+ expected = %(<select id="date_minute" name="date[minute]" class="selector" accesskey="M">\n)
expected << %(<option value="00">00</option>\n<option value="01">01</option>\n<option value="02">02</option>\n<option value="03">03</option>\n<option value="04" selected="selected">04</option>\n<option value="05">05</option>\n<option value="06">06</option>\n<option value="07">07</option>\n<option value="08">08</option>\n<option value="09">09</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n<option value="32">32</option>\n<option value="33">33</option>\n<option value="34">34</option>\n<option value="35">35</option>\n<option value="36">36</option>\n<option value="37">37</option>\n<option value="38">38</option>\n<option value="39">39</option>\n<option value="40">40</option>\n<option value="41">41</option>\n<option value="42">42</option>\n<option value="43">43</option>\n<option value="44">44</option>\n<option value="45">45</option>\n<option value="46">46</option>\n<option value="47">47</option>\n<option value="48">48</option>\n<option value="49">49</option>\n<option value="50">50</option>\n<option value="51">51</option>\n<option value="52">52</option>\n<option value="53">53</option>\n<option value="54">54</option>\n<option value="55">55</option>\n<option value="56">56</option>\n<option value="57">57</option>\n<option value="58">58</option>\n<option value="59">59</option>\n)
expected << "</select>\n"
@@ -948,6 +998,15 @@ class DateHelperTest < ActionView::TestCase
assert_dom_equal expected, select_date(Time.mktime(2003, 8, 16), { :date_separator => " / ", :discard_month => true, :discard_day => true, :start_year => 2003, :end_year => 2005, :prefix => "date[first]"})
end
+ def test_select_date_with_hidden
+ expected = %(<input id="date_first_year" name="date[first][year]" type="hidden" value="2003"/>\n)
+ expected << %(<input id="date_first_month" name="date[first][month]" type="hidden" value="8" />\n)
+ expected << %(<input id="date_first_day" name="date[first][day]" type="hidden" value="16" />\n)
+
+ assert_dom_equal expected, select_date(Time.mktime(2003, 8, 16), { :prefix => "date[first]", :use_hidden => true })
+ assert_dom_equal expected, select_date(Time.mktime(2003, 8, 16), { :date_separator => " / ", :prefix => "date[first]", :use_hidden => true })
+ end
+
def test_select_datetime
expected = %(<select id="date_first_year" name="date[first][year]">\n)
expected << %(<option value="2003" selected="selected">2003</option>\n<option value="2004">2004</option>\n<option value="2005">2005</option>\n)
@@ -1184,6 +1243,18 @@ class DateHelperTest < ActionView::TestCase
:prompt => {:day => 'Choose day', :month => 'Choose month', :year => 'Choose year', :hour => 'Choose hour', :minute => 'Choose minute'})
end
+ def test_select_datetime_with_hidden
+ expected = %(<input id="date_first_year" name="date[first][year]" type="hidden" value="2003" />\n)
+ expected << %(<input id="date_first_month" name="date[first][month]" type="hidden" value="8" />\n)
+ expected << %(<input id="date_first_day" name="date[first][day]" type="hidden" value="16" />\n)
+ expected << %(<input id="date_first_hour" name="date[first][hour]" type="hidden" value="8" />\n)
+ expected << %(<input id="date_first_minute" name="date[first][minute]" type="hidden" value="4" />\n)
+
+ assert_dom_equal expected, select_datetime(Time.mktime(2003, 8, 16, 8, 4, 18), :prefix => "date[first]", :use_hidden => true)
+ assert_dom_equal expected, select_datetime(Time.mktime(2003, 8, 16, 8, 4, 18), :datetime_separator => "&mdash;", :date_separator => "/",
+ :time_separator => ":", :prefix => "date[first]", :use_hidden => true)
+ end
+
def test_select_time
expected = %(<input name="date[year]" id="date_year" value="2003" type="hidden" />\n)
expected << %(<input name="date[month]" id="date_month" value="8" type="hidden" />\n)
@@ -1359,6 +1430,17 @@ class DateHelperTest < ActionView::TestCase
:prompt => {:hour => 'Choose hour', :minute => 'Choose minute', :second => 'Choose seconds'})
end
+ def test_select_time_with_hidden
+ expected = %(<input id="date_first_year" name="date[first][year]" type="hidden" value="2003" />\n)
+ expected << %(<input id="date_first_month" name="date[first][month]" type="hidden" value="8" />\n)
+ expected << %(<input id="date_first_day" name="date[first][day]" type="hidden" value="16" />\n)
+ expected << %(<input id="date_first_hour" name="date[first][hour]" type="hidden" value="8" />\n)
+ expected << %(<input id="date_first_minute" name="date[first][minute]" type="hidden" value="4" />\n)
+
+ assert_dom_equal expected, select_time(Time.mktime(2003, 8, 16, 8, 4, 18), :prefix => "date[first]", :use_hidden => true)
+ assert_dom_equal expected, select_time(Time.mktime(2003, 8, 16, 8, 4, 18), :time_separator => ":", :prefix => "date[first]", :use_hidden => true)
+ end
+
def test_date_select
@post = Post.new
@post.written_on = Date.new(2004, 6, 15)
diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb
index 3fa3898ec8..beb3ea752a 100644
--- a/actionpack/test/template/form_helper_test.rb
+++ b/actionpack/test/template/form_helper_test.rb
@@ -97,7 +97,7 @@ class FormHelperTest < ActionView::TestCase
end
end
- match "/foo", :to => "controller#action"
+ get "/foo", :to => "controller#action"
root :to => "main#index"
end
@@ -350,36 +350,52 @@ class FormHelperTest < ActionView::TestCase
text_field("user", "email", :type => "email")
end
- def test_check_box
+ def test_check_box_is_html_safe
assert check_box("post", "secret").html_safe?
+ end
+
+ def test_check_box_checked_if_object_value_is_same_that_check_value
assert_dom_equal(
'<input name="post[secret]" type="hidden" value="0" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="1" />',
check_box("post", "secret")
)
+ end
+
+ def test_check_box_not_checked_if_object_value_is_same_that_unchecked_value
@post.secret = 0
assert_dom_equal(
'<input name="post[secret]" type="hidden" value="0" /><input id="post_secret" name="post[secret]" type="checkbox" value="1" />',
check_box("post", "secret")
)
+ end
+
+ def test_check_box_checked_if_option_checked_is_present
assert_dom_equal(
'<input name="post[secret]" type="hidden" value="0" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="1" />',
check_box("post", "secret" ,{"checked"=>"checked"})
)
+ end
+
+ def test_check_box_checked_if_object_value_is_true
@post.secret = true
assert_dom_equal(
'<input name="post[secret]" type="hidden" value="0" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="1" />',
check_box("post", "secret")
)
+
assert_dom_equal(
'<input name="post[secret]" type="hidden" value="0" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="1" />',
check_box("post", "secret?")
)
+ end
+ def test_check_box_checked_if_object_value_includes_checked_value
@post.secret = ['0']
assert_dom_equal(
'<input name="post[secret]" type="hidden" value="0" /><input id="post_secret" name="post[secret]" type="checkbox" value="1" />',
check_box("post", "secret")
)
+
@post.secret = ['1']
assert_dom_equal(
'<input name="post[secret]" type="hidden" value="0" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="1" />',
@@ -392,12 +408,92 @@ class FormHelperTest < ActionView::TestCase
assert_dom_equal('<input id="post_secret" name="post[secret]" type="checkbox" value="1" />', check_box("post", "secret", :include_hidden => false))
end
- def test_check_box_with_explicit_checked_and_unchecked_values
+ def test_check_box_with_explicit_checked_and_unchecked_values_when_object_value_is_string
@post.secret = "on"
assert_dom_equal(
'<input name="post[secret]" type="hidden" value="off" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="on" />',
check_box("post", "secret", {}, "on", "off")
)
+
+ @post.secret = "off"
+ assert_dom_equal(
+ '<input name="post[secret]" type="hidden" value="off" /><input id="post_secret" name="post[secret]" type="checkbox" value="on" />',
+ check_box("post", "secret", {}, "on", "off")
+ )
+ end
+
+ def test_check_box_with_explicit_checked_and_unchecked_values_when_object_value_is_boolean
+ @post.secret = false
+ assert_dom_equal(
+ '<input name="post[secret]" type="hidden" value="true" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="false" />',
+ check_box("post", "secret", {}, false, true)
+ )
+
+ @post.secret = true
+ assert_dom_equal(
+ '<input name="post[secret]" type="hidden" value="true" /><input id="post_secret" name="post[secret]" type="checkbox" value="false" />',
+ check_box("post", "secret", {}, false, true)
+ )
+ end
+
+ def test_check_box_with_explicit_checked_and_unchecked_values_when_object_value_is_integer
+ @post.secret = 0
+ assert_dom_equal(
+ '<input name="post[secret]" type="hidden" value="1" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="0" />',
+ check_box("post", "secret", {}, 0, 1)
+ )
+
+ @post.secret = 1
+ assert_dom_equal(
+ '<input name="post[secret]" type="hidden" value="1" /><input id="post_secret" name="post[secret]" type="checkbox" value="0" />',
+ check_box("post", "secret", {}, 0, 1)
+ )
+
+ @post.secret = 2
+ assert_dom_equal(
+ '<input name="post[secret]" type="hidden" value="1" /><input id="post_secret" name="post[secret]" type="checkbox" value="0" />',
+ check_box("post", "secret", {}, 0, 1)
+ )
+ end
+
+ def test_check_box_with_explicit_checked_and_unchecked_values_when_object_value_is_float
+ @post.secret = 0.0
+ assert_dom_equal(
+ '<input name="post[secret]" type="hidden" value="1" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="0" />',
+ check_box("post", "secret", {}, 0, 1)
+ )
+
+ @post.secret = 1.1
+ assert_dom_equal(
+ '<input name="post[secret]" type="hidden" value="1" /><input id="post_secret" name="post[secret]" type="checkbox" value="0" />',
+ check_box("post", "secret", {}, 0, 1)
+ )
+
+ @post.secret = 2.2
+ assert_dom_equal(
+ '<input name="post[secret]" type="hidden" value="1" /><input id="post_secret" name="post[secret]" type="checkbox" value="0" />',
+ check_box("post", "secret", {}, 0, 1)
+ )
+ end
+
+ def test_check_box_with_explicit_checked_and_unchecked_values_when_object_value_is_big_decimal
+ @post.secret = BigDecimal.new(0)
+ assert_dom_equal(
+ '<input name="post[secret]" type="hidden" value="1" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="0" />',
+ check_box("post", "secret", {}, 0, 1)
+ )
+
+ @post.secret = BigDecimal.new(1)
+ assert_dom_equal(
+ '<input name="post[secret]" type="hidden" value="1" /><input id="post_secret" name="post[secret]" type="checkbox" value="0" />',
+ check_box("post", "secret", {}, 0, 1)
+ )
+
+ @post.secret = BigDecimal.new(2.2, 1)
+ assert_dom_equal(
+ '<input name="post[secret]" type="hidden" value="1" /><input id="post_secret" name="post[secret]" type="checkbox" value="0" />',
+ check_box("post", "secret", {}, 0, 1)
+ )
end
def test_check_box_with_nil_unchecked_value
@@ -2169,6 +2265,23 @@ class FormHelperTest < ActionView::TestCase
ActionView::Base.default_form_builder = old_default_form_builder
end
+ def test_lazy_loading_default_form_builder
+ old_default_form_builder, ActionView::Base.default_form_builder =
+ ActionView::Base.default_form_builder, "FormHelperTest::LabelledFormBuilder"
+
+ form_for(@post) do |f|
+ concat f.text_field(:title)
+ end
+
+ expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do
+ "<label for='title'>Title:</label> <input name='post[title]' type='text' id='post_title' value='Hello World' /><br/>"
+ end
+
+ assert_dom_equal expected, output_buffer
+ ensure
+ ActionView::Base.default_form_builder = old_default_form_builder
+ end
+
def test_fields_for_with_labelled_builder
output_buffer = fields_for(:post, @post, :builder => LabelledFormBuilder) do |f|
concat f.text_field(:title)
diff --git a/actionpack/test/template/javascript_helper_test.rb b/actionpack/test/template/javascript_helper_test.rb
index 0b96985002..fe7607ee26 100644
--- a/actionpack/test/template/javascript_helper_test.rb
+++ b/actionpack/test/template/javascript_helper_test.rb
@@ -42,36 +42,6 @@ class JavaScriptHelperTest < ActionView::TestCase
assert_instance_of ActiveSupport::SafeBuffer, escape_javascript(ActiveSupport::SafeBuffer.new(given))
end
- def test_button_to_function
- assert_dom_equal %(<input type="button" onclick="alert('Hello world!');" value="Greeting" />),
- button_to_function("Greeting", "alert('Hello world!')")
- end
-
- def test_button_to_function_with_onclick
- assert_dom_equal "<input onclick=\"alert('Goodbye World :('); alert('Hello world!');\" type=\"button\" value=\"Greeting\" />",
- button_to_function("Greeting", "alert('Hello world!')", :onclick => "alert('Goodbye World :(')")
- end
-
- def test_button_to_function_without_function
- assert_dom_equal "<input onclick=\";\" type=\"button\" value=\"Greeting\" />",
- button_to_function("Greeting")
- end
-
- def test_link_to_function
- assert_dom_equal %(<a href="#" onclick="alert('Hello world!'); return false;">Greeting</a>),
- link_to_function("Greeting", "alert('Hello world!')")
- end
-
- def test_link_to_function_with_existing_onclick
- assert_dom_equal %(<a href="#" onclick="confirm('Sanity!'); alert('Hello world!'); return false;">Greeting</a>),
- link_to_function("Greeting", "alert('Hello world!')", :onclick => "confirm('Sanity!')")
- end
-
- def test_function_with_href
- assert_dom_equal %(<a href="http://example.com/" onclick="alert('Hello world!'); return false;">Greeting</a>),
- link_to_function("Greeting", "alert('Hello world!')", :href => 'http://example.com/')
- end
-
def test_javascript_tag
self.output_buffer = 'foo'
diff --git a/actionpack/test/template/render_test.rb b/actionpack/test/template/render_test.rb
index 122b07d348..cdaca56ef2 100644
--- a/actionpack/test/template/render_test.rb
+++ b/actionpack/test/template/render_test.rb
@@ -21,9 +21,7 @@ module RenderTestCases
end
def test_render_without_options
- @view.render()
- flunk "Render did not raise ArgumentError"
- rescue ArgumentError => e
+ e = assert_raises(ArgumentError) { @view.render() }
assert_match "You invoked render but did not give any of :partial, :template, :inline, :file or :text option.", e.message
end
@@ -153,25 +151,26 @@ module RenderTestCases
end
def test_render_partial_with_invalid_name
- @view.render(:partial => "test/200")
- flunk "Render did not raise ArgumentError"
- rescue ArgumentError => e
+ e = assert_raises(ArgumentError) { @view.render(:partial => "test/200") }
assert_equal "The partial name (test/200) is not a valid Ruby identifier; " +
- "make sure your partial name starts with a letter or underscore, " +
- "and is followed by any combinations of letters, numbers, or underscores.", e.message
+ "make sure your partial name starts with a letter or underscore, " +
+ "and is followed by any combinations of letters, numbers, or underscores.", e.message
+ end
+
+ def test_render_partial_with_missing_filename
+ e = assert_raises(ArgumentError) { @view.render(:partial => "test/") }
+ assert_equal "The partial name (test/) is not a valid Ruby identifier; " +
+ "make sure your partial name starts with a letter or underscore, " +
+ "and is followed by any combinations of letters, numbers, or underscores.", e.message
end
def test_render_partial_with_incompatible_object
- @view.render(:partial => nil)
- flunk "Render did not raise ArgumentError"
- rescue ArgumentError => e
+ e = assert_raises(ArgumentError) { @view.render(:partial => nil) }
assert_equal "'#{nil.inspect}' is not an ActiveModel-compatible object. It must implement :to_partial_path.", e.message
end
def test_render_partial_with_errors
- @view.render(:partial => "test/raise")
- flunk "Render did not raise Template::Error"
- rescue ActionView::Template::Error => e
+ e = assert_raises(ActionView::Template::Error) { @view.render(:partial => "test/raise") }
assert_match %r!method.*doesnt_exist!, e.message
assert_equal "", e.sub_template_message
assert_equal "1", e.line_number
@@ -180,9 +179,7 @@ module RenderTestCases
end
def test_render_sub_template_with_errors
- @view.render(:template => "test/sub_template_raise")
- flunk "Render did not raise Template::Error"
- rescue ActionView::Template::Error => e
+ e = assert_raises(ActionView::Template::Error) { @view.render(:template => "test/sub_template_raise") }
assert_match %r!method.*doesnt_exist!, e.message
assert_equal "Trace of template inclusion: #{File.expand_path("#{FIXTURE_LOAD_PATH}/test/sub_template_raise.html.erb")}", e.sub_template_message
assert_equal "1", e.line_number
@@ -190,9 +187,7 @@ module RenderTestCases
end
def test_render_file_with_errors
- @view.render(:file => File.expand_path("test/_raise", FIXTURE_LOAD_PATH))
- flunk "Render did not raise Template::Error"
- rescue ActionView::Template::Error => e
+ e = assert_raises(ActionView::Template::Error) { @view.render(:file => File.expand_path("test/_raise", FIXTURE_LOAD_PATH)) }
assert_match %r!method.*doesnt_exist!, e.message
assert_equal "", e.sub_template_message
assert_equal "1", e.line_number
@@ -238,11 +233,26 @@ module RenderTestCases
def test_render_partial_with_nil_values_in_collection
assert_equal "Hello: davidHello: Anonymous", @view.render(:partial => "test/customer", :collection => [ Customer.new("david"), nil ])
end
-
+
def test_render_partial_with_layout_using_collection_and_template
assert_equal "<b>Hello: Amazon</b><b>Hello: Yahoo</b>", @view.render(:partial => "test/customer", :layout => 'test/b_layout_for_partial', :collection => [ Customer.new("Amazon"), Customer.new("Yahoo") ])
end
+ def test_render_partial_with_layout_using_collection_and_template_makes_current_item_available_in_layout
+ assert_equal '<b class="amazon">Hello: Amazon</b><b class="yahoo">Hello: Yahoo</b>',
+ @view.render(:partial => "test/customer", :layout => 'test/b_layout_for_partial_with_object', :collection => [ Customer.new("Amazon"), Customer.new("Yahoo") ])
+ end
+
+ def test_render_partial_with_layout_using_collection_and_template_makes_current_item_counter_available_in_layout
+ assert_equal '<b data-counter="0">Hello: Amazon</b><b data-counter="1">Hello: Yahoo</b>',
+ @view.render(:partial => "test/customer", :layout => 'test/b_layout_for_partial_with_object_counter', :collection => [ Customer.new("Amazon"), Customer.new("Yahoo") ])
+ end
+
+ def test_render_partial_with_layout_using_object_and_template_makes_object_available_in_layout
+ assert_equal '<b class="amazon">Hello: Amazon</b>',
+ @view.render(:partial => "test/customer", :layout => 'test/b_layout_for_partial_with_object', :object => Customer.new("Amazon"))
+ end
+
def test_render_partial_with_empty_array_should_return_nil
assert_nil @view.render(:partial => [])
end
@@ -274,7 +284,7 @@ module RenderTestCases
# TODO: The reason for this test is unclear, improve documentation
def test_render_missing_xml_partial_and_raise_missing_template
@view.formats = [:xml]
- assert_raise(ActionView::MissingTemplate) { @view.render(:partial => "test/layout_for_partial") }
+ assert_raises(ActionView::MissingTemplate) { @view.render(:partial => "test/layout_for_partial") }
ensure
@view.formats = nil
end
@@ -315,7 +325,7 @@ module RenderTestCases
ActionView::Template.register_template_handler :foo, CustomHandler
assert_equal 'source: "Hello, <%= name %>!"', @view.render(:inline => "Hello, <%= name %>!", :locals => { :name => "Josh" }, :type => :foo)
end
-
+
def test_render_knows_about_types_registered_when_extensions_are_checked_earlier_in_initialization
ActionView::Template::Handlers.extensions
ActionView::Template.register_template_handler :foo, CustomHandler
@@ -325,7 +335,7 @@ module RenderTestCases
def test_render_ignores_templates_with_malformed_template_handlers
ActiveSupport::Deprecation.silence do
%w(malformed malformed.erb malformed.html.erb malformed.en.html.erb).each do |name|
- assert_raise(ActionView::MissingTemplate) { @view.render(:file => "test/malformed/#{name}") }
+ assert_raises(ActionView::MissingTemplate) { @view.render(:file => "test/malformed/#{name}") }
end
end
end
@@ -450,23 +460,15 @@ class LazyViewRenderTest < ActiveSupport::TestCase
def test_render_utf8_template_with_incompatible_external_encoding
with_external_encoding Encoding::SHIFT_JIS do
- begin
- @view.render(:file => "test/utf8", :formats => [:html], :layouts => "layouts/yield")
- flunk 'Should have raised incompatible encoding error'
- rescue ActionView::Template::Error => error
- assert_match 'Your template was not saved as valid Shift_JIS', error.original_exception.message
- end
+ e = assert_raises(ActionView::Template::Error) { @view.render(:file => "test/utf8", :formats => [:html], :layouts => "layouts/yield") }
+ assert_match 'Your template was not saved as valid Shift_JIS', e.original_exception.message
end
end
def test_render_utf8_template_with_partial_with_incompatible_encoding
with_external_encoding Encoding::SHIFT_JIS do
- begin
- @view.render(:file => "test/utf8_magic_with_bare_partial", :formats => [:html], :layouts => "layouts/yield")
- flunk 'Should have raised incompatible encoding error'
- rescue ActionView::Template::Error => error
- assert_match 'Your template was not saved as valid Shift_JIS', error.original_exception.message
- end
+ e = assert_raises(ActionView::Template::Error) { @view.render(:file => "test/utf8_magic_with_bare_partial", :formats => [:html], :layouts => "layouts/yield") }
+ assert_match 'Your template was not saved as valid Shift_JIS', e.original_exception.message
end
end
diff --git a/actionpack/test/template/tag_helper_test.rb b/actionpack/test/template/tag_helper_test.rb
index 32b33b4a55..7161d107b3 100644
--- a/actionpack/test/template/tag_helper_test.rb
+++ b/actionpack/test/template/tag_helper_test.rb
@@ -91,6 +91,11 @@ class TagHelperTest < ActionView::TestCase
assert_equal "<![CDATA[<hello world>]]>", cdata_section("<hello world>")
end
+ def test_cdata_section_splitted
+ assert_equal "<![CDATA[hello]]]]><![CDATA[>world]]>", cdata_section("hello]]>world")
+ assert_equal "<![CDATA[hello]]]]><![CDATA[>world]]]]><![CDATA[>again]]>", cdata_section("hello]]>world]]>again")
+ end
+
def test_escape_once
assert_equal '1 &lt; 2 &amp; 3', escape_once('1 < 2 &amp; 3')
end
diff --git a/actionpack/test/template/test_test.rb b/actionpack/test/template/test_test.rb
index adcbf1447f..108a674d95 100644
--- a/actionpack/test/template/test_test.rb
+++ b/actionpack/test/template/test_test.rb
@@ -48,7 +48,7 @@ class PeopleHelperTest < ActionView::TestCase
def with_test_route_set
with_routing do |set|
set.draw do
- match 'people', :to => 'people#index', :as => :people
+ get 'people', :to => 'people#index', :as => :people
end
yield
end
diff --git a/actionpack/test/template/translation_helper_test.rb b/actionpack/test/template/translation_helper_test.rb
index 397de9c2ce..97777ccff0 100644
--- a/actionpack/test/template/translation_helper_test.rb
+++ b/actionpack/test/template/translation_helper_test.rb
@@ -11,7 +11,8 @@ class TranslationHelperTest < ActiveSupport::TestCase
:translations => {
:templates => {
:found => { :foo => 'Foo' },
- :array => { :foo => { :bar => 'Foo Bar' } }
+ :array => { :foo => { :bar => 'Foo Bar' } },
+ :default => { :foo => 'Foo' }
},
:foo => 'Foo',
:hello => '<a>Hello World</a>',
@@ -71,6 +72,10 @@ class TranslationHelperTest < ActiveSupport::TestCase
assert_equal 'Foo Bar', @view.render(:file => 'translations/templates/array').strip
end
+ def test_default_lookup_scoped_by_partial
+ assert_equal 'Foo', view.render(:file => 'translations/templates/default').strip
+ end
+
def test_missing_translation_scoped_by_partial
expected = '<span class="translation_missing" title="translation missing: en.translations.templates.missing.missing">Missing</span>'
assert_equal expected, view.render(:file => 'translations/templates/missing').strip
@@ -102,4 +107,22 @@ class TranslationHelperTest < ActiveSupport::TestCase
def test_translation_returning_an_array_ignores_html_suffix
assert_equal ["foo", "bar"], translate(:'translations.array_html')
end
+
+ def test_translate_with_default_named_html
+ translation = translate(:'translations.missing', :default => :'translations.hello_html')
+ assert_equal '<a>Hello World</a>', translation
+ assert translation.html_safe?
+ end
+
+ def test_translate_with_two_defaults_named_html
+ translation = translate(:'translations.missing', :default => [:'translations.missing_html', :'translations.hello_html'])
+ assert_equal '<a>Hello World</a>', translation
+ assert translation.html_safe?
+ end
+
+ def test_translate_with_last_default_named_html
+ translation = translate(:'translations.missing', :default => [:'translations.missing', :'translations.hello_html'])
+ assert_equal '<a>Hello World</a>', translation
+ assert translation.html_safe?
+ end
end
diff --git a/actionpack/test/template/url_helper_test.rb b/actionpack/test/template/url_helper_test.rb
index 88f506b217..eaa8bdbd26 100644
--- a/actionpack/test/template/url_helper_test.rb
+++ b/actionpack/test/template/url_helper_test.rb
@@ -15,9 +15,9 @@ class UrlHelperTest < ActiveSupport::TestCase
routes = ActionDispatch::Routing::RouteSet.new
routes.draw do
- match "/" => "foo#bar"
- match "/other" => "foo#other"
- match "/article/:id" => "foo#article", :as => :article
+ get "/" => "foo#bar"
+ get "/other" => "foo#other"
+ get "/article/:id" => "foo#article", :as => :article
end
include routes.url_helpers
@@ -471,25 +471,25 @@ end
class UrlHelperControllerTest < ActionController::TestCase
class UrlHelperController < ActionController::Base
test_routes do
- match 'url_helper_controller_test/url_helper/show/:id',
+ get 'url_helper_controller_test/url_helper/show/:id',
:to => 'url_helper_controller_test/url_helper#show',
:as => :show
- match 'url_helper_controller_test/url_helper/profile/:name',
+ get 'url_helper_controller_test/url_helper/profile/:name',
:to => 'url_helper_controller_test/url_helper#show',
:as => :profile
- match 'url_helper_controller_test/url_helper/show_named_route',
+ get 'url_helper_controller_test/url_helper/show_named_route',
:to => 'url_helper_controller_test/url_helper#show_named_route',
:as => :show_named_route
- match "/:controller(/:action(/:id))"
+ get "/:controller(/:action(/:id))"
- match 'url_helper_controller_test/url_helper/normalize_recall_params',
+ get 'url_helper_controller_test/url_helper/normalize_recall_params',
:to => UrlHelperController.action(:normalize_recall),
:as => :normalize_recall_params
- match '/url_helper_controller_test/url_helper/override_url_helper/default',
+ get '/url_helper_controller_test/url_helper/override_url_helper/default',
:to => 'url_helper_controller_test/url_helper#override_url_helper',
:as => :override_url_helper
end