aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack')
-rw-r--r--actionpack/CHANGELOG.md40
-rw-r--r--actionpack/lib/action_controller/test_case.rb3
-rw-r--r--actionpack/lib/action_dispatch/http/url.rb2
-rw-r--r--actionpack/lib/action_dispatch/middleware/flash.rb34
-rw-r--r--actionpack/lib/action_dispatch/middleware/session/cookie_store.rb10
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb2
-rw-r--r--actionpack/lib/action_dispatch/testing/assertions/routing.rb11
-rw-r--r--actionpack/lib/action_view/renderer/partial_renderer.rb1
-rw-r--r--actionpack/lib/action_view/renderer/renderer.rb14
-rw-r--r--actionpack/lib/action_view/renderer/template_renderer.rb2
-rw-r--r--actionpack/test/controller/flash_hash_test.rb21
-rw-r--r--actionpack/test/controller/render_test.rb10
-rw-r--r--actionpack/test/dispatch/request_test.rb15
-rw-r--r--actionpack/test/dispatch/routing_test.rb20
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