diff options
Diffstat (limited to 'actionpack')
-rw-r--r-- | actionpack/CHANGELOG.md | 40 | ||||
-rw-r--r-- | actionpack/lib/action_controller/test_case.rb | 3 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/http/url.rb | 2 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/middleware/flash.rb | 34 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/middleware/session/cookie_store.rb | 10 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/routing/mapper.rb | 2 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/testing/assertions/routing.rb | 11 | ||||
-rw-r--r-- | actionpack/lib/action_view/renderer/partial_renderer.rb | 1 | ||||
-rw-r--r-- | actionpack/lib/action_view/renderer/renderer.rb | 14 | ||||
-rw-r--r-- | actionpack/lib/action_view/renderer/template_renderer.rb | 2 | ||||
-rw-r--r-- | actionpack/test/controller/flash_hash_test.rb | 21 | ||||
-rw-r--r-- | actionpack/test/controller/render_test.rb | 10 | ||||
-rw-r--r-- | actionpack/test/dispatch/request_test.rb | 15 | ||||
-rw-r--r-- | actionpack/test/dispatch/routing_test.rb | 20 |
14 files changed, 144 insertions, 41 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index 1ebc75ed2f..85a83ed7d9 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,5 +1,45 @@ ## Rails 4.0.0 (unreleased) ## +* Allow setting a symbol as path in scope on routes. This is now allowed: + + scope :api do + resources :users + end + + It is also possible to pass multiple symbols to scope to shorten multiple nested scopes: + + scope :api do + scope :v1 do + resources :users + end + end + + can be rewritten as: + + scope :api, :v1 do + resources :users + end + + *Guillermo Iguaran* + +* Fix error when using a non-hash query argument named "params" in `url_for`. + + Before: + + url_for(params: "") # => undefined method `reject!' for "":String + + After: + + url_for(params: "") # => http://www.example.com?params= + + *tumayun + Carlos Antonio da Silva* + +* Render every partial with a new `ActionView::PartialRenderer`. This resolves + issues when rendering nested partials. + Fix #8197 + + *Yves Senn* + * 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 diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb index 5aecb59df9..be8055955d 100644 --- a/actionpack/lib/action_controller/test_case.rb +++ b/actionpack/lib/action_controller/test_case.rb @@ -509,7 +509,7 @@ module ActionController @request.assign_parameters(@routes, controller_class_name, action.to_s, parameters) @request.session.update(session) if session - @request.session["flash"] = @request.flash.update(flash || {}) + @request.flash.update(flash || {}) @controller.request = @request @controller.response = @response @@ -526,6 +526,7 @@ module ActionController @response.prepare! @assigns = @controller.respond_to?(:view_assigns) ? @controller.view_assigns : {} + @request.session['flash'] = @request.flash.to_session_value @request.session.delete('flash') if @request.session['flash'].blank? @response end diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb index 9a7e8a5a9c..bced7d84c0 100644 --- a/actionpack/lib/action_dispatch/http/url.rb +++ b/actionpack/lib/action_dispatch/http/url.rb @@ -28,7 +28,7 @@ module ActionDispatch path = options.delete(:script_name).to_s.chomp("/") path << options.delete(:path).to_s - params = options[:params] || {} + params = options[:params].is_a?(Hash) ? options[:params] : options.slice(:params) params.reject! { |_,v| v.to_param.nil? } result = build_host_url(options) diff --git a/actionpack/lib/action_dispatch/middleware/flash.rb b/actionpack/lib/action_dispatch/middleware/flash.rb index 9928b7cc3a..7b18c57420 100644 --- a/actionpack/lib/action_dispatch/middleware/flash.rb +++ b/actionpack/lib/action_dispatch/middleware/flash.rb @@ -4,7 +4,7 @@ module ActionDispatch # read a notice you put there or <tt>flash["notice"] = "hello"</tt> # to put a new one. def flash - @env[Flash::KEY] ||= (session["flash"] || Flash::FlashHash.new).tap(&:sweep) + @env[Flash::KEY] ||= Flash::FlashHash.from_session_value(session["flash"]) end end @@ -70,16 +70,30 @@ module ActionDispatch end end - # Implementation detail: please do not change the signature of the - # FlashHash class. Doing that will likely affect all Rails apps in - # production as the FlashHash currently stored in their sessions will - # become invalid. class FlashHash include Enumerable - def initialize #:nodoc: - @discard = Set.new - @flashes = {} + def self.from_session_value(value) + flash = case value + when FlashHash # Rails 3.1, 3.2 + new(value.instance_variable_get(:@flashes), value.instance_variable_get(:@used)) + when Hash # Rails 4.0 + new(value['flashes'], value['discard']) + else + new + end + + flash.tap(&:sweep) + end + + def to_session_value + return nil if empty? + {'discard' => @discard.to_a, 'flashes' => @flashes} + end + + def initialize(flashes = {}, discard = []) #:nodoc: + @discard = Set.new(discard) + @flashes = flashes @now = nil end @@ -223,7 +237,7 @@ module ActionDispatch if flash_hash if !flash_hash.empty? || session.key?('flash') - session["flash"] = flash_hash + session["flash"] = flash_hash.to_session_value new_hash = flash_hash.dup else new_hash = flash_hash @@ -233,7 +247,7 @@ module ActionDispatch end if (!session.respond_to?(:loaded?) || session.loaded?) && # (reset_session uses {}, which doesn't implement #loaded?) - session.key?('flash') && session['flash'].empty? + session.key?('flash') && session['flash'].nil? session.delete('flash') end end diff --git a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb index d7f83a1cc6..ce5f89ee5b 100644 --- a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb @@ -95,9 +95,17 @@ module ActionDispatch end # This cookie store helps you upgrading apps that use +CookieStore+ to the new default +EncryptedCookieStore+ + # To use this CookieStore set + # + # Myapp::Application.config.session_store :upgrade_signature_to_encryption_cookie_store, key: '_myapp_session' # - # To use this CookieStore set MyApp.config.session_store :upgrade_signature_to_encryption_cookie_store, key: '_myapp_session' # in your config/initializers/session_store.rb + # + # You will also need to add + # + # Myapp::Application.config.secret_key_base = 'some secret' + # + # in your config/initializers/secret_token.rb, but do not remove +Myapp::Application.config.secret_token = 'some secret'+ class UpgradeSignatureToEncryptionCookieStore < EncryptedCookieStore private diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index d6fe436b68..05cbcf709e 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -644,7 +644,7 @@ module ActionDispatch options = args.extract_options! options = options.dup - options[:path] = args.first if args.first.is_a?(String) + options[:path] = args.flatten.join('/') if args.any? recover = {} options[:constraints] ||= {} diff --git a/actionpack/lib/action_dispatch/testing/assertions/routing.rb b/actionpack/lib/action_dispatch/testing/assertions/routing.rb index 8f17ee05be..79dff7d121 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/routing.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/routing.rb @@ -36,16 +36,19 @@ module ActionDispatch # # # Test a custom route # assert_recognizes({controller: 'items', action: 'show', id: '1'}, 'view/item1') - def assert_recognizes(expected_options, path, extras={}, message=nil) + def assert_recognizes(expected_options, path, extras={}, msg=nil) request = recognized_request_for(path, extras) expected_options = expected_options.clone expected_options.stringify_keys! - message ||= sprintf("The recognized options <%s> did not match <%s>, difference: <%s>", - request.path_parameters, expected_options, diff(expected_options, request.path_parameters)) - assert_equal(expected_options, request.path_parameters, message) + msg = message(msg, "") { + sprintf("The recognized options <%s> did not match <%s>, difference:", + request.path_parameters, expected_options) + } + + assert_equal(expected_options, request.path_parameters, msg) end # Asserts that the provided options can be used to generate the provided path. This is the inverse of +assert_recognizes+. diff --git a/actionpack/lib/action_view/renderer/partial_renderer.rb b/actionpack/lib/action_view/renderer/partial_renderer.rb index 36d557e1a3..f5fdf766ad 100644 --- a/actionpack/lib/action_view/renderer/partial_renderer.rb +++ b/actionpack/lib/action_view/renderer/partial_renderer.rb @@ -1,4 +1,3 @@ - module ActionView # = Action View Partials # diff --git a/actionpack/lib/action_view/renderer/renderer.rb b/actionpack/lib/action_view/renderer/renderer.rb index bf1b5a7d22..30a0c4be70 100644 --- a/actionpack/lib/action_view/renderer/renderer.rb +++ b/actionpack/lib/action_view/renderer/renderer.rb @@ -33,22 +33,12 @@ module ActionView # Direct accessor to template rendering. def render_template(context, options) #:nodoc: - _template_renderer.render(context, options) + TemplateRenderer.new(@lookup_context).render(context, options) end # Direct access to partial rendering. def render_partial(context, options, &block) #:nodoc: - _partial_renderer.render(context, options, block) - end - - private - - def _template_renderer #:nodoc: - @_template_renderer ||= TemplateRenderer.new(@lookup_context) - end - - def _partial_renderer #:nodoc: - @_partial_renderer ||= PartialRenderer.new(@lookup_context) + PartialRenderer.new(@lookup_context).render(context, options, block) end end end diff --git a/actionpack/lib/action_view/renderer/template_renderer.rb b/actionpack/lib/action_view/renderer/template_renderer.rb index 2a5ea5a711..4d5c5db80c 100644 --- a/actionpack/lib/action_view/renderer/template_renderer.rb +++ b/actionpack/lib/action_view/renderer/template_renderer.rb @@ -41,7 +41,7 @@ module ActionView # Renders the given template. A string representing the layout can be # supplied as well. - def render_template(template, layout_name = nil, locals = {}) #:nodoc: + def render_template(template, layout_name = nil, locals = nil) #:nodoc: view, locals = @view, locals || {} render_with_layout(layout_name, locals) do |layout| diff --git a/actionpack/test/controller/flash_hash_test.rb b/actionpack/test/controller/flash_hash_test.rb index ccca0dac17..5490d9394b 100644 --- a/actionpack/test/controller/flash_hash_test.rb +++ b/actionpack/test/controller/flash_hash_test.rb @@ -46,6 +46,27 @@ module ActionDispatch assert_equal({'foo' => 'bar'}, @hash.to_hash) end + def test_to_session_value + @hash['foo'] = 'bar' + assert_equal({'flashes' => {'foo' => 'bar'}, 'discard' => []}, @hash.to_session_value) + + @hash.discard('foo') + assert_equal({'flashes' => {'foo' => 'bar'}, 'discard' => %w[foo]}, @hash.to_session_value) + + @hash.now['qux'] = 1 + assert_equal({'flashes' => {'foo' => 'bar', 'qux' => 1}, 'discard' => %w[foo qux]}, @hash.to_session_value) + + @hash.sweep + assert_equal(nil, @hash.to_session_value) + end + + def test_from_session_value + rails_3_2_cookie = 'BAh7B0kiD3Nlc3Npb25faWQGOgZFRkkiJWY4ZTFiODE1MmJhNzYwOWMyOGJiYjE3ZWM5MjYzYmE3BjsAVEkiCmZsYXNoBjsARm86JUFjdGlvbkRpc3BhdGNoOjpGbGFzaDo6Rmxhc2hIYXNoCToKQHVzZWRvOghTZXQGOgpAaGFzaHsAOgxAY2xvc2VkRjoNQGZsYXNoZXN7BkkiDG1lc3NhZ2UGOwBGSSIKSGVsbG8GOwBGOglAbm93MA==' + session = Marshal.load(Base64.decode64(rails_3_2_cookie)) + hash = Flash::FlashHash.from_session_value(session['flash']) + assert_equal({'flashes' => {'message' => 'Hello'}, 'discard' => %w[message]}, hash.to_session_value) + end + def test_empty? assert @hash.empty? @hash['zomg'] = 'bears' diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index aa33f01d02..859ed1466b 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -646,6 +646,10 @@ class TestController < ActionController::Base render :partial => "customer", :spacer_template => "partial_only", :collection => [ Customer.new("david"), Customer.new("mary") ] end + def partial_collection_with_spacer_which_uses_render + render :partial => "customer", :spacer_template => "partial_with_partial", :collection => [ Customer.new("david"), Customer.new("mary") ] + end + def partial_collection_shorthand_with_locals render :partial => [ Customer.new("david"), Customer.new("mary") ], :locals => { :greeting => "Bonjour" } end @@ -1445,6 +1449,12 @@ class RenderTest < ActionController::TestCase assert_template :partial => '_customer' end + def test_partial_collection_with_spacer_which_uses_render + get :partial_collection_with_spacer_which_uses_render + assert_equal "Hello: davidpartial html\npartial with partial\nHello: mary", @response.body + assert_template :partial => '_customer' + end + def test_partial_collection_shorthand_with_locals get :partial_collection_shorthand_with_locals assert_equal "Bonjour: davidBonjour: mary", @response.body diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb index e2964f9071..f2bacf3e20 100644 --- a/actionpack/test/dispatch/request_test.rb +++ b/actionpack/test/dispatch/request_test.rb @@ -3,7 +3,7 @@ require 'abstract_unit' class RequestTest < ActiveSupport::TestCase def url_for(options = {}) - options.reverse_merge!(:host => 'www.example.com') + options = { host: 'www.example.com' }.merge!(options) ActionDispatch::Http::URL.url_for(options) end @@ -25,6 +25,8 @@ class RequestTest < ActiveSupport::TestCase assert_equal 'http://www.example.com/', url_for(:trailing_slash => true) assert_equal 'http://dhh:supersecret@www.example.com', url_for(:user => 'dhh', :password => 'supersecret') assert_equal 'http://www.example.com?search=books', url_for(:params => { :search => 'books' }) + assert_equal 'http://www.example.com?params=', url_for(:params => '') + assert_equal 'http://www.example.com?params=1', url_for(:params => 1) end test "remote ip" do @@ -355,7 +357,6 @@ class RequestTest < ActiveSupport::TestCase assert_equal "/of/some/uri", request.path_info end - test "host with default port" do request = stub_request 'HTTP_HOST' => 'rubyonrails.org:80' assert_equal "rubyonrails.org", request.host_with_port @@ -577,16 +578,16 @@ class RequestTest < ActiveSupport::TestCase test "formats with accept header" do request = stub_request 'HTTP_ACCEPT' => 'text/html' request.expects(:parameters).at_least_once.returns({}) - assert_equal [ Mime::HTML ], request.formats + assert_equal [Mime::HTML], request.formats request = stub_request 'CONTENT_TYPE' => 'application/xml; charset=UTF-8', 'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest" request.expects(:parameters).at_least_once.returns({}) - assert_equal with_set(Mime::XML), request.formats + assert_equal [Mime::XML], request.formats request = stub_request request.expects(:parameters).at_least_once.returns({ :format => :txt }) - assert_equal with_set(Mime::TEXT), request.formats + assert_equal [Mime::TEXT], request.formats request = stub_request request.expects(:parameters).at_least_once.returns({ :format => :unknown }) @@ -811,8 +812,4 @@ protected ActionDispatch::Http::URL.tld_length = tld_length ActionDispatch::Request.new(env) end - - def with_set(*args) - args - end end diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index 34606512dc..0a59d3cf9e 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -370,6 +370,14 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest scope :path => 'api' do resource :me get '/' => 'mes#index' + scope :v2 do + resource :me, as: 'v2_me' + get '/' => 'mes#index' + end + + scope :v3, :admin do + resource :me, as: 'v3_me' + end end get "(/:username)/followers" => "followers#index" @@ -1467,6 +1475,18 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest assert_equal 'mes#index', @response.body end + def test_symbol_scope + get '/api/v2/me' + assert_equal 'mes#show', @response.body + assert_equal '/api/v2/me', v2_me_path + + get '/api/v2' + assert_equal 'mes#index', @response.body + + get '/api/v3/admin/me' + assert_equal 'mes#show', @response.body + end + def test_url_generator_for_generic_route get 'whatever/foo/bar' assert_equal 'foo#bar', @response.body |