diff options
author | Jon Leighton <j@jonathanleighton.com> | 2010-11-08 11:02:26 +0000 |
---|---|---|
committer | Jon Leighton <j@jonathanleighton.com> | 2010-11-08 11:02:26 +0000 |
commit | e05162cffad7ae86615c21c6b54ab161d0261c39 (patch) | |
tree | c02e6faf12c2ce50ef4ac40342daf488d7fa0f8d /actionpack | |
parent | 083d6f267611472b8acfb9801e64971ee6d19994 (diff) | |
parent | 4e0477c9b75683372f662a614ae91b158120ebe8 (diff) | |
download | rails-e05162cffad7ae86615c21c6b54ab161d0261c39.tar.gz rails-e05162cffad7ae86615c21c6b54ab161d0261c39.tar.bz2 rails-e05162cffad7ae86615c21c6b54ab161d0261c39.zip |
Merge branch 'master' into nested_has_many_through
Conflicts:
activerecord/lib/active_record/associations.rb
Diffstat (limited to 'actionpack')
19 files changed, 158 insertions, 38 deletions
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 3c7dcea003..1bbb4f1f92 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/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/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/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index d6e175c7e8..80a872068d 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -294,10 +294,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 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 => "£", :separator => ",", :delimiter => "") # # => £1234567890,50 # number_to_currency(1234567890.50, :unit => "£", :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/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/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/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 '<em>bar</em>', string + end + + def test_capture_doesnt_escape_twice + string = @av.capture { '<em>bar</em>'.html_safe } + assert_equal '<em>bar</em>', string + end + def test_content_for assert ! content_for?(:title) content_for :title, 'title' 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("£1234567890,50", number_to_currency(1234567890.50, {:unit => "£", :separator => ",", :delimiter => ""})) assert_equal("$1,234,567,890.50", number_to_currency("1234567890.50")) assert_equal("1,234,567,890.50 Kč", number_to_currency("1234567890.50", {:unit => "Kč", :format => "%n %u"})) + assert_equal("1,234,567,890.50 - Kč", number_to_currency("-1234567890.50", {:unit => "Kč", :format => "%n %u", :negative_format => "%n - %u"})) end def test_number_to_percentage 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", |