Permalink
Browse files

Added a new container for cookies that makes them more intuative to u…

…se. The old methods of cookie and @cookies have been deprecated.

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@20 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information...
dhh committed Nov 26, 2004
1 parent b62937a commit d0c90331f19004f9f297989785f1516631ea0fc3
View
@@ -1,9 +1,20 @@
*SVN*
-* Added ActionController#cookies[]= as an alias for cookie "name", "value" -- you'll still need to use the latter if you have options to set.
+* Added a new container for cookies that makes them more intuative to use. The old methods of cookie and @cookies have been deprecated.
-* Added ActionController#cookies[] as a reader for @cookies that'll return the value of the cookie instead of the cookie object itself.
- NOTE: If you were using the old accessor, this could potentially break your code -- if you expect a full cookie object!
+ Examples for writing:
+
+ cookies["user_name"] = "david" # => Will set a simple session cookie
+ cookies["login"] = { "value" => "XJ-122", "expires" => Time.now + 360} # => Will set a cookie that expires in 1 hour
+
+ Examples for reading:
+
+ cookies["user_name"] # => "david"
+ cookies.size # => 2
+
+ Read more in ActionController::Cookies
+
+ NOTE: If you were using the old accessor (cookies instead of @cookies), this could potentially break your code -- if you expect a full cookie object!
* Added the opportunity to defined method_missing on a controller which will handle all requests for actions not otherwise defined #223 [timb]
View
@@ -41,6 +41,7 @@
action_controller/cgi_ext/cgi_ext.rb
action_controller/cgi_ext/cgi_methods.rb
action_controller/cgi_process.rb
+ action_controller/cookies.rb
action_controller/filters.rb
action_controller/flash.rb
action_controller/helpers.rb
@@ -34,6 +34,7 @@
require 'action_controller/scaffolding'
require 'action_controller/helpers'
require 'action_controller/dependencies'
+require 'action_controller/cookies'
require 'action_controller/cgi_process'
ActionController::Base.class_eval do
@@ -45,6 +46,7 @@
include ActionController::Scaffolding
include ActionController::Helpers
include ActionController::Dependencies
+ include ActionController::Cookies
end
require 'action_view'
@@ -539,40 +539,18 @@ def redirect_to_url(url) #:doc:
@performed_redirect = true
end
- # Creates a new cookie that is sent along-side the next render or redirect command. API is the same as for CGI::Cookie.
- # Examples:
- #
- # cookie("name", "value1", "value2", ...)
- # cookie("name" => "name", "value" => "value")
- # cookie('name' => 'name',
- # 'value' => ['value1', 'value2', ...],
- # 'path' => 'path', # optional
- # 'domain' => 'domain', # optional
- # 'expires' => Time.now, # optional
- # 'secure' => true # optional
- # )
- def cookie(*options) #:doc:
- @response.headers["cookie"] << CGI::Cookie.new(*options)
- end
-
- # Alias for cookie "name", "value"
- def cookies[]=(name, value)
- cookie(name, value)
- end
-
- # Returns the value of the cookie by +name+ -- or nil if no such cookie exist. You set new cookies using either the cookie method
- # or cookies[]= (for simple name/value cookies without options).
- def cookies[](name)
- @cookies[name].value if @cookies[name]
- end
-
# Resets the session by clearsing out all the objects stored within and initializing a new session object.
def reset_session #:doc:
@request.reset_session
@session = @request.session
@response.session = @session
end
+ # Deprecated cookie writer method
+ def cookie(*options)
+ @response.headers["cookie"] << CGI::Cookie.new(*options)
+ end
+
private
def initialize_template_class(response)
begin
@@ -0,0 +1,61 @@
+module ActionController #:nodoc:
+ # Cookies are read and written through ActionController#cookies. The cookies being read is what was received along with the request,
+ # the cookies being written is what will be sent out will the response. Cookies are read by value (so you won't get the cookie object
+ # itself back -- just the value it holds). Examples for writting:
+ #
+ # cookies["user_name"] = "david" # => Will set a simple session cookie
+ # cookies["login"] = { "value" => "XJ-122", "expires" => Time.now + 360} # => Will set a cookie that expires in 1 hour
+ #
+ # Examples for reading:
+ #
+ # cookies["user_name"] # => "david"
+ # cookies.size # => 2
+ #
+ # All the options for setting cookies are:
+ #
+ # value:: the cookie's value or list of values (as an array).
+ # path:: the path for which this cookie applies. Defaults to the root of the application.
+ # domain:: the domain for which this cookie applies.
+ # expires:: the time at which this cookie expires, as a +Time+ object.
+ # secure:: whether this cookie is a secure cookie or not (default to false).
+ # Secure cookies are only transmitted to HTTPS servers.
+ module Cookies
+ # Returns the cookie container, which operates as described above.
+ def cookies
+ CookieContainer.new(self)
+ end
+ end
+
+ class CookieContainer < Hash #:nodoc:
+ def initialize(controller)
+ @controller, @cookies = controller, controller.instance_variable_get("@cookies")
+ super()
+ update(@cookies)
+ end
+
+ # Returns the value of the cookie by +name+ -- or nil if no such cookie exist. You set new cookies using either the cookie method
+ # or cookies[]= (for simple name/value cookies without options).
+ def [](name)
+ @cookies[name].value if @cookies[name]
+ end
+
+ def []=(name, options)
+ if options.is_a?(Hash)
+ options["name"] = name
+ else
+ options = [ name, options ]
+ end
+
+ set_cookie(name, options)
+ end
+
+ private
+ def set_cookie(name, options) #:doc:
+ if options.is_a?(Array)
+ @controller.response.headers["cookie"] << CGI::Cookie.new(*options)
+ else
+ @controller.response.headers["cookie"] << CGI::Cookie.new(options)
+ end
+ end
+ end
+end
@@ -2,11 +2,27 @@
class CookieTest < Test::Unit::TestCase
class TestController < ActionController::Base
- def authenticate
+ def authenticate_with_deprecated_writer
cookie "name" => "user_name", "value" => "david"
render_text "hello world"
end
+ def authenticate
+ cookies["user_name"] = "david"
+ render_text "hello world"
+ end
+
+ def authenticate_for_fourten_days
+ cookies["user_name"] = { "value" => "david", "expires" => Time.local(2005, 10, 10) }
+ render_text "hello world"
+ end
+
+ def set_multiple_cookies
+ cookies["user_name"] = { "value" => "david", "expires" => Time.local(2005, 10, 10) }
+ cookies["login"] = "XJ-122"
+ render_text "hello world"
+ end
+
def access_frozen_cookies
@cookies["wont"] = "work"
end
@@ -21,12 +37,27 @@ def setup
@request.host = "www.nextangle.com"
end
+ def test_setting_cookie_with_deprecated_writer
+ @request.action = "authenticate_with_deprecated_writer"
+ assert_equal [ CGI::Cookie::new("name" => "user_name", "value" => "david") ], process_request.headers["cookie"]
+ end
+
def test_setting_cookie
@request.action = "authenticate"
assert_equal [ CGI::Cookie::new("name" => "user_name", "value" => "david") ], process_request.headers["cookie"]
end
- def test_setting_cookie
+ def test_setting_cookie_for_fourteen_days
+ @request.action = "authenticate_for_fourten_days"
+ assert_equal [ CGI::Cookie::new("name" => "user_name", "value" => "david", "expires" => Time.local(2005, 10, 10)) ], process_request.headers["cookie"]
+ end
+
+ def test_multiple_cookies
+ @request.action = "set_multiple_cookies"
+ assert_equal 2, process_request.headers["cookie"].size
+ end
+
+ def test_setting_cookie_on_frozen_instance_variable
@request.action = "access_frozen_cookies"
assert_raises(TypeError) { process_request }
end

0 comments on commit d0c9033

Please sign in to comment.