diff options
Diffstat (limited to 'actionpack')
17 files changed, 169 insertions, 27 deletions
diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb index ec1160c31e..691310d5d2 100644 --- a/actionpack/lib/abstract_controller/rendering.rb +++ b/actionpack/lib/abstract_controller/rendering.rb @@ -113,7 +113,7 @@ module AbstractController def render_to_string(*args, &block) options = _normalize_args(*args, &block) _normalize_options(options) - render_to_body(options) + render_to_body(options).tap { self.response_body = nil } end # Raw rendering of a template to a Rack-compatible body. diff --git a/actionpack/lib/action_controller/log_subscriber.rb b/actionpack/lib/action_controller/log_subscriber.rb index 3b19310a69..3fae697cc3 100644 --- a/actionpack/lib/action_controller/log_subscriber.rb +++ b/actionpack/lib/action_controller/log_subscriber.rb @@ -16,7 +16,11 @@ module ActionController payload = event.payload additions = ActionController::Base.log_process_action(payload) - message = "Completed #{payload[:status]} #{Rack::Utils::HTTP_STATUS_CODES[payload[:status]]} in %.0fms" % event.duration + status = payload[:status] + if status.nil? && payload[:exception].present? + status = Rack::Utils.status_code(ActionDispatch::ShowExceptions.rescue_responses[payload[:exception].first]) rescue nil + end + message = "Completed #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]} in %.0fms" % event.duration message << " (#{additions.join(" | ")})" unless additions.blank? info(message) diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb index 0caf37b8cd..032769a5c6 100644 --- a/actionpack/lib/action_controller/metal.rb +++ b/actionpack/lib/action_controller/metal.rb @@ -183,7 +183,7 @@ module ActionController end def response_body=(val) - body = val.respond_to?(:each) ? val : [val] + body = val.nil? ? nil : (val.respond_to?(:each) ? val : [val]) super body end diff --git a/actionpack/lib/action_dispatch/middleware/callbacks.rb b/actionpack/lib/action_dispatch/middleware/callbacks.rb index 4d038c29f2..1bb2ad7f67 100644 --- a/actionpack/lib/action_dispatch/middleware/callbacks.rb +++ b/actionpack/lib/action_dispatch/middleware/callbacks.rb @@ -25,7 +25,7 @@ module ActionDispatch end def call(env) - _run_call_callbacks do + run_callbacks :call do @app.call(env) end end diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb index f369d2d3c2..7ac608f0a8 100644 --- a/actionpack/lib/action_dispatch/middleware/cookies.rb +++ b/actionpack/lib/action_dispatch/middleware/cookies.rb @@ -90,17 +90,14 @@ module ActionDispatch # **.**, ***.** style TLDs like co.uk or com.au # # www.example.co.uk gives: - # $1 => example - # $2 => co.uk + # $& => example.co.uk # # example.com gives: - # $1 => example - # $2 => com + # $& => example.com # # lots.of.subdomains.example.local gives: - # $1 => example - # $2 => local - DOMAIN_REGEXP = /([^.]*)\.([^.]*|..\...|...\...)$/ + # $& => example.local + DOMAIN_REGEXP = /[^.]*\.([^.]*|..\...|...\...)$/ def self.build(request) secret = request.env[TOKEN_KEY] @@ -131,11 +128,17 @@ module ActionDispatch options[:path] ||= "/" if options[:domain] == :all + # if there is a provided tld length then we use it otherwise default domain regexp + domain_regexp = options[:tld_length] ? /([^.]+\.?){#{options[:tld_length]}}$/ : DOMAIN_REGEXP + # if host is not ip and matches domain regexp # (ip confirms to domain regexp so we explicitly check for ip) - options[:domain] = if (@host !~ /^[\d.]+$/) && (@host =~ DOMAIN_REGEXP) - ".#{$1}.#{$2}" + options[:domain] = if (@host !~ /^[\d.]+$/) && (@host =~ domain_regexp) + ".#{$&}" end + elsif options[:domain].is_a? Array + # if host matches one of the supplied domains without a dot in front of it + options[:domain] = options[:domain].find {|domain| @host.include? domain[/^\.?(.*)$/, 1] } end end diff --git a/actionpack/lib/action_dispatch/middleware/reloader.rb b/actionpack/lib/action_dispatch/middleware/reloader.rb index f6ab368ad8..29289a76b4 100644 --- a/actionpack/lib/action_dispatch/middleware/reloader.rb +++ b/actionpack/lib/action_dispatch/middleware/reloader.rb @@ -43,12 +43,12 @@ module ActionDispatch # Execute all prepare callbacks. def self.prepare! - new(nil).send(:_run_prepare_callbacks) + new(nil).run_callbacks :prepare end # Execute all cleanup callbacks. def self.cleanup! - new(nil).send(:_run_cleanup_callbacks) + new(nil).run_callbacks :cleanup end def initialize(app) @@ -64,12 +64,12 @@ module ActionDispatch end def call(env) - _run_prepare_callbacks + run_callbacks :prepare response = @app.call(env) response[2].extend(CleanupOnClose) response rescue Exception - _run_cleanup_callbacks + run_callbacks :cleanup raise end end diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index 3d276000a1..4f7f5c454f 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -459,7 +459,7 @@ module ActionView end AUTO_LINK_RE = %r{ - (?: ([\w+.:-]+:)// | www\. ) + (?: ([0-9A-Za-z+.:-]+:)// | www\. ) [^\s<]+ }x diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb index c23315b344..cfa88c91e3 100644 --- a/actionpack/lib/action_view/helpers/url_helper.rb +++ b/actionpack/lib/action_view/helpers/url_helper.rb @@ -253,8 +253,9 @@ module ActionView # using the +link_to+ method with the <tt>:method</tt> modifier as described in # the +link_to+ documentation. # - # The generated form element has a class name of <tt>button_to</tt> - # to allow styling of the form itself and its children. You can control + # By default, the generated form element has a class name of <tt>button_to</tt> + # to allow styling of the form itself and its children. This can be changed + # using the <tt>:form_class</tt> modifier within +html_options+. You can control # the form submission and input element behavior using +html_options+. # This method accepts the <tt>:method</tt> and <tt>:confirm</tt> modifiers # described in the +link_to+ documentation. If no <tt>:method</tt> modifier @@ -275,6 +276,8 @@ module ActionView # processed normally, otherwise no action is taken. # * <tt>:remote</tt> - If set to true, will allow the Unobtrusive JavaScript drivers to control the # submit behaviour. By default this behaviour is an ajax submit. + # * <tt>:form_class</tt> - This controls the class of the form within which the submit button will + # be placed # # ==== Examples # <%= button_to "New", :action => "new" %> @@ -283,6 +286,12 @@ module ActionView # # </form>" # # + # <%= button_to "New", :action => "new", :form_class => "new-thing" %> + # # => "<form method="post" action="/controller/new" class="new-thing"> + # # <div><input value="New" type="submit" /></div> + # # </form>" + # + # # <%= button_to "Delete Image", { :action => "delete", :id => @image.id }, # :confirm => "Are you sure?", :method => :delete %> # # => "<form method="post" action="/images/delete/1" class="button_to"> @@ -312,6 +321,7 @@ module ActionView end form_method = method.to_s == 'get' ? 'get' : 'post' + form_class = html_options.delete('form_class') || 'button_to' remote = html_options.delete('remote') @@ -327,7 +337,7 @@ module ActionView html_options.merge!("type" => "submit", "value" => name) - ("<form method=\"#{form_method}\" action=\"#{ERB::Util.html_escape(url)}\" #{"data-remote=\"true\"" if remote} class=\"button_to\"><div>" + + ("<form method=\"#{form_method}\" action=\"#{ERB::Util.html_escape(url)}\" #{"data-remote=\"true\"" if remote} class=\"#{ERB::Util.html_escape(form_class)}\"><div>" + method_tag + tag("input", html_options) + request_token_tag + "</div></form>").html_safe end diff --git a/actionpack/lib/action_view/partials.rb b/actionpack/lib/action_view/partials.rb index 56c661c00c..c181689e62 100644 --- a/actionpack/lib/action_view/partials.rb +++ b/actionpack/lib/action_view/partials.rb @@ -40,7 +40,7 @@ module ActionView # With the <tt>:as</tt> option we can specify a different name for said local variable. For example, if we # wanted it to be +agreement+ instead of +contract+ we'd do: # - # <%= render :partial => "contract", :as => :agreement %> + # <%= render :partial => "contract", :as => 'agreement' %> # # The <tt>:object</tt> option can be used to directly specify which object is rendered into the partial; # useful when the template's object is elsewhere, in a different ivar or in a local variable for instance. diff --git a/actionpack/lib/action_view/renderer/partial_renderer.rb b/actionpack/lib/action_view/renderer/partial_renderer.rb index 3fdea23a4a..94c0a8a8fb 100644 --- a/actionpack/lib/action_view/renderer/partial_renderer.rb +++ b/actionpack/lib/action_view/renderer/partial_renderer.rb @@ -108,7 +108,7 @@ module ActionView locals << @variable_counter if @collection find_template(path, locals) end - end + end def find_template(path=@path, locals=@locals.keys) prefixes = path.include?(?/) ? [] : @view.controller_prefixes @@ -159,7 +159,7 @@ module ActionView end def retrieve_variable(path) - variable = @options[:as] || path[%r'_?(\w+)(\.\w+)*$', 1].to_sym + variable = @options[:as].try(:to_sym) || path[%r'_?(\w+)(\.\w+)*$', 1].to_sym variable_counter = :"#{variable}_counter" if @collection [variable, variable_counter] end diff --git a/actionpack/test/controller/log_subscriber_test.rb b/actionpack/test/controller/log_subscriber_test.rb index cac0881133..21bbd83653 100644 --- a/actionpack/test/controller/log_subscriber_test.rb +++ b/actionpack/test/controller/log_subscriber_test.rb @@ -32,6 +32,11 @@ module Another cache_page("Super soaker", "/index.html") render :nothing => true end + + def with_exception + raise Exception + end + end end @@ -168,6 +173,16 @@ class ACLogSubscriberTest < ActionController::TestCase ensure @controller.config.perform_caching = true end + + def test_process_action_with_exception_includes_http_status_code + begin + get :with_exception + wait + rescue Exception => e + end + assert_equal 2, logs.size + assert_match(/Completed 500/, logs.last) + end def logs @logs ||= @logger.logged(:info) diff --git a/actionpack/test/controller/render_json_test.rb b/actionpack/test/controller/render_json_test.rb index 6dd2a9f23d..fc604a2db3 100644 --- a/actionpack/test/controller/render_json_test.rb +++ b/actionpack/test/controller/render_json_test.rb @@ -26,6 +26,10 @@ class RenderJsonTest < ActionController::TestCase render :json => nil end + def render_json_render_to_string + render :text => render_to_string(:json => '[]') + end + def render_json_hello_world render :json => ActiveSupport::JSON.encode(:hello => 'world') end @@ -76,6 +80,12 @@ class RenderJsonTest < ActionController::TestCase assert_equal 'application/json', @response.content_type end + def test_render_json_render_to_string + get :render_json_render_to_string + assert_equal '[]', @response.body + end + + def test_render_json get :render_json_hello_world assert_equal '{"hello":"world"}', @response.body diff --git a/actionpack/test/controller/webservice_test.rb b/actionpack/test/controller/webservice_test.rb index 6ba4c6c48d..621fb79915 100644 --- a/actionpack/test/controller/webservice_test.rb +++ b/actionpack/test/controller/webservice_test.rb @@ -216,7 +216,7 @@ class WebServiceTest < ActionDispatch::IntegrationTest def test_typecast_as_yaml with_test_route_set do with_params_parsers Mime::YAML => :yaml do - yaml = <<-YAML + yaml = (<<-YAML).strip --- data: a: 15 diff --git a/actionpack/test/dispatch/cookies_test.rb b/actionpack/test/dispatch/cookies_test.rb index e2040401c7..1cfea6aa12 100644 --- a/actionpack/test/dispatch/cookies_test.rb +++ b/actionpack/test/dispatch/cookies_test.rb @@ -95,6 +95,26 @@ class CookiesTest < ActionController::TestCase head :ok end + def set_cookie_with_domain_and_tld + cookies[:user_name] = {:value => "rizwanreza", :domain => :all, :tld_length => 2} + head :ok + end + + def delete_cookie_with_domain_and_tld + cookies.delete(:user_name, :domain => :all, :tld_length => 2) + head :ok + end + + def set_cookie_with_domains + cookies[:user_name] = {:value => "rizwanreza", :domain => %w(example1.com example2.com .example3.com)} + head :ok + end + + def delete_cookie_with_domains + cookies.delete(:user_name, :domain => %w(example1.com example2.com .example3.com)) + head :ok + end + def symbol_key cookies[:user_name] = "david" head :ok @@ -322,6 +342,67 @@ 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_cookie_with_all_domain_option_and_tld_length + get :set_cookie_with_domain_and_tld + assert_response :success + assert_cookie_header "user_name=rizwanreza; domain=.nextangle.com; path=/" + end + + def test_cookie_with_all_domain_option_using_a_non_standard_tld_and_tld_length + @request.host = "two.subdomains.nextangle.local" + get :set_cookie_with_domain_and_tld + assert_response :success + assert_cookie_header "user_name=rizwanreza; domain=.nextangle.local; path=/" + end + + def test_cookie_with_all_domain_option_using_host_with_port_and_tld_length + @request.host = "nextangle.local:3000" + get :set_cookie_with_domain_and_tld + assert_response :success + assert_cookie_header "user_name=rizwanreza; domain=.nextangle.local; path=/" + end + + def test_deleting_cookie_with_all_domain_option_and_tld_length + get :delete_cookie_with_domain_and_tld + assert_response :success + assert_cookie_header "user_name=; domain=.nextangle.com; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT" + end + + def test_cookie_with_several_preset_domains_using_one_of_these_domains + @request.host = "example1.com" + get :set_cookie_with_domains + assert_response :success + assert_cookie_header "user_name=rizwanreza; domain=example1.com; path=/" + end + + def test_cookie_with_several_preset_domains_using_other_domain + @request.host = "other-domain.com" + get :set_cookie_with_domains + assert_response :success + assert_cookie_header "user_name=rizwanreza; path=/" + end + + def test_cookie_with_several_preset_domains_using_shared_domain + @request.host = "example3.com" + get :set_cookie_with_domains + assert_response :success + assert_cookie_header "user_name=rizwanreza; domain=.example3.com; path=/" + end + + def test_deletings_cookie_with_several_preset_domains_using_one_of_these_domains + @request.host = "example2.com" + get :delete_cookie_with_domains + assert_response :success + assert_cookie_header "user_name=; domain=example2.com; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT" + end + + def test_deletings_cookie_with_several_preset_domains_using_other_domain + @request.host = "other-domain.com" + get :delete_cookie_with_domains + assert_response :success + assert_cookie_header "user_name=; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT" + end + def test_cookies_hash_is_indifferent_access [:symbol_key, :string_key].each do |cookie_key| get cookie_key diff --git a/actionpack/test/template/render_test.rb b/actionpack/test/template/render_test.rb index 38bedd2e4e..e02d69231f 100644 --- a/actionpack/test/template/render_test.rb +++ b/actionpack/test/template/render_test.rb @@ -146,7 +146,12 @@ module RenderTestCases assert_equal "Hello: davidHello: mary", @view.render(:partial => "test/customer", :collection => [ Customer.new("david"), Customer.new("mary") ]) end - def test_render_partial_collection_as + def test_render_partial_collection_as_by_string + assert_equal "david david davidmary mary mary", + @view.render(:partial => "test/customer_with_var", :collection => [ Customer.new("david"), Customer.new("mary") ], :as => 'customer') + end + + def test_render_partial_collection_as_by_symbol assert_equal "david david davidmary mary mary", @view.render(:partial => "test/customer_with_var", :collection => [ Customer.new("david"), Customer.new("mary") ], :as => :customer) end diff --git a/actionpack/test/template/text_helper_test.rb b/actionpack/test/template/text_helper_test.rb index 9e9ed9120d..d0d4286393 100644 --- a/actionpack/test/template/text_helper_test.rb +++ b/actionpack/test/template/text_helper_test.rb @@ -1,4 +1,4 @@ -# encoding: us-ascii +# encoding: utf-8 require 'abstract_unit' require 'testing_sandbox' @@ -415,6 +415,12 @@ class TextHelperTest < ActionView::TestCase link10_raw = 'http://www.mail-archive.com/ruby-talk@ruby-lang.org/' link10_result = generate_result(link10_raw) assert_equal %(<p>#{link10_result} Link</p>), auto_link("<p>#{link10_raw} Link</p>") + + link11_raw = 'http://asakusa.rubyist.net/' + link11_result = generate_result(link11_raw) + with_kcode 'u' do + assert_equal %(浅草.rbの公式サイトはこちら#{link11_result}), auto_link("浅草.rbの公式サイトはこちら#{link11_raw}") + end end def test_auto_link_should_sanitize_input_when_sanitize_option_is_not_false diff --git a/actionpack/test/template/url_helper_test.rb b/actionpack/test/template/url_helper_test.rb index 4a8cea36d4..2e1661a0ac 100644 --- a/actionpack/test/template/url_helper_test.rb +++ b/actionpack/test/template/url_helper_test.rb @@ -50,6 +50,14 @@ class UrlHelperTest < ActiveSupport::TestCase assert_dom_equal "<form method=\"post\" action=\"http://www.example.com\" class=\"button_to\"><div><input type=\"submit\" value=\"Hello\" /></div></form>", button_to("Hello", "http://www.example.com") end + def test_button_to_with_form_class + assert_dom_equal "<form method=\"post\" action=\"http://www.example.com\" class=\"custom-class\"><div><input type=\"submit\" value=\"Hello\" /></div></form>", button_to("Hello", "http://www.example.com", :form_class => 'custom-class') + end + + def test_button_to_with_form_class_escapes + assert_dom_equal "<form method=\"post\" action=\"http://www.example.com\" class=\"<script>evil_js</script>\"><div><input type=\"submit\" value=\"Hello\" /></div></form>", button_to("Hello", "http://www.example.com", :form_class => '<script>evil_js</script>') + end + def test_button_to_with_query assert_dom_equal "<form method=\"post\" action=\"http://www.example.com/q1=v1&q2=v2\" class=\"button_to\"><div><input type=\"submit\" value=\"Hello\" /></div></form>", button_to("Hello", "http://www.example.com/q1=v1&q2=v2") end |