aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack')
-rw-r--r--actionpack/CHANGELOG.md74
-rw-r--r--actionpack/lib/action_controller/metal/data_streaming.rb2
-rw-r--r--actionpack/lib/action_dispatch/http/request.rb5
-rw-r--r--actionpack/lib/action_dispatch/middleware/best_standards_support.rb8
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb2
-rw-r--r--actionpack/lib/action_dispatch/routing/redirection.rb6
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb29
-rw-r--r--actionpack/lib/action_view/helpers/date_helper.rb15
-rw-r--r--actionpack/lib/action_view/helpers/form_helper.rb4
-rw-r--r--actionpack/lib/action_view/helpers/form_tag_helper.rb4
-rw-r--r--actionpack/lib/action_view/renderer/partial_renderer.rb2
-rw-r--r--actionpack/lib/action_view/template/handlers/erb.rb16
-rw-r--r--actionpack/test/controller/new_base/render_template_test.rb10
-rw-r--r--actionpack/test/controller/send_file_test.rb14
-rw-r--r--actionpack/test/dispatch/best_standards_support_test.rb34
-rw-r--r--actionpack/test/dispatch/prefix_generation_test.rb5
-rw-r--r--actionpack/test/dispatch/request_test.rb7
-rw-r--r--actionpack/test/dispatch/routing/route_set_test.rb86
-rw-r--r--actionpack/test/dispatch/routing_test.rb9
-rw-r--r--actionpack/test/template/date_helper_i18n_test.rb15
-rw-r--r--actionpack/test/template/date_helper_test.rb31
-rw-r--r--actionpack/test/template/form_helper_test.rb13
-rw-r--r--actionpack/test/template/render_test.rb7
-rw-r--r--actionpack/test/template/sprockets_helper_test.rb2
-rw-r--r--actionpack/test/template/sprockets_helper_with_routes_test.rb4
-rw-r--r--actionpack/test/template/template_test.rb16
26 files changed, 381 insertions, 39 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index 4d7035e63f..6917d0e06c 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,3 +1,77 @@
+## Rails 3.2.11 (unreleased) ##
+
+* Clear url helper methods when routes are reloaded by removing the methods
+ explicitly rather than just clearing the module because it didn't work
+ properly and could be the source of a memory leak.
+
+ *Andrew White*
+
+* Fix a bug in ActionDispatch::Request#raw_post that caused env['rack.input']
+ to be read but not rewound.
+
+ *Matt Venables*
+
+* More descriptive error messages when calling `render :partial` with
+ an invalid `:layout` argument.
+ #8376
+
+ render :partial => 'partial', :layout => true
+
+ # results in ActionView::MissingTemplate: Missing partial /true
+
+ *Yves Senn*
+
+* Accept symbols as #send_data :disposition value. [Backport #8329] *Elia Schito*
+
+* Add i18n scope to distance_of_time_in_words. [Backport #7997] *Steve Klabnik*
+
+* Fix side effect of `url_for` changing the `:controller` string option. [Backport #6003]
+ Before:
+
+ controller = '/projects'
+ url_for :controller => controller, :action => 'status'
+
+ puts controller #=> 'projects'
+
+ After
+
+ puts controller #=> '/projects'
+
+ [Nikita Beloglazov + Andrew White]
+
+* Introduce `ActionView::Template::Handlers::ERB.escape_whitelist`. This is a list
+ of mime types where template text is not html escaped by default. It prevents `Jack & Joe`
+ from rendering as `Jack & Joe` for the whitelisted mime types. The default whitelist
+ contains text/plain. Fix #7976 [Backport #8235]
+
+ *Joost Baaij*
+
+* `BestStandardsSupport` middleware now appends it's `X-UA-Compatible` value to app's
+ returned value if any. Fix #8086 [Backport #8093]
+
+ *Nikita Afanasenko*
+
+* prevent double slashes in engine urls when `Rails.application.default_url_options[:trailing_slash] = true` is set
+ Fix #7842
+
+ *Yves Senn*
+
+* Fix input name when `:multiple => true` and `:index` are set.
+
+ Before:
+
+ check_box("post", "comment_ids", { :multiple => true, :index => "foo" }, 1)
+ #=> <input name=\"post[foo][comment_ids]\" type=\"hidden\" value=\"0\" /><input id=\"post_foo_comment_ids_1\" name=\"post[foo][comment_ids]\" type=\"checkbox\" value=\"1\" />
+
+ After:
+
+ check_box("post", "comment_ids", { :multiple => true, :index => "foo" }, 1)
+ #=> <input name=\"post[foo][comment_ids][]\" type=\"hidden\" value=\"0\" /><input id=\"post_foo_comment_ids_1\" name=\"post[foo][comment_ids][]\" type=\"checkbox\" value=\"1\" />
+
+ Fix #8108
+
+ *Daniel Fox, Grant Hutchins & Trace Wax*
+
## Rails 3.2.10 ##
## Rails 3.2.9 (Nov 12, 2012) ##
diff --git a/actionpack/lib/action_controller/metal/data_streaming.rb b/actionpack/lib/action_controller/metal/data_streaming.rb
index 62e16ea047..95c058fc86 100644
--- a/actionpack/lib/action_controller/metal/data_streaming.rb
+++ b/actionpack/lib/action_controller/metal/data_streaming.rb
@@ -141,7 +141,7 @@ module ActionController #:nodoc:
raise ArgumentError, ":#{arg} option required" if options[arg].nil?
end
- disposition = options[:disposition]
+ disposition = options[:disposition].to_s
disposition += %(; filename="#{options[:filename]}") if options[:filename]
content_type = options[:type]
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index afc0496ef9..0413346d94 100644
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -179,8 +179,9 @@ module ActionDispatch
# work with raw requests directly.
def raw_post
unless @env.include? 'RAW_POST_DATA'
- @env['RAW_POST_DATA'] = body.read(@env['CONTENT_LENGTH'].to_i)
- body.rewind if body.respond_to?(:rewind)
+ raw_post_body = body
+ @env['RAW_POST_DATA'] = raw_post_body.read(@env['CONTENT_LENGTH'].to_i)
+ raw_post_body.rewind if raw_post_body.respond_to?(:rewind)
end
@env['RAW_POST_DATA']
end
diff --git a/actionpack/lib/action_dispatch/middleware/best_standards_support.rb b/actionpack/lib/action_dispatch/middleware/best_standards_support.rb
index 69adcc419f..d338996240 100644
--- a/actionpack/lib/action_dispatch/middleware/best_standards_support.rb
+++ b/actionpack/lib/action_dispatch/middleware/best_standards_support.rb
@@ -15,7 +15,13 @@ module ActionDispatch
def call(env)
status, headers, body = @app.call(env)
- headers["X-UA-Compatible"] = @header
+
+ if headers["X-UA-Compatible"] && @header
+ headers["X-UA-Compatible"] << "," << @header.to_s
+ else
+ headers["X-UA-Compatible"] = @header
+ end
+
[status, headers, body]
end
end
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index 952219631a..9a474d2e3a 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -451,7 +451,7 @@ module ActionDispatch
# we must actually delete prefix segment keys to avoid passing them to next url_for
_route.segment_keys.each { |k| options.delete(k) }
prefix = _routes.url_helpers.send("#{name}_path", prefix_options)
- prefix = '' if prefix == '/'
+ prefix = prefix.gsub(%r{/\z}, '')
prefix
end
end
diff --git a/actionpack/lib/action_dispatch/routing/redirection.rb b/actionpack/lib/action_dispatch/routing/redirection.rb
index dc28389360..50b20a2a25 100644
--- a/actionpack/lib/action_dispatch/routing/redirection.rb
+++ b/actionpack/lib/action_dispatch/routing/redirection.rb
@@ -78,10 +78,10 @@ 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
+ # }
#
# 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.
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index 667094c469..a993699e05 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -94,7 +94,12 @@ module ActionDispatch
attr_reader :routes, :helpers, :module
def initialize
- clear!
+ @routes = {}
+ @helpers = []
+
+ @module = Module.new do
+ instance_methods.each { |selector| remove_method(selector) }
+ end
end
def helper_names
@@ -102,12 +107,14 @@ module ActionDispatch
end
def clear!
+ @helpers.each do |helper|
+ @module.module_eval do
+ remove_possible_method helper
+ end
+ end
+
@routes = {}
@helpers = []
-
- @module ||= Module.new do
- instance_methods.each { |selector| remove_method(selector) }
- end
end
def add(name, route)
@@ -291,7 +298,6 @@ module ActionDispatch
def clear!
@finalized = false
- @url_helpers = nil
named_routes.clear
set.clear
formatter.clear
@@ -442,12 +448,12 @@ module ActionDispatch
normalize_options!
normalize_controller_action_id!
use_relative_controller!
- controller.sub!(%r{^/}, '') if controller
+ normalize_controller!
handle_nil_action!
end
def controller
- @controller ||= @options[:controller]
+ @options[:controller]
end
def current_controller
@@ -504,10 +510,15 @@ module ActionDispatch
old_parts = current_controller.split('/')
size = controller.count("/") + 1
parts = old_parts[0...-size] << controller
- @controller = @options[:controller] = parts.join("/")
+ @options[:controller] = parts.join("/")
end
end
+ # Remove leading slashes from controllers
+ def normalize_controller!
+ @options[:controller] = controller.sub(%r{^/}, '') if controller
+ end
+
# This handles the case of :action => nil being explicitly passed.
# It is identical to :action => "index"
def handle_nil_action!
diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb
index 87e2332c42..99aa144d3a 100644
--- a/actionpack/lib/action_view/helpers/date_helper.rb
+++ b/actionpack/lib/action_view/helpers/date_helper.rb
@@ -65,12 +65,17 @@ module ActionView
# 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 = {})
+ options = {
+ :scope => :'datetime.distance_in_words',
+ }.merge!(options)
+
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
+ distance = (to_time.to_f - from_time.to_f).abs
+ distance_in_minutes = (distance / 60.0).round
+ distance_in_seconds = distance.round
- I18n.with_options :locale => options[:locale], :scope => :'datetime.distance_in_words' do |locale|
+ I18n.with_options :locale => options[:locale], :scope => options[:scope] do |locale|
case distance_in_minutes
when 0..1
return distance_in_minutes == 0 ?
@@ -129,8 +134,8 @@ module ActionView
# 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 = false, options = {})
+ distance_of_time_in_words(from_time, Time.now, include_seconds, options)
end
alias_method :distance_of_time_in_words_to_now, :time_ago_in_words
diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb
index a3409ee3c7..d00bad7608 100644
--- a/actionpack/lib/action_view/helpers/form_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_helper.rb
@@ -1205,9 +1205,11 @@ module ActionView
options["name"] ||= tag_name_with_index(@auto_index)
options["id"] = options.fetch("id"){ tag_id_with_index(@auto_index) }
else
- options["name"] ||= tag_name + (options['multiple'] ? '[]' : '')
+ options["name"] ||= tag_name
options["id"] = options.fetch("id"){ tag_id }
end
+
+ options["name"] += "[]" if options["multiple"]
options["id"] = [options.delete('namespace'), options["id"]].compact.join("_").presence
end
diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb
index 670ff18a66..f0573437ca 100644
--- a/actionpack/lib/action_view/helpers/form_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb
@@ -45,7 +45,7 @@ module ActionView
# # => <form action="/posts" method="post">
#
# form_tag('/posts/1', :method => :put)
- # # => <form action="/posts/1" method="put">
+ # # => <form action="/posts/1" method="post"> ... <input name="_method" type="hidden" value="put" /> ...
#
# form_tag('/upload', :multipart => true)
# # => <form action="/upload" method="post" enctype="multipart/form-data">
@@ -53,7 +53,7 @@ module ActionView
# <%= form_tag('/posts') do -%>
# <div><%= submit_tag 'Save' %></div>
# <% end -%>
- # # => <form action="/posts" method="post"><div><input type="submit" name="submit" value="Save" /></div></form>
+ # # => <form action="/posts" method="post"><div><input type="submit" name="commit" value="Save" /></div></form>
#
# <%= form_tag('/posts', :remote => true) %>
# # => <form action="/posts" method="post" data-remote="true">
diff --git a/actionpack/lib/action_view/renderer/partial_renderer.rb b/actionpack/lib/action_view/renderer/partial_renderer.rb
index 3093aca91e..71fa05ab3e 100644
--- a/actionpack/lib/action_view/renderer/partial_renderer.rb
+++ b/actionpack/lib/action_view/renderer/partial_renderer.rb
@@ -256,7 +256,7 @@ module ActionView
object, as = @object, @variable
if !block && (layout = @options[:layout])
- layout = find_template(layout)
+ layout = find_template(layout.to_s)
end
object ||= locals[as]
diff --git a/actionpack/lib/action_view/template/handlers/erb.rb b/actionpack/lib/action_view/template/handlers/erb.rb
index ea495ea9ca..118b18a81c 100644
--- a/actionpack/lib/action_view/template/handlers/erb.rb
+++ b/actionpack/lib/action_view/template/handlers/erb.rb
@@ -15,6 +15,17 @@ module ActionView
src << "@output_buffer.safe_concat('" << escape_text(text) << "');"
end
+ # Erubis toggles <%= and <%== behavior when escaping is enabled.
+ # We override to always treat <%== as escaped.
+ def add_expr(src, code, indicator)
+ case indicator
+ when '=='
+ add_expr_escaped(src, code)
+ else
+ super
+ end
+ end
+
BLOCK_EXPR = /\s+(do|\{)(\s*\|[^|]*\|)?\s*\Z/
def add_expr_literal(src, code)
@@ -48,6 +59,10 @@ module ActionView
class_attribute :erb_implementation
self.erb_implementation = Erubis
+ # Do not escape templates of these mime types.
+ class_attribute :escape_whitelist
+ self.escape_whitelist = ["text/plain"]
+
ENCODING_TAG = Regexp.new("\\A(<%#{ENCODING_FLAG}-?%>)[ \\t]*")
def self.call(template)
@@ -83,6 +98,7 @@ module ActionView
self.class.erb_implementation.new(
erb,
+ :escape => (self.class.escape_whitelist.include? template.mime_type),
:trim => (self.class.erb_trim_mode == "-")
).src
end
diff --git a/actionpack/test/controller/new_base/render_template_test.rb b/actionpack/test/controller/new_base/render_template_test.rb
index 29c8885d9f..c727f03346 100644
--- a/actionpack/test/controller/new_base/render_template_test.rb
+++ b/actionpack/test/controller/new_base/render_template_test.rb
@@ -9,7 +9,8 @@ module RenderTemplate
"locals.html.erb" => "The secret is <%= secret %>",
"xml_template.xml.builder" => "xml.html do\n xml.p 'Hello'\nend",
"with_raw.html.erb" => "Hello <%=raw '<strong>this is raw</strong>' %>",
- "with_implicit_raw.html.erb" => "Hello <%== '<strong>this is also raw</strong>' %>",
+ "with_implicit_raw.html.erb" => "Hello <%== '<strong>this is also raw</strong>' %> in a html template",
+ "with_implicit_raw.text.erb" => "Hello <%== '<strong>this is also raw</strong>' %> in a text template",
"test/with_json.html.erb" => "<%= render :template => 'test/with_json', :formats => [:json] %>",
"test/with_json.json.erb" => "<%= render :template => 'test/final', :formats => [:json] %>",
"test/final.json.erb" => "{ final: json }",
@@ -113,7 +114,12 @@ module RenderTemplate
get :with_implicit_raw
- assert_body "Hello <strong>this is also raw</strong>"
+ assert_body "Hello <strong>this is also raw</strong> in a html template"
+ assert_status 200
+
+ get :with_implicit_raw, :format => 'text'
+
+ assert_body "Hello <strong>this is also raw</strong> in a text template"
assert_status 200
end
diff --git a/actionpack/test/controller/send_file_test.rb b/actionpack/test/controller/send_file_test.rb
index 8f885ff28e..4e4dd8d005 100644
--- a/actionpack/test/controller/send_file_test.rb
+++ b/actionpack/test/controller/send_file_test.rb
@@ -118,6 +118,18 @@ class SendFileTest < ActionController::TestCase
assert_equal 'private', h['Cache-Control']
end
+ def test_send_file_headers_with_disposition_as_a_symbol
+ options = {
+ :type => Mime::PNG,
+ :disposition => :disposition,
+ :filename => 'filename'
+ }
+
+ @controller.headers = {}
+ @controller.send(:send_file_headers!, options)
+ assert_equal 'disposition; filename="filename"', @controller.headers['Content-Disposition']
+ end
+
def test_send_file_headers_with_mime_lookup_with_symbol
options = {
:type => :png
@@ -138,7 +150,7 @@ class SendFileTest < ActionController::TestCase
@controller.headers = {}
assert_raise(ArgumentError){ @controller.send(:send_file_headers!, options) }
end
-
+
def test_send_file_headers_guess_type_from_extension
{
'image.png' => 'image/png',
diff --git a/actionpack/test/dispatch/best_standards_support_test.rb b/actionpack/test/dispatch/best_standards_support_test.rb
new file mode 100644
index 0000000000..0737c40a39
--- /dev/null
+++ b/actionpack/test/dispatch/best_standards_support_test.rb
@@ -0,0 +1,34 @@
+require 'abstract_unit'
+
+class BestStandardsSupportTest < ActiveSupport::TestCase
+ def test_with_best_standards_support
+ _, headers, _ = app(true, {}).call({})
+ assert_equal "IE=Edge,chrome=1", headers["X-UA-Compatible"]
+ end
+
+ def test_with_builtin_best_standards_support
+ _, headers, _ = app(:builtin, {}).call({})
+ assert_equal "IE=Edge", headers["X-UA-Compatible"]
+ end
+
+ def test_without_best_standards_support
+ _, headers, _ = app(false, {}).call({})
+ assert_equal nil, headers["X-UA-Compatible"]
+ end
+
+ def test_appends_to_app_headers
+ app_headers = { "X-UA-Compatible" => "requiresActiveX=true" }
+ _, headers, _ = app(true, app_headers).call({})
+
+ expects = "requiresActiveX=true,IE=Edge,chrome=1"
+ assert_equal expects, headers["X-UA-Compatible"]
+ end
+
+ private
+
+ def app(type, headers)
+ app = proc { [200, headers, "response"] }
+ ActionDispatch::BestStandardsSupport.new(app, type)
+ end
+
+end
diff --git a/actionpack/test/dispatch/prefix_generation_test.rb b/actionpack/test/dispatch/prefix_generation_test.rb
index bd5b5edab0..88dc2c093b 100644
--- a/actionpack/test/dispatch/prefix_generation_test.rb
+++ b/actionpack/test/dispatch/prefix_generation_test.rb
@@ -248,6 +248,11 @@ module TestGenerationPrefix
assert_equal "/something/", app_object.root_path
end
+ test "[OBJECT] generating application's route includes default_url_options[:trailing_slash]" do
+ RailsApplication.routes.default_url_options[:trailing_slash] = true
+ assert_equal "/awesome/blog/posts", engine_object.posts_path
+ end
+
test "[OBJECT] generating engine's route with url_for" do
path = engine_object.url_for(:controller => "inside_engine_generating",
:action => "show",
diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb
index 5b3d38c48c..56431b4daf 100644
--- a/actionpack/test/dispatch/request_test.rb
+++ b/actionpack/test/dispatch/request_test.rb
@@ -530,6 +530,13 @@ class RequestTest < ActiveSupport::TestCase
assert_equal Mime::XML, request.negotiate_mime([Mime::XML, Mime::CSV])
end
+ test "raw_post rewinds rack.input if RAW_POST_DATA is nil" do
+ request = stub_request('rack.input' => StringIO.new("foo"),
+ 'CONTENT_LENGTH' => 3)
+ assert_equal "foo", request.raw_post
+ assert_equal "foo", request.env['rack.input'].read
+ end
+
test "process parameter filter" do
test_hashes = [
[{'foo'=>'bar'},{'foo'=>'bar'},%w'food'],
diff --git a/actionpack/test/dispatch/routing/route_set_test.rb b/actionpack/test/dispatch/routing/route_set_test.rb
new file mode 100644
index 0000000000..629b8ed8bd
--- /dev/null
+++ b/actionpack/test/dispatch/routing/route_set_test.rb
@@ -0,0 +1,86 @@
+require 'abstract_unit'
+
+module ActionDispatch
+ module Routing
+ class RouteSetTest < ActiveSupport::TestCase
+ class SimpleApp
+ def initialize(response)
+ @response = response
+ end
+
+ def call(env)
+ [ 200, { 'Content-Type' => 'text/plain' }, [response] ]
+ end
+ end
+
+ setup do
+ @set = RouteSet.new
+ end
+
+ test "url helpers are added when route is added" do
+ draw do
+ get 'foo', :to => SimpleApp.new('foo#index')
+ end
+
+ assert_equal '/foo', url_helpers.foo_path
+ assert_raises NoMethodError do
+ assert_equal '/bar', url_helpers.bar_path
+ end
+
+ draw do
+ get 'foo', :to => SimpleApp.new('foo#index')
+ get 'bar', :to => SimpleApp.new('bar#index')
+ end
+
+ assert_equal '/foo', url_helpers.foo_path
+ assert_equal '/bar', url_helpers.bar_path
+ end
+
+ test "url helpers are updated when route is updated" do
+ draw do
+ get 'bar', :to => SimpleApp.new('bar#index'), :as => :bar
+ end
+
+ assert_equal '/bar', url_helpers.bar_path
+
+ draw do
+ get 'baz', :to => SimpleApp.new('baz#index'), :as => :bar
+ end
+
+ assert_equal '/baz', url_helpers.bar_path
+ end
+
+ test "url helpers are removed when route is removed" do
+ draw do
+ get 'foo', :to => SimpleApp.new('foo#index')
+ get 'bar', :to => SimpleApp.new('bar#index')
+ end
+
+ assert_equal '/foo', url_helpers.foo_path
+ assert_equal '/bar', url_helpers.bar_path
+
+ draw do
+ get 'foo', :to => SimpleApp.new('foo#index')
+ end
+
+ assert_equal '/foo', url_helpers.foo_path
+ assert_raises NoMethodError do
+ assert_equal '/bar', url_helpers.bar_path
+ end
+ end
+
+ private
+ def clear!
+ @set.clear!
+ end
+
+ def draw(&block)
+ @set.draw(&block)
+ end
+
+ def url_helpers
+ @set.url_helpers
+ end
+ end
+ end
+end
diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb
index e61b4e2d8f..46d16598f7 100644
--- a/actionpack/test/dispatch/routing_test.rb
+++ b/actionpack/test/dispatch/routing_test.rb
@@ -887,6 +887,15 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
assert_equal original_options, options
end
+ def test_url_for_does_not_modify_controller
+ controller = '/projects'
+ options = {:controller => controller, :action => 'status', :only_path => true}
+ url = url_for(options)
+
+ assert_equal '/projects/status', url
+ assert_equal '/projects', controller
+ end
+
# tests the arguments modification free version of define_hash_access
def test_named_route_with_no_side_effects
original_options = { :host => 'test.host' }
diff --git a/actionpack/test/template/date_helper_i18n_test.rb b/actionpack/test/template/date_helper_i18n_test.rb
index d45215acfd..b0b407b473 100644
--- a/actionpack/test/template/date_helper_i18n_test.rb
+++ b/actionpack/test/template/date_helper_i18n_test.rb
@@ -36,16 +36,25 @@ class DateHelperDistanceOfTimeInWordsI18nTests < Test::Unit::TestCase
end
end
- def assert_distance_of_time_in_words_translates_key(passed, expected)
+ def test_distance_of_time_in_words_calls_i18n_with_custom_scope
+ {
+ [30.days, false] => [:'about_x_months', 1],
+ [60.days, false] => [:'x_months', 2],
+ }.each do |passed, expected|
+ assert_distance_of_time_in_words_translates_key(passed, expected, {:scope => :'datetime.distance_in_words_ago'})
+ end
+ end
+
+ def assert_distance_of_time_in_words_translates_key(passed, expected, options = {})
diff, include_seconds = *passed
key, count = *expected
to = @from + diff
- options = {:locale => 'en', :scope => :'datetime.distance_in_words'}
+ options = {:locale => 'en', :scope => :'datetime.distance_in_words'}.merge(options)
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, include_seconds, options)
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 cf707e1de5..e4f84f8dd7 100644
--- a/actionpack/test/template/date_helper_test.rb
+++ b/actionpack/test/template/date_helper_test.rb
@@ -128,12 +128,39 @@ class DateHelperTest < ActionView::TestCase
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)
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, true)
+ assert_equal "less than a minute", distance_of_time_in_words(40.seconds, 0, true)
+ assert_equal "less than a minute", distance_of_time_in_words(59.seconds, 0, true)
+ assert_equal "1 minute", distance_of_time_in_words(60.seconds, 0, true)
+ end
+
+ def test_distance_in_words_with_offset_datetimes
+ start_date = DateTime.new 1975, 1, 31, 0, 0, 0, '+6'
+ end_date = DateTime.new 1977, 1, 31, 0, 0, 0, '+6'
+ assert_equal("about 2 years", distance_of_time_in_words(start_date, end_date))
+
+ start_date = DateTime.new 1982, 12, 3, 0, 0, 0, '+6'
+ end_date = DateTime.new 2010, 11, 30, 0, 0, 0, '+6'
+ assert_equal("almost 28 years", distance_of_time_in_words(start_date, end_date))
+ end
+
def test_time_ago_in_words
assert_equal "about 1 year", time_ago_in_words(1.year.ago - 1.day)
end
diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb
index 19af01e2c8..49a325af79 100644
--- a/actionpack/test/template/form_helper_test.rb
+++ b/actionpack/test/template/form_helper_test.rb
@@ -393,6 +393,19 @@ class FormHelperTest < ActionView::TestCase
)
end
+ def test_check_box_with_multiple_behavior_and_index
+ @post.comment_ids = [2,3]
+ assert_dom_equal(
+ '<input name="post[foo][comment_ids][]" type="hidden" value="0" /><input id="post_foo_comment_ids_1" name="post[foo][comment_ids][]" type="checkbox" value="1" />',
+ check_box("post", "comment_ids", { :multiple => true, :index => "foo" }, 1)
+ )
+ assert_dom_equal(
+ '<input name="post[bar][comment_ids][]" type="hidden" value="0" /><input checked="checked" id="post_bar_comment_ids_3" name="post[bar][comment_ids][]" type="checkbox" value="3" />',
+ check_box("post", "comment_ids", { :multiple => true, :index => "bar" }, 3)
+ )
+
+ end
+
def test_checkbox_disabled_disables_hidden_field
assert_dom_equal(
'<input name="post[secret]" type="hidden" value="0" disabled="disabled"/><input checked="checked" disabled="disabled" id="post_secret" name="post[secret]" type="checkbox" value="1" />',
diff --git a/actionpack/test/template/render_test.rb b/actionpack/test/template/render_test.rb
index bfeb6aee1a..b907e3297b 100644
--- a/actionpack/test/template/render_test.rb
+++ b/actionpack/test/template/render_test.rb
@@ -336,7 +336,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
@@ -406,6 +406,11 @@ module RenderTestCases
@view.render(:partial => 'test/partial_with_layout_block_content', :layout => 'test/layout_for_partial', :locals => { :name => 'Foo!'})
end
+ def test_render_partial_with_layout_raises_descriptive_error
+ e = assert_raises(ActionView::MissingTemplate) { @view.render(:partial => 'test/partial', :layout => true) }
+ assert_match "Missing partial /true with", e.message
+ end
+
def test_render_with_nested_layout
assert_equal %(<title>title</title>\n\n<div id="column">column</div>\n<div id="content">content</div>\n),
@view.render(:file => "test/nested_layout", :layout => "layouts/yield")
diff --git a/actionpack/test/template/sprockets_helper_test.rb b/actionpack/test/template/sprockets_helper_test.rb
index 72d03e43e9..e944cfaee3 100644
--- a/actionpack/test/template/sprockets_helper_test.rb
+++ b/actionpack/test/template/sprockets_helper_test.rb
@@ -1,7 +1,7 @@
require 'abstract_unit'
require 'sprockets'
require 'sprockets/helpers/rails_helper'
-require 'mocha'
+require 'mocha/setup'
class SprocketsHelperTest < ActionView::TestCase
include Sprockets::Helpers::RailsHelper
diff --git a/actionpack/test/template/sprockets_helper_with_routes_test.rb b/actionpack/test/template/sprockets_helper_with_routes_test.rb
index bcbd81a7dd..bc253ea0fd 100644
--- a/actionpack/test/template/sprockets_helper_with_routes_test.rb
+++ b/actionpack/test/template/sprockets_helper_with_routes_test.rb
@@ -1,7 +1,7 @@
require 'abstract_unit'
require 'sprockets'
require 'sprockets/helpers/rails_helper'
-require 'mocha'
+require 'mocha/setup'
class SprocketsHelperWithRoutesTest < ActionView::TestCase
include Sprockets::Helpers::RailsHelper
@@ -54,4 +54,4 @@ class SprocketsHelperWithRoutesTest < ActionView::TestCase
stylesheet_link_tag(:application)
end
-end \ No newline at end of file
+end
diff --git a/actionpack/test/template/template_test.rb b/actionpack/test/template/template_test.rb
index 5880eb2bd4..56943381d8 100644
--- a/actionpack/test/template/template_test.rb
+++ b/actionpack/test/template/template_test.rb
@@ -25,6 +25,10 @@ class TestERBTemplate < ActiveSupport::TestCase
"Hello"
end
+ def apostrophe
+ "l'apostrophe"
+ end
+
def partial
ActionView::Template.new(
"<%= @virtual_path %>",
@@ -47,7 +51,7 @@ class TestERBTemplate < ActiveSupport::TestCase
end
end
- def new_template(body = "<%= hello %>", details = {})
+ def new_template(body = "<%= hello %>", details = { :format => :html })
ActionView::Template.new(body, "hello template", ERBHandler, {:virtual_path => "hello"}.merge!(details))
end
@@ -64,6 +68,16 @@ class TestERBTemplate < ActiveSupport::TestCase
assert_equal "Hello", render
end
+ def test_basic_template_does_html_escape
+ @template = new_template("<%= apostrophe %>")
+ assert_equal "l&#x27;apostrophe", render
+ end
+
+ def test_text_template_does_not_html_escape
+ @template = new_template("<%= apostrophe %> <%== apostrophe %>", :format => :text)
+ assert_equal "l'apostrophe l'apostrophe", render
+ end
+
def test_template_loses_its_source_after_rendering
@template = new_template
render