aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack')
-rw-r--r--actionpack/CHANGELOG4
-rw-r--r--actionpack/lib/abstract_controller/callbacks.rb32
-rw-r--r--actionpack/lib/action_controller/metal/mime_responds.rb2
-rw-r--r--actionpack/lib/action_controller/metal/testing.rb9
-rw-r--r--actionpack/lib/action_controller/test_case.rb5
-rw-r--r--actionpack/lib/action_dispatch/http/request.rb21
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb5
-rw-r--r--actionpack/lib/action_dispatch/routing/route.rb3
-rw-r--r--actionpack/lib/action_dispatch/testing/test_process.rb2
-rw-r--r--actionpack/lib/action_view/helpers/asset_tag_helper.rb8
-rw-r--r--actionpack/lib/action_view/helpers/capture_helper.rb3
-rw-r--r--actionpack/lib/action_view/helpers/date_helper.rb2
-rw-r--r--actionpack/lib/action_view/helpers/form_helper.rb24
-rw-r--r--actionpack/lib/action_view/helpers/number_helper.rb31
-rw-r--r--actionpack/lib/action_view/renderer/partial_renderer.rb7
-rw-r--r--actionpack/lib/action_view/template/handlers/erb.rb7
-rw-r--r--actionpack/test/activerecord/active_record_store_test.rb20
-rw-r--r--actionpack/test/controller/filters_test.rb81
-rw-r--r--actionpack/test/controller/mime_responds_test.rb16
-rw-r--r--actionpack/test/controller/new_base/bare_metal_test.rb7
-rw-r--r--actionpack/test/controller/new_base/render_template_test.rb10
-rw-r--r--actionpack/test/dispatch/cookies_test.rb18
-rw-r--r--actionpack/test/dispatch/routing_test.rb31
-rw-r--r--actionpack/test/fixtures/layouts/_partial_and_yield.erb2
-rw-r--r--actionpack/test/fixtures/layouts/_yield_only.erb1
-rw-r--r--actionpack/test/fixtures/layouts/_yield_with_params.erb1
-rw-r--r--actionpack/test/fixtures/layouts/yield_with_render_partial_inside.erb2
-rw-r--r--actionpack/test/fixtures/test/_partial_with_layout.erb2
-rw-r--r--actionpack/test/fixtures/test/_partial_with_layout_block_content.erb4
-rw-r--r--actionpack/test/fixtures/test/_partial_with_layout_block_partial.erb4
-rw-r--r--actionpack/test/fixtures/test/_partial_with_partial.erb2
-rw-r--r--actionpack/test/lib/controller/fake_models.rb10
-rw-r--r--actionpack/test/template/asset_tag_helper_test.rb11
-rw-r--r--actionpack/test/template/capture_helper_test.rb10
-rw-r--r--actionpack/test/template/date_helper_test.rb41
-rw-r--r--actionpack/test/template/form_helper_test.rb21
-rw-r--r--actionpack/test/template/number_helper_i18n_test.rb5
-rw-r--r--actionpack/test/template/number_helper_test.rb4
-rw-r--r--actionpack/test/template/render_test.rb45
-rw-r--r--actionpack/test/template/url_helper_test.rb7
40 files changed, 454 insertions, 66 deletions
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG
index 2d133ca0b2..db02beee35 100644
--- a/actionpack/CHANGELOG
+++ b/actionpack/CHANGELOG
@@ -23,6 +23,10 @@
* Add Rack::Cache to the default stack. Create a Rails store that delegates to the Rails cache, so by default, whatever caching layer you are using will be used for HTTP caching. Note that Rack::Cache will be used if you use #expires_in, #fresh_when or #stale with :public => true. Otherwise, the caching rules will apply to the browser only. [Yehuda Katz, Carl Lerche]
+*Rails 3.0.2 (unreleased)*
+
+* The helper number_to_currency accepts a new :negative_format option to be able to configure how to render negative amounts. [Don Wilson]
+
*Rails 3.0.1 (October 15, 2010)*
* No Changes, just a version bump.
diff --git a/actionpack/lib/abstract_controller/callbacks.rb b/actionpack/lib/abstract_controller/callbacks.rb
index 7b0d80614d..f169ab7c3a 100644
--- a/actionpack/lib/abstract_controller/callbacks.rb
+++ b/actionpack/lib/abstract_controller/callbacks.rb
@@ -81,27 +81,29 @@ module AbstractController
class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
# Append a before, after or around filter. See _insert_callbacks
# for details on the allowed parameters.
- def #{filter}_filter(*names, &blk) # def before_filter(*names, &blk)
- _insert_callbacks(names, blk) do |name, options| # _insert_callbacks(names, blk) do |name, options}
- set_callback(:process_action, :#{filter}, name, options) # set_callback(:process_action, :before_filter, name, options)
- end # end
- end # end
+ def #{filter}_filter(*names, &blk)
+ _insert_callbacks(names, blk) do |name, options|
+ options[:if] = (Array.wrap(options[:if]) << "!halted") if #{filter == :after}
+ set_callback(:process_action, :#{filter}, name, options)
+ end
+ end
# Prepend a before, after or around filter. See _insert_callbacks
# for details on the allowed parameters.
- def prepend_#{filter}_filter(*names, &blk) # def prepend_before_filter(*names, &blk)
- _insert_callbacks(names, blk) do |name, options| # _insert_callbacks(names, blk) do |name, options|
- set_callback(:process_action, :#{filter}, name, options.merge(:prepend => true)) # set_callback(:process_action, :before, name, options.merge(:prepend => true))
- end # end
- end # end
+ def prepend_#{filter}_filter(*names, &blk)
+ _insert_callbacks(names, blk) do |name, options|
+ options[:if] = (Array.wrap(options[:if]) << "!halted") if #{filter == :after}
+ set_callback(:process_action, :#{filter}, name, options.merge(:prepend => true))
+ end
+ end
# Skip a before, after or around filter. See _insert_callbacks
# for details on the allowed parameters.
- def skip_#{filter}_filter(*names, &blk) # def skip_before_filter(*names, &blk)
- _insert_callbacks(names, blk) do |name, options| # _insert_callbacks(names, blk) do |name, options|
- skip_callback(:process_action, :#{filter}, name, options) # skip_callback(:process_action, :before, name, options)
- end # end
- end # end
+ def skip_#{filter}_filter(*names, &blk)
+ _insert_callbacks(names, blk) do |name, options|
+ skip_callback(:process_action, :#{filter}, name, options)
+ end
+ end
# *_filter is the same as append_*_filter
alias_method :append_#{filter}_filter, :#{filter}_filter
diff --git a/actionpack/lib/action_controller/metal/mime_responds.rb b/actionpack/lib/action_controller/metal/mime_responds.rb
index c6d4c6d936..f7dd0dcb69 100644
--- a/actionpack/lib/action_controller/metal/mime_responds.rb
+++ b/actionpack/lib/action_controller/metal/mime_responds.rb
@@ -227,7 +227,7 @@ module ActionController #:nodoc:
"controller responds to in the class level" if self.class.mimes_for_respond_to.empty?
if response = retrieve_response_from_mimes(&block)
- options = resources.extract_options!
+ options = resources.size == 1 ? {} : resources.extract_options!
options.merge!(:default_response => response)
(options.delete(:responder) || self.class.responder).call(self, resources, options)
end
diff --git a/actionpack/lib/action_controller/metal/testing.rb b/actionpack/lib/action_controller/metal/testing.rb
index 4b8c452d50..f4efeb33ba 100644
--- a/actionpack/lib/action_controller/metal/testing.rb
+++ b/actionpack/lib/action_controller/metal/testing.rb
@@ -14,18 +14,9 @@ module ActionController
cookies.write(@_response)
end
@_response.prepare!
- set_test_assigns
ret
end
- def set_test_assigns
- @assigns = {}
- (instance_variable_names - self.class.protected_instance_variables).each do |var|
- name, value = var[1..-1], instance_variable_get(var)
- @assigns[name] = value
- end
- end
-
# TODO : Rewrite tests using controller.headers= to use Rack env
def headers=(new_headers)
@_response ||= ActionDispatch::Response.new
diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb
index 0c26071379..2b2f647d32 100644
--- a/actionpack/lib/action_controller/test_case.rb
+++ b/actionpack/lib/action_controller/test_case.rb
@@ -411,8 +411,9 @@ module ActionController
@controller.request = @request
@controller.params.merge!(parameters)
build_request_uri(action, parameters)
- Base.class_eval { include Testing }
+ @controller.class.class_eval { include Testing }
@controller.process_with_new_base_test(@request, @response)
+ @assigns = @controller.respond_to?(:view_assigns) ? @controller.view_assigns : {}
@request.session.delete('flash') if @request.session['flash'].blank?
@response
end
@@ -448,7 +449,7 @@ module ActionController
def build_request_uri(action, parameters)
unless @request.env["PATH_INFO"]
- options = @controller.__send__(:url_options).merge(parameters)
+ options = @controller.respond_to?(:url_options) ? @controller.__send__(:url_options).merge(parameters) : parameters
options.update(
:only_path => true,
:action => action,
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index 55a3166f6d..08f30e068d 100644
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -4,6 +4,7 @@ require 'strscan'
require 'active_support/core_ext/hash/indifferent_access'
require 'active_support/core_ext/string/access'
+require 'active_support/inflector'
require 'action_dispatch/http/headers'
module ActionDispatch
@@ -44,8 +45,24 @@ module ActionDispatch
@env.key?(key)
end
- HTTP_METHODS = %w(get head put post delete options)
- HTTP_METHOD_LOOKUP = HTTP_METHODS.inject({}) { |h, m| h[m] = h[m.upcase] = m.to_sym; h }
+ # List of HTTP request methods from the following RFCs:
+ # Hypertext Transfer Protocol -- HTTP/1.1 (http://www.ietf.org/rfc/rfc2616.txt)
+ # HTTP Extensions for Distributed Authoring -- WEBDAV (http://www.ietf.org/rfc/rfc2518.txt)
+ # Versioning Extensions to WebDAV (http://www.ietf.org/rfc/rfc3253.txt)
+ # Ordered Collections Protocol (WebDAV) (http://www.ietf.org/rfc/rfc3648.txt)
+ # Web Distributed Authoring and Versioning (WebDAV) Access Control Protocol (http://www.ietf.org/rfc/rfc3744.txt)
+ # Web Distributed Authoring and Versioning (WebDAV) SEARCH (http://www.ietf.org/rfc/rfc5323.txt)
+ # PATCH Method for HTTP (http://www.ietf.org/rfc/rfc5789.txt)
+ RFC2616 = %w(OPTIONS GET HEAD POST PUT DELETE TRACE CONNECT)
+ RFC2518 = %w(PROPFIND PROPPATCH MKCOL COPY MOVE LOCK UNLOCK)
+ RFC3253 = %w(VERSION-CONTROL REPORT CHECKOUT CHECKIN UNCHECKOUT MKWORKSPACE UPDATE LABEL MERGE BASELINE-CONTROL MKACTIVITY)
+ RFC3648 = %w(ORDERPATCH)
+ RFC3744 = %w(ACL)
+ RFC5323 = %w(SEARCH)
+ RFC5789 = %w(PATCH)
+
+ HTTP_METHODS = RFC2616 + RFC2518 + RFC3253 + RFC3648 + RFC3744 + RFC5323 + RFC5789
+ HTTP_METHOD_LOOKUP = Hash.new { |h, m| h[m] = m.underscore.to_sym if HTTP_METHODS.include?(m) }
# Returns the HTTP \method that the application should see.
# In the case where the \method was overridden by a middleware
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index 2eb2af7a11..63a22ad105 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -1,6 +1,7 @@
require 'erb'
require 'active_support/core_ext/hash/except'
require 'active_support/core_ext/object/blank'
+require 'active_support/inflector'
module ActionDispatch
module Routing
@@ -186,8 +187,8 @@ module ActionDispatch
def request_method_condition
if via = @options[:via]
- via = Array(via).map { |m| m.to_s.upcase }
- { :request_method => Regexp.union(*via) }
+ via = Array(via).map { |m| m.to_s.dasherize.upcase }
+ { :request_method => %r[^#{via.join('|')}$] }
else
{ }
end
diff --git a/actionpack/lib/action_dispatch/routing/route.rb b/actionpack/lib/action_dispatch/routing/route.rb
index f91a48e16c..08a8408f25 100644
--- a/actionpack/lib/action_dispatch/routing/route.rb
+++ b/actionpack/lib/action_dispatch/routing/route.rb
@@ -30,7 +30,8 @@ module ActionDispatch
if method = conditions[:request_method]
case method
when Regexp
- method.source.upcase
+ source = method.source.upcase
+ source =~ /\A\^[-A-Z|]+\$\Z/ ? source[1..-2] : source
else
method.to_s.upcase
end
diff --git a/actionpack/lib/action_dispatch/testing/test_process.rb b/actionpack/lib/action_dispatch/testing/test_process.rb
index c56ebc6438..16f3674164 100644
--- a/actionpack/lib/action_dispatch/testing/test_process.rb
+++ b/actionpack/lib/action_dispatch/testing/test_process.rb
@@ -22,7 +22,7 @@ module ActionDispatch
end
def cookies
- @request.cookies.merge(@response.cookies)
+ HashWithIndifferentAccess.new(@request.cookies.merge(@response.cookies))
end
def redirect_to_url
diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
index a728fde748..db5f5f301a 100644
--- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
@@ -878,7 +878,7 @@ module ActionView
end
def join_asset_file_contents(paths)
- paths.collect { |path| File.read(asset_file_path!(path)) }.join("\n\n")
+ paths.collect { |path| File.read(asset_file_path!(path, true)) }.join("\n\n")
end
def write_asset_file_contents(joined_asset_path, asset_paths)
@@ -896,8 +896,10 @@ module ActionView
File.join(config.assets_dir, path.split('?').first)
end
- def asset_file_path!(path)
- unless is_uri?(path)
+ def asset_file_path!(path, error_if_file_is_uri = false)
+ if is_uri?(path)
+ raise(Errno::ENOENT, "Asset file #{path} is uri and cannot be merged into single file") if error_if_file_is_uri
+ else
absolute_path = asset_file_path(path)
raise(Errno::ENOENT, "Asset file not found at '#{absolute_path}'" ) unless File.exist?(absolute_path)
return absolute_path
diff --git a/actionpack/lib/action_view/helpers/capture_helper.rb b/actionpack/lib/action_view/helpers/capture_helper.rb
index 0401e6a09b..c88bd1efd5 100644
--- a/actionpack/lib/action_view/helpers/capture_helper.rb
+++ b/actionpack/lib/action_view/helpers/capture_helper.rb
@@ -1,4 +1,5 @@
require 'active_support/core_ext/object/blank'
+require 'active_support/core_ext/string/output_safety'
module ActionView
# = Action View Capture Helper
@@ -38,7 +39,7 @@ module ActionView
value = nil
buffer = with_output_buffer { value = yield(*args) }
if string = buffer.presence || value and string.is_a?(String)
- string
+ ERB::Util.html_escape string
end
end
diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb
index c1214bc44e..875ec9b77b 100644
--- a/actionpack/lib/action_view/helpers/date_helper.rb
+++ b/actionpack/lib/action_view/helpers/date_helper.rb
@@ -882,6 +882,8 @@ module ActionView
# Returns the separator for a given datetime component
def separator(type)
case type
+ when :year
+ @options[:discard_year] ? "" : @options[:date_separator]
when :month
@options[:discard_month] ? "" : @options[:date_separator]
when :day
diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb
index d6e175c7e8..8c300ec745 100644
--- a/actionpack/lib/action_view/helpers/form_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_helper.rb
@@ -112,6 +112,7 @@ module ActionView
# <%= f.text_field :version %><br />
# <%= f.label :author, 'Author' %>:
# <%= f.text_field :author %><br />
+ # <%= f.submit %>
# <% end %>
#
# There, +form_for+ is able to generate the rest of RESTful form
@@ -129,6 +130,7 @@ module ActionView
# Last name : <%= f.text_field :last_name %><br />
# Biography : <%= f.text_area :biography %><br />
# Admin? : <%= f.check_box :admin %><br />
+ # <%= f.submit %>
# <% end %>
#
# There, the argument is a symbol or string with the name of the
@@ -160,6 +162,7 @@ module ActionView
# Last name : <%= f.text_field :last_name %>
# Biography : <%= text_area :person, :biography %>
# Admin? : <%= check_box_tag "person[admin]", @person.company.admin? %>
+ # <%= f.submit %>
# <% end %>
#
# This also works for the methods in FormOptionHelper and DateHelper that
@@ -269,8 +272,9 @@ module ActionView
# <%= form_for @person, :url => { :action => "create" }, :builder => LabellingFormBuilder do |f| %>
# <%= f.text_field :first_name %>
# <%= f.text_field :last_name %>
- # <%= text_area :person, :biography %>
- # <%= check_box_tag "person[admin]", @person.company.admin? %>
+ # <%= f.text_area :biography %>
+ # <%= f.check_box :admin %>
+ # <%= f.submit %>
# <% end %>
#
# In this case, if you use this:
@@ -294,10 +298,9 @@ module ActionView
#
# If you don't need to attach a form to a model instance, then check out
# FormTagHelper#form_tag.
- def form_for(record, options = nil, &proc)
+ def form_for(record, options = {}, &proc)
raise ArgumentError, "Missing block" unless block_given?
- options ||= {}
options[:html] ||= {}
case record
@@ -348,6 +351,8 @@ module ActionView
# <%= fields_for @person.permission do |permission_fields| %>
# Admin? : <%= permission_fields.check_box :admin %>
# <% end %>
+ #
+ # <%= f.submit %>
# <% end %>
#
# ...or if you have an object that needs to be represented as a different
@@ -409,6 +414,7 @@ module ActionView
# Street : <%= address_fields.text_field :street %>
# Zip code: <%= address_fields.text_field :zip_code %>
# <% end %>
+ # ...
# <% end %>
#
# When address is already an association on a Person you can use
@@ -438,6 +444,7 @@ module ActionView
# ...
# Delete: <%= address_fields.check_box :_destroy %>
# <% end %>
+ # ...
# <% end %>
#
# ==== One-to-many
@@ -467,6 +474,7 @@ module ActionView
# Name: <%= project_fields.text_field :name %>
# <% end %>
# <% end %>
+ # ...
# <% end %>
#
# It's also possible to specify the instance to be used:
@@ -480,6 +488,7 @@ module ActionView
# <% end %>
# <% end %>
# <% end %>
+ # ...
# <% end %>
#
# Or a collection to be used:
@@ -489,6 +498,7 @@ module ActionView
# <%= person_form.fields_for :projects, @active_projects do |project_fields| %>
# Name: <%= project_fields.text_field :name %>
# <% end %>
+ # ...
# <% end %>
#
# When projects is already an association on Person you can use
@@ -518,6 +528,7 @@ module ActionView
# <%= person_form.fields_for :projects do |project_fields| %>
# Delete: <%= project_fields.check_box :_destroy %>
# <% end %>
+ # ...
# <% end %>
def fields_for(record, record_object = nil, options = nil, &block)
capture(instantiate_builder(record, record_object, options, &block), &block)
@@ -1206,6 +1217,7 @@ module ActionView
self.multipart = true
@template.file_field(@object_name, method, objectify_options(options))
end
+
# Add the submit button for the given form. When no value is given, it checks
# if the object is a new resource or not to create the proper label:
#
@@ -1278,11 +1290,11 @@ module ActionView
if association.respond_to?(:persisted?)
association = [association] if @object.send(association_name).is_a?(Array)
- elsif !association.is_a?(Array)
+ elsif !association.respond_to?(:to_ary)
association = @object.send(association_name)
end
- if association.is_a?(Array)
+ if association.respond_to?(:to_ary)
explicit_child_index = options[:child_index]
output = ActiveSupport::SafeBuffer.new
association.each do |child|
diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb
index 1488e72c6e..a9400c347f 100644
--- a/actionpack/lib/action_view/helpers/number_helper.rb
+++ b/actionpack/lib/action_view/helpers/number_helper.rb
@@ -15,7 +15,7 @@ module ActionView
# unchanged if can't be converted into a valid number.
module NumberHelper
- DEFAULT_CURRENCY_VALUES = { :format => "%u%n", :unit => "$", :separator => ".", :delimiter => ",",
+ DEFAULT_CURRENCY_VALUES = { :format => "%u%n", :negative_format => "-%u%n", :unit => "$", :separator => ".", :delimiter => ",",
:precision => 2, :significant => false, :strip_insignificant_zeros => false }
# Raised when argument +number+ param given to the helpers is invalid and
@@ -81,15 +81,18 @@ module ActionView
# in the +options+ hash.
#
# ==== Options
- # * <tt>:locale</tt> - Sets the locale to be used for formatting (defaults to current locale).
- # * <tt>:precision</tt> - Sets the level of precision (defaults to 2).
- # * <tt>:unit</tt> - Sets the denomination of the currency (defaults to "$").
- # * <tt>:separator</tt> - Sets the separator between the units (defaults to ".").
- # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to ",").
- # * <tt>:format</tt> - Sets the format of the output string (defaults to "%u%n"). The field types are:
- #
- # %u The currency unit
- # %n The number
+ # * <tt>:locale</tt> - Sets the locale to be used for formatting (defaults to current locale).
+ # * <tt>:precision</tt> - Sets the level of precision (defaults to 2).
+ # * <tt>:unit</tt> - Sets the denomination of the currency (defaults to "$").
+ # * <tt>:separator</tt> - Sets the separator between the units (defaults to ".").
+ # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to ",").
+ # * <tt>:format</tt> - Sets the format for non-negative numbers (defaults to "%u%n").
+ # Fields are <tt>%u</tt> for the currency, and <tt>%n</tt>
+ # for the number.
+ # * <tt>:negative_format</tt> - Sets the format for negative numbers (defaults to prepending
+ # an hyphen to the formatted number given by <tt>:format</tt>).
+ # Accepts the same fields than <tt>:format</tt>, except
+ # <tt>%n</tt> is here the absolute value of the number.
#
# ==== Examples
# number_to_currency(1234567890.50) # => $1,234,567,890.50
@@ -97,6 +100,8 @@ module ActionView
# number_to_currency(1234567890.506, :precision => 3) # => $1,234,567,890.506
# number_to_currency(1234567890.506, :locale => :fr) # => 1 234 567 890,506 €
#
+ # number_to_currency(1234567890.50, :negative_format => "(%u%n)")
+ # # => ($1,234,567,890.51)
# number_to_currency(1234567890.50, :unit => "&pound;", :separator => ",", :delimiter => "")
# # => &pound;1234567890,50
# number_to_currency(1234567890.50, :unit => "&pound;", :separator => ",", :delimiter => "", :format => "%n %u")
@@ -110,11 +115,17 @@ module ActionView
currency = I18n.translate(:'number.currency.format', :locale => options[:locale], :default => {})
defaults = DEFAULT_CURRENCY_VALUES.merge(defaults).merge!(currency)
+ defaults[:negative_format] = "-" + options[:format] if options[:format]
options = defaults.merge!(options)
unit = options.delete(:unit)
format = options.delete(:format)
+ if number.to_f < 0
+ format = options.delete(:negative_format)
+ number = number.respond_to?("abs") ? number.abs : number.sub(/^-/, '')
+ end
+
begin
value = number_with_precision(number, options.merge(:raise => true))
format.gsub(/%n/, value).gsub(/%u/, unit).html_safe
diff --git a/actionpack/lib/action_view/renderer/partial_renderer.rb b/actionpack/lib/action_view/renderer/partial_renderer.rb
index c580397cad..317479ad4c 100644
--- a/actionpack/lib/action_view/renderer/partial_renderer.rb
+++ b/actionpack/lib/action_view/renderer/partial_renderer.rb
@@ -90,13 +90,14 @@ module ActionView
def collection
if @options.key?(:collection)
- @options[:collection] || []
+ collection = @options[:collection]
+ collection.respond_to?(:to_ary) ? collection.to_ary : []
end
end
def collection_from_object
if @object.respond_to?(:to_ary)
- @object
+ @object.to_ary
end
end
@@ -163,4 +164,4 @@ module ActionView
[variable, variable_counter]
end
end
-end \ No newline at end of file
+end
diff --git a/actionpack/lib/action_view/template/handlers/erb.rb b/actionpack/lib/action_view/template/handlers/erb.rb
index b827610456..0803114f44 100644
--- a/actionpack/lib/action_view/template/handlers/erb.rb
+++ b/actionpack/lib/action_view/template/handlers/erb.rb
@@ -15,6 +15,7 @@ module ActionView
super(value.to_s)
end
alias :append= :<<
+ alias :safe_append= :safe_concat
end
class Template
@@ -40,7 +41,11 @@ module ActionView
end
def add_expr_escaped(src, code)
- src << '@output_buffer.append= ' << escaped_expr(code) << ';'
+ if code =~ BLOCK_EXPR
+ src << "@output_buffer.safe_append= " << code
+ else
+ src << "@output_buffer.safe_concat((" << code << ").to_s);"
+ end
end
def add_postamble(src)
diff --git a/actionpack/test/activerecord/active_record_store_test.rb b/actionpack/test/activerecord/active_record_store_test.rb
index f5811a1530..7c595d1b89 100644
--- a/actionpack/test/activerecord/active_record_store_test.rb
+++ b/actionpack/test/activerecord/active_record_store_test.rb
@@ -27,6 +27,12 @@ class ActiveRecordStoreTest < ActionDispatch::IntegrationTest
head :ok
end
+ def renew
+ env["rack.session.options"][:renew] = true
+ session[:foo] = "baz"
+ head :ok
+ end
+
def rescue_action(e) raise end
end
@@ -64,6 +70,20 @@ class ActiveRecordStoreTest < ActionDispatch::IntegrationTest
end
end
end
+
+ define_method("test_renewing_with_#{class_name}_store") do
+ with_store class_name do
+ with_test_route_set do
+ get '/set_session_value'
+ assert_response :success
+ assert cookies['_session_id']
+
+ get '/renew'
+ assert_response :success
+ assert_not_equal [], headers['Set-Cookie']
+ end
+ end
+ end
end
def test_getting_nil_session_value
diff --git a/actionpack/test/controller/filters_test.rb b/actionpack/test/controller/filters_test.rb
index 3a8a37d967..68febf425d 100644
--- a/actionpack/test/controller/filters_test.rb
+++ b/actionpack/test/controller/filters_test.rb
@@ -78,7 +78,8 @@ class FilterTest < ActionController::TestCase
end
class RenderingController < ActionController::Base
- before_filter :render_something_else
+ before_filter :before_filter_rendering
+ after_filter :unreached_after_filter
def show
@ran_action = true
@@ -86,9 +87,59 @@ class FilterTest < ActionController::TestCase
end
private
- def render_something_else
+ def before_filter_rendering
+ @ran_filter ||= []
+ @ran_filter << "before_filter_rendering"
render :inline => "something else"
end
+
+ def unreached_after_filter
+ @ran_filter << "unreached_after_filter_after_render"
+ end
+ end
+
+ class RenderingForPrependAfterFilterController < RenderingController
+ prepend_after_filter :unreached_prepend_after_filter
+
+ private
+ def unreached_prepend_after_filter
+ @ran_filter << "unreached_preprend_after_filter_after_render"
+ end
+ end
+
+ class BeforeFilterRedirectionController < ActionController::Base
+ before_filter :before_filter_redirects
+ after_filter :unreached_after_filter
+
+ def show
+ @ran_action = true
+ render :inline => "ran show action"
+ end
+
+ def target_of_redirection
+ @ran_target_of_redirection = true
+ render :inline => "ran target_of_redirection action"
+ end
+
+ private
+ def before_filter_redirects
+ @ran_filter ||= []
+ @ran_filter << "before_filter_redirects"
+ redirect_to(:action => 'target_of_redirection')
+ end
+
+ def unreached_after_filter
+ @ran_filter << "unreached_after_filter_after_redirection"
+ end
+ end
+
+ class BeforeFilterRedirectionForPrependAfterFilterController < BeforeFilterRedirectionController
+ prepend_after_filter :unreached_prepend_after_filter_after_redirection
+
+ private
+ def unreached_prepend_after_filter_after_redirection
+ @ran_filter << "unreached_prepend_after_filter_after_redirection"
+ end
end
class ConditionalFilterController < ActionController::Base
@@ -625,6 +676,32 @@ class FilterTest < ActionController::TestCase
assert !assigns["ran_action"]
end
+ def test_before_filter_rendering_breaks_filtering_chain_for_after_filter
+ response = test_process(RenderingController)
+ assert_equal %w( before_filter_rendering ), assigns["ran_filter"]
+ assert !assigns["ran_action"]
+ end
+
+ def test_before_filter_redirects_breaks_filtering_chain_for_after_filter
+ response = test_process(BeforeFilterRedirectionController)
+ assert_response :redirect
+ assert_equal "http://test.host/filter_test/before_filter_redirection/target_of_redirection", redirect_to_url
+ assert_equal %w( before_filter_redirects ), assigns["ran_filter"]
+ end
+
+ def test_before_filter_rendering_breaks_filtering_chain_for_preprend_after_filter
+ response = test_process(RenderingForPrependAfterFilterController)
+ assert_equal %w( before_filter_rendering ), assigns["ran_filter"]
+ assert !assigns["ran_action"]
+ end
+
+ def test_before_filter_redirects_breaks_filtering_chain_for_preprend_after_filter
+ response = test_process(BeforeFilterRedirectionForPrependAfterFilterController)
+ assert_response :redirect
+ assert_equal "http://test.host/filter_test/before_filter_redirection_for_prepend_after_filter/target_of_redirection", redirect_to_url
+ assert_equal %w( before_filter_redirects ), assigns["ran_filter"]
+ end
+
def test_filters_with_mixed_specialization_run_in_order
assert_nothing_raised do
response = test_process(MixedSpecializationController, 'bar')
diff --git a/actionpack/test/controller/mime_responds_test.rb b/actionpack/test/controller/mime_responds_test.rb
index a898ef76e5..b6ce9f7d34 100644
--- a/actionpack/test/controller/mime_responds_test.rb
+++ b/actionpack/test/controller/mime_responds_test.rb
@@ -487,6 +487,10 @@ class RespondWithController < ActionController::Base
respond_with(resource)
end
+ def using_hash_resource
+ respond_with({:result => resource})
+ end
+
def using_resource_with_block
respond_with(resource) do |format|
format.csv { render :text => "CSV" }
@@ -587,6 +591,18 @@ class RespondWithControllerTest < ActionController::TestCase
end
end
+ def test_using_hash_resource
+ @request.accept = "application/xml"
+ get :using_hash_resource
+ assert_equal "application/xml", @response.content_type
+ assert_equal "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<hash>\n <name>david</name>\n</hash>\n", @response.body
+
+ @request.accept = "application/json"
+ get :using_hash_resource
+ assert_equal "application/json", @response.content_type
+ assert_equal %Q[{"result":["david",13]}], @response.body
+ end
+
def test_using_resource_with_block
@request.accept = "*/*"
get :using_resource_with_block
diff --git a/actionpack/test/controller/new_base/bare_metal_test.rb b/actionpack/test/controller/new_base/bare_metal_test.rb
index 44922cecff..543c02b2c5 100644
--- a/actionpack/test/controller/new_base/bare_metal_test.rb
+++ b/actionpack/test/controller/new_base/bare_metal_test.rb
@@ -39,4 +39,11 @@ module BareMetalTest
assert_equal 404, status
end
end
+
+ class BareControllerTest < ActionController::TestCase
+ test "GET index" do
+ get :index
+ assert_equal "Hello world", @response.body
+ end
+ end
end
diff --git a/actionpack/test/controller/new_base/render_template_test.rb b/actionpack/test/controller/new_base/render_template_test.rb
index d31193a063..9899036fe8 100644
--- a/actionpack/test/controller/new_base/render_template_test.rb
+++ b/actionpack/test/controller/new_base/render_template_test.rb
@@ -9,6 +9,7 @@ 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>' %>",
"test/with_json.html.erb" => "<%= render :template => 'test/with_json.json' %>",
"test/with_json.json.erb" => "<%= render :template => 'test/final' %>",
"test/final.json.erb" => "{ final: json }",
@@ -51,6 +52,10 @@ module RenderTemplate
render :template => "with_raw"
end
+ def with_implicit_raw
+ render :template => "with_implicit_raw"
+ end
+
def with_error
render :template => "test/with_error"
end
@@ -99,6 +104,11 @@ module RenderTemplate
assert_body "Hello <strong>this is raw</strong>"
assert_status 200
+
+ get :with_implicit_raw
+
+ assert_body "Hello <strong>this is also raw</strong>"
+ assert_status 200
end
test "rendering a template with renders another template with other format that renders other template in the same format" do
diff --git a/actionpack/test/dispatch/cookies_test.rb b/actionpack/test/dispatch/cookies_test.rb
index faeae91f6b..5ec7f12cc1 100644
--- a/actionpack/test/dispatch/cookies_test.rb
+++ b/actionpack/test/dispatch/cookies_test.rb
@@ -94,6 +94,16 @@ class CookiesTest < ActionController::TestCase
cookies.delete(:user_name, :domain => :all)
head :ok
end
+
+ def symbol_key
+ cookies[:user_name] = "david"
+ head :ok
+ end
+
+ def string_key
+ cookies['user_name'] = "david"
+ head :ok
+ end
end
tests TestController
@@ -291,6 +301,14 @@ class CookiesTest < ActionController::TestCase
assert_cookie_header "user_name=; domain=.nextangle.com; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT"
end
+ def test_cookies_hash_is_indifferent_access
+ [:symbol_key, :string_key].each do |cookie_key|
+ get cookie_key
+ assert_equal "david", cookies[:user_name]
+ assert_equal "david", cookies['user_name']
+ end
+ end
+
private
def assert_cookie_header(expected)
header = @response.headers["Set-Cookie"]
diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb
index 5c188a60c7..0ac8c249cb 100644
--- a/actionpack/test/dispatch/routing_test.rb
+++ b/actionpack/test/dispatch/routing_test.rb
@@ -2255,3 +2255,34 @@ class TestDefaultScope < ActionDispatch::IntegrationTest
end
end
+class TestHttpMethods < ActionDispatch::IntegrationTest
+ RFC2616 = %w(OPTIONS GET HEAD POST PUT DELETE TRACE CONNECT)
+ RFC2518 = %w(PROPFIND PROPPATCH MKCOL COPY MOVE LOCK UNLOCK)
+ RFC3253 = %w(VERSION-CONTROL REPORT CHECKOUT CHECKIN UNCHECKOUT MKWORKSPACE UPDATE LABEL MERGE BASELINE-CONTROL MKACTIVITY)
+ RFC3648 = %w(ORDERPATCH)
+ RFC3744 = %w(ACL)
+ RFC5323 = %w(SEARCH)
+ RFC5789 = %w(PATCH)
+
+ def simple_app(response)
+ lambda { |env| [ 200, { 'Content-Type' => 'text/plain' }, [response] ] }
+ end
+
+ setup do
+ s = self
+ @app = ActionDispatch::Routing::RouteSet.new
+
+ @app.draw do
+ (RFC2616 + RFC2518 + RFC3253 + RFC3648 + RFC3744 + RFC5323 + RFC5789).each do |method|
+ match '/' => s.simple_app(method), :via => method.underscore.to_sym
+ end
+ end
+ end
+
+ (RFC2616 + RFC2518 + RFC3253 + RFC3648 + RFC3744 + RFC5323 + RFC5789).each do |method|
+ test "request method #{method.underscore} can be matched" do
+ get '/', nil, 'REQUEST_METHOD' => method
+ assert_equal method, @response.body
+ end
+ end
+end
diff --git a/actionpack/test/fixtures/layouts/_partial_and_yield.erb b/actionpack/test/fixtures/layouts/_partial_and_yield.erb
new file mode 100644
index 0000000000..74cc428ffa
--- /dev/null
+++ b/actionpack/test/fixtures/layouts/_partial_and_yield.erb
@@ -0,0 +1,2 @@
+<%= render :partial => 'test/partial' %>
+<%= yield %>
diff --git a/actionpack/test/fixtures/layouts/_yield_only.erb b/actionpack/test/fixtures/layouts/_yield_only.erb
new file mode 100644
index 0000000000..37f0bddbd7
--- /dev/null
+++ b/actionpack/test/fixtures/layouts/_yield_only.erb
@@ -0,0 +1 @@
+<%= yield %>
diff --git a/actionpack/test/fixtures/layouts/_yield_with_params.erb b/actionpack/test/fixtures/layouts/_yield_with_params.erb
new file mode 100644
index 0000000000..68e6557fb8
--- /dev/null
+++ b/actionpack/test/fixtures/layouts/_yield_with_params.erb
@@ -0,0 +1 @@
+<%= yield 'Yield!' %>
diff --git a/actionpack/test/fixtures/layouts/yield_with_render_partial_inside.erb b/actionpack/test/fixtures/layouts/yield_with_render_partial_inside.erb
new file mode 100644
index 0000000000..74cc428ffa
--- /dev/null
+++ b/actionpack/test/fixtures/layouts/yield_with_render_partial_inside.erb
@@ -0,0 +1,2 @@
+<%= render :partial => 'test/partial' %>
+<%= yield %>
diff --git a/actionpack/test/fixtures/test/_partial_with_layout.erb b/actionpack/test/fixtures/test/_partial_with_layout.erb
new file mode 100644
index 0000000000..2a50c834fe
--- /dev/null
+++ b/actionpack/test/fixtures/test/_partial_with_layout.erb
@@ -0,0 +1,2 @@
+<%= render :partial => 'test/partial', :layout => 'test/layout_for_partial', :locals => { :name => 'Bar!' } %>
+partial with layout
diff --git a/actionpack/test/fixtures/test/_partial_with_layout_block_content.erb b/actionpack/test/fixtures/test/_partial_with_layout_block_content.erb
new file mode 100644
index 0000000000..65dafd93a8
--- /dev/null
+++ b/actionpack/test/fixtures/test/_partial_with_layout_block_content.erb
@@ -0,0 +1,4 @@
+<%= render :layout => 'test/layout_for_partial', :locals => { :name => 'Bar!' } do %>
+ Content from inside layout!
+<% end %>
+partial with layout
diff --git a/actionpack/test/fixtures/test/_partial_with_layout_block_partial.erb b/actionpack/test/fixtures/test/_partial_with_layout_block_partial.erb
new file mode 100644
index 0000000000..444197a7d0
--- /dev/null
+++ b/actionpack/test/fixtures/test/_partial_with_layout_block_partial.erb
@@ -0,0 +1,4 @@
+<%= render :layout => 'test/layout_for_partial', :locals => { :name => 'Bar!' } do %>
+ <%= render 'test/partial' %>
+<% end %>
+partial with layout
diff --git a/actionpack/test/fixtures/test/_partial_with_partial.erb b/actionpack/test/fixtures/test/_partial_with_partial.erb
new file mode 100644
index 0000000000..ee0d5037b6
--- /dev/null
+++ b/actionpack/test/fixtures/test/_partial_with_partial.erb
@@ -0,0 +1,2 @@
+<%= render 'test/partial' %>
+partial with partial
diff --git a/actionpack/test/lib/controller/fake_models.rb b/actionpack/test/lib/controller/fake_models.rb
index dba632e6df..ae0c38184d 100644
--- a/actionpack/test/lib/controller/fake_models.rb
+++ b/actionpack/test/lib/controller/fake_models.rb
@@ -184,3 +184,13 @@ module Blog
end
end
end
+
+class ArelLike
+ def to_ary
+ true
+ end
+ def each
+ a = Array.new(2) { |id| Comment.new(id + 1) }
+ a.each { |i| yield i }
+ end
+end
diff --git a/actionpack/test/template/asset_tag_helper_test.rb b/actionpack/test/template/asset_tag_helper_test.rb
index 3abcdfbc1e..caf1c694c8 100644
--- a/actionpack/test/template/asset_tag_helper_test.rb
+++ b/actionpack/test/template/asset_tag_helper_test.rb
@@ -727,6 +727,17 @@ class AssetTagHelperTest < ActionView::TestCase
assert !File.exist?(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'money.js'))
end
+ def test_caching_javascript_include_tag_when_caching_on_and_javascript_file_is_uri
+ ENV["RAILS_ASSET_ID"] = ""
+ config.perform_caching = true
+
+ assert_raise(Errno::ENOENT) {
+ javascript_include_tag('bank', 'robber', 'https://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.js', :cache => true)
+ }
+
+ assert !File.exist?(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'all.js'))
+ end
+
def test_caching_javascript_include_tag_when_caching_off_and_missing_javascript_file
ENV["RAILS_ASSET_ID"] = ""
config.perform_caching = false
diff --git a/actionpack/test/template/capture_helper_test.rb b/actionpack/test/template/capture_helper_test.rb
index 8f81076299..03050485fa 100644
--- a/actionpack/test/template/capture_helper_test.rb
+++ b/actionpack/test/template/capture_helper_test.rb
@@ -28,6 +28,16 @@ class CaptureHelperTest < ActionView::TestCase
assert_nil @av.capture { 1 }
end
+ def test_capture_escapes_html
+ string = @av.capture { '<em>bar</em>' }
+ assert_equal '&lt;em&gt;bar&lt;/em&gt;', string
+ end
+
+ def test_capture_doesnt_escape_twice
+ string = @av.capture { '&lt;em&gt;bar&lt;/em&gt;'.html_safe }
+ assert_equal '&lt;em&gt;bar&lt;/em&gt;', string
+ end
+
def test_content_for
assert ! content_for?(:title)
content_for :title, 'title'
diff --git a/actionpack/test/template/date_helper_test.rb b/actionpack/test/template/date_helper_test.rb
index 0cf7885772..55c384e68f 100644
--- a/actionpack/test/template/date_helper_test.rb
+++ b/actionpack/test/template/date_helper_test.rb
@@ -1584,6 +1584,47 @@ class DateHelperTest < ActionView::TestCase
assert_dom_equal expected, date_select("post", "written_on", { :date_separator => " / " })
end
+ def test_date_select_with_separator_and_order
+ @post = Post.new
+ @post.written_on = Date.new(2004, 6, 15)
+
+ expected = %{<select id="post_written_on_3i" name="post[written_on(3i)]">\n}
+ expected << %{<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="4">4</option>\n<option value="5">5</option>\n<option value="6">6</option>\n<option value="7">7</option>\n<option value="8">8</option>\n<option value="9">9</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" selected="selected">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}
+ expected << "</select>\n"
+
+ expected << " / "
+
+ expected << %{<select id="post_written_on_2i" name="post[written_on(2i)]">\n}
+ expected << %{<option value="1">January</option>\n<option value="2">February</option>\n<option value="3">March</option>\n<option value="4">April</option>\n<option value="5">May</option>\n<option value="6" selected="selected">June</option>\n<option value="7">July</option>\n<option value="8">August</option>\n<option value="9">September</option>\n<option value="10">October</option>\n<option value="11">November</option>\n<option value="12">December</option>\n}
+ expected << "</select>\n"
+
+ expected << " / "
+
+ expected << %{<select id="post_written_on_1i" name="post[written_on(1i)]">\n}
+ expected << %{<option value="1999">1999</option>\n<option value="2000">2000</option>\n<option value="2001">2001</option>\n<option value="2002">2002</option>\n<option value="2003">2003</option>\n<option value="2004" selected="selected">2004</option>\n<option value="2005">2005</option>\n<option value="2006">2006</option>\n<option value="2007">2007</option>\n<option value="2008">2008</option>\n<option value="2009">2009</option>\n}
+ expected << "</select>\n"
+
+ assert_dom_equal expected, date_select("post", "written_on", { :order => [:day, :month, :year], :date_separator => " / " })
+ end
+
+ def test_date_select_with_separator_and_order_and_year_discarded
+ @post = Post.new
+ @post.written_on = Date.new(2004, 6, 15)
+
+ expected = %{<select id="post_written_on_3i" name="post[written_on(3i)]">\n}
+ expected << %{<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="4">4</option>\n<option value="5">5</option>\n<option value="6">6</option>\n<option value="7">7</option>\n<option value="8">8</option>\n<option value="9">9</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" selected="selected">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}
+ expected << "</select>\n"
+
+ expected << " / "
+
+ expected << %{<select id="post_written_on_2i" name="post[written_on(2i)]">\n}
+ expected << %{<option value="1">January</option>\n<option value="2">February</option>\n<option value="3">March</option>\n<option value="4">April</option>\n<option value="5">May</option>\n<option value="6" selected="selected">June</option>\n<option value="7">July</option>\n<option value="8">August</option>\n<option value="9">September</option>\n<option value="10">October</option>\n<option value="11">November</option>\n<option value="12">December</option>\n}
+ expected << "</select>\n"
+ expected << %{<input type="hidden" id="post_written_on_1i" name="post[written_on(1i)]" value="2004" />\n}
+
+ assert_dom_equal expected, date_select("post", "written_on", { :order => [:day, :month, :year], :discard_year => true, :date_separator => " / " })
+ end
+
def test_date_select_with_default_prompt
@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 acb6e7aa64..2c60096475 100644
--- a/actionpack/test/template/form_helper_test.rb
+++ b/actionpack/test/template/form_helper_test.rb
@@ -1230,6 +1230,27 @@ class FormHelperTest < ActionView::TestCase
assert_dom_equal expected, output_buffer
end
+ def test_nested_fields_for_arel_like
+ @post.comments = ArelLike.new
+
+ form_for(@post) do |f|
+ concat f.text_field(:title)
+ concat f.fields_for(:comments, @post.comments) { |cf|
+ concat cf.text_field(:name)
+ }
+ end
+
+ expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do
+ '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
+ '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #1" />' +
+ '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="1" />' +
+ '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="comment #2" />' +
+ '<input id="post_comments_attributes_1_id" name="post[comments_attributes][1][id]" type="hidden" value="2" />'
+ end
+
+ assert_dom_equal expected, output_buffer
+ end
+
def test_nested_fields_for_with_existing_records_on_a_supplied_nested_attributes_collection_different_from_record_one
comments = Array.new(2) { |id| Comment.new(id + 1) }
@post.comments = []
diff --git a/actionpack/test/template/number_helper_i18n_test.rb b/actionpack/test/template/number_helper_i18n_test.rb
index c82ead663f..5df09b4d3b 100644
--- a/actionpack/test/template/number_helper_i18n_test.rb
+++ b/actionpack/test/template/number_helper_i18n_test.rb
@@ -7,7 +7,7 @@ class NumberHelperTest < ActionView::TestCase
I18n.backend.store_translations 'ts',
:number => {
:format => { :precision => 3, :delimiter => ',', :separator => '.', :significant => false, :strip_insignificant_zeros => false },
- :currency => { :format => { :unit => '&$', :format => '%u - %n', :precision => 2 } },
+ :currency => { :format => { :unit => '&$', :format => '%u - %n', :negative_format => '(%u - %n)', :precision => 2 } },
:human => {
:format => {
:precision => 2,
@@ -43,11 +43,14 @@ class NumberHelperTest < ActionView::TestCase
def test_number_to_i18n_currency
assert_equal("&$ - 10.00", number_to_currency(10, :locale => 'ts'))
+ assert_equal("(&$ - 10.00)", number_to_currency(-10, :locale => 'ts'))
+ assert_equal("-10.00 - &$", number_to_currency(-10, :locale => 'ts', :format => "%n - %u"))
end
def test_number_to_currency_with_clean_i18n_settings
clean_i18n do
assert_equal("$10.00", number_to_currency(10))
+ assert_equal("-$10.00", number_to_currency(-10))
end
end
diff --git a/actionpack/test/template/number_helper_test.rb b/actionpack/test/template/number_helper_test.rb
index dcdf28ddd5..ab127521ad 100644
--- a/actionpack/test/template/number_helper_test.rb
+++ b/actionpack/test/template/number_helper_test.rb
@@ -45,11 +45,15 @@ class NumberHelperTest < ActionView::TestCase
def test_number_to_currency
assert_equal("$1,234,567,890.50", number_to_currency(1234567890.50))
assert_equal("$1,234,567,890.51", number_to_currency(1234567890.506))
+ assert_equal("-$1,234,567,890.50", number_to_currency(-1234567890.50))
+ assert_equal("-$ 1,234,567,890.50", number_to_currency(-1234567890.50, {:format => "%u %n"}))
+ assert_equal("($1,234,567,890.50)", number_to_currency(-1234567890.50, {:negative_format => "(%u%n)"}))
assert_equal("$1,234,567,892", number_to_currency(1234567891.50, {:precision => 0}))
assert_equal("$1,234,567,890.5", number_to_currency(1234567890.50, {:precision => 1}))
assert_equal("&pound;1234567890,50", number_to_currency(1234567890.50, {:unit => "&pound;", :separator => ",", :delimiter => ""}))
assert_equal("$1,234,567,890.50", number_to_currency("1234567890.50"))
assert_equal("1,234,567,890.50 K&#269;", number_to_currency("1234567890.50", {:unit => "K&#269;", :format => "%n %u"}))
+ assert_equal("1,234,567,890.50 - K&#269;", number_to_currency("-1234567890.50", {:unit => "K&#269;", :format => "%n %u", :negative_format => "%n - %u"}))
end
def test_number_to_percentage
diff --git a/actionpack/test/template/render_test.rb b/actionpack/test/template/render_test.rb
index 17bb610b6a..d2bf45a63a 100644
--- a/actionpack/test/template/render_test.rb
+++ b/actionpack/test/template/render_test.rb
@@ -247,6 +247,51 @@ module RenderTestCases
@view.render(:file => "test/hello_world.erb", :layout => "layouts/yield_with_render_inline_inside")
end
+ def test_render_with_layout_which_renders_another_partial
+ assert_equal %(partial html\nHello world!\n),
+ @view.render(:file => "test/hello_world.erb", :layout => "layouts/yield_with_render_partial_inside")
+ end
+
+ def test_render_layout_with_block_and_yield
+ assert_equal %(Content from block!\n),
+ @view.render(:layout => "layouts/yield_only") { "Content from block!" }
+ end
+
+ def test_render_layout_with_block_and_yield_with_params
+ assert_equal %(Yield! Content from block!\n),
+ @view.render(:layout => "layouts/yield_with_params") { |param| "#{param} Content from block!" }
+ end
+
+ def test_render_layout_with_block_which_renders_another_partial_and_yields
+ assert_equal %(partial html\nContent from block!\n),
+ @view.render(:layout => "layouts/partial_and_yield") { "Content from block!" }
+ end
+
+ def test_render_partial_and_layout_without_block_with_locals
+ assert_equal %(Before (Foo!)\npartial html\nAfter),
+ @view.render(:partial => 'test/partial', :layout => 'test/layout_for_partial', :locals => { :name => 'Foo!'})
+ end
+
+ def test_render_partial_and_layout_without_block_with_locals_and_rendering_another_partial
+ assert_equal %(Before (Foo!)\npartial html\npartial with partial\n\nAfter),
+ @view.render(:partial => 'test/partial_with_partial', :layout => 'test/layout_for_partial', :locals => { :name => 'Foo!'})
+ end
+
+ def test_render_layout_with_a_nested_render_layout_call
+ assert_equal %(Before (Foo!)\nBefore (Bar!)\npartial html\nAfter\npartial with layout\n\nAfter),
+ @view.render(:partial => 'test/partial_with_layout', :layout => 'test/layout_for_partial', :locals => { :name => 'Foo!'})
+ end
+
+ def test_render_layout_with_a_nested_render_layout_call_using_block_with_render_partial
+ assert_equal %(Before (Foo!)\nBefore (Bar!)\n\n partial html\n\nAfterpartial with layout\n\nAfter),
+ @view.render(:partial => 'test/partial_with_layout_block_partial', :layout => 'test/layout_for_partial', :locals => { :name => 'Foo!'})
+ end
+
+ def test_render_layout_with_a_nested_render_layout_call_using_block_with_render_content
+ assert_equal %(Before (Foo!)\nBefore (Bar!)\n\n Content from inside layout!\n\nAfterpartial with layout\n\nAfter),
+ @view.render(:partial => 'test/partial_with_layout_block_content', :layout => 'test/layout_for_partial', :locals => { :name => 'Foo!'})
+ 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.erb", :layout => "layouts/yield")
diff --git a/actionpack/test/template/url_helper_test.rb b/actionpack/test/template/url_helper_test.rb
index bc2548e06c..4a8cea36d4 100644
--- a/actionpack/test/template/url_helper_test.rb
+++ b/actionpack/test/template/url_helper_test.rb
@@ -263,12 +263,7 @@ class UrlHelperTest < ActiveSupport::TestCase
assert_equal "<strong>Showing</strong>",
link_to_unless(true, "Showing", url_hash) { |name|
- "<strong>#{name}</strong>"
- }
-
- assert_equal "<strong>Showing</strong>",
- link_to_unless(true, "Showing", url_hash) { |name|
- "<strong>#{name}</strong>"
+ "<strong>#{name}</strong>".html_safe
}
assert_equal "test",