actionpack 3.0.0.beta4 → 3.0.0.rc

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

Files changed (102) hide show
  1. data/CHANGELOG +36 -0
  2. data/{README → README.rdoc} +79 -137
  3. data/lib/abstract_controller.rb +1 -0
  4. data/lib/abstract_controller/asset_paths.rb +1 -1
  5. data/lib/abstract_controller/base.rb +3 -12
  6. data/lib/abstract_controller/rendering.rb +2 -2
  7. data/lib/abstract_controller/view_paths.rb +2 -1
  8. data/lib/action_controller.rb +1 -2
  9. data/lib/action_controller/base.rb +3 -9
  10. data/lib/action_controller/log_subscriber.rb +56 -0
  11. data/lib/action_controller/metal.rb +10 -3
  12. data/lib/action_controller/metal/helpers.rb +5 -4
  13. data/lib/action_controller/metal/hide_actions.rb +3 -3
  14. data/lib/action_controller/metal/instrumentation.rb +2 -1
  15. data/lib/action_controller/metal/mime_responds.rb +13 -10
  16. data/lib/action_controller/metal/rack_delegation.rb +0 -4
  17. data/lib/action_controller/metal/request_forgery_protection.rb +1 -1
  18. data/lib/action_controller/metal/rescue.rb +9 -0
  19. data/lib/action_controller/metal/responder.rb +13 -5
  20. data/lib/action_controller/metal/streaming.rb +2 -0
  21. data/lib/action_controller/metal/url_for.rb +5 -5
  22. data/lib/action_controller/railtie.rb +14 -23
  23. data/lib/action_controller/record_identifier.rb +6 -25
  24. data/lib/action_controller/test_case.rb +18 -6
  25. data/lib/action_controller/vendor/html-scanner/html/node.rb +1 -0
  26. data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +1 -0
  27. data/lib/action_dispatch.rb +6 -0
  28. data/lib/action_dispatch/http/cache.rb +2 -2
  29. data/lib/action_dispatch/http/filter_parameters.rb +10 -66
  30. data/lib/action_dispatch/http/mime_type.rb +1 -1
  31. data/lib/action_dispatch/http/parameter_filter.rb +72 -0
  32. data/lib/action_dispatch/http/parameters.rb +31 -2
  33. data/lib/action_dispatch/http/request.rb +4 -1
  34. data/lib/action_dispatch/http/upload.rb +2 -2
  35. data/lib/action_dispatch/middleware/callbacks.rb +4 -4
  36. data/lib/action_dispatch/middleware/cookies.rb +39 -6
  37. data/lib/action_dispatch/middleware/flash.rb +9 -2
  38. data/lib/action_dispatch/middleware/session/abstract_store.rb +121 -36
  39. data/lib/action_dispatch/middleware/session/cookie_store.rb +26 -19
  40. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +9 -1
  41. data/lib/action_dispatch/middleware/show_exceptions.rb +2 -2
  42. data/lib/action_dispatch/middleware/stack.rb +12 -5
  43. data/lib/action_dispatch/railtie.rb +1 -1
  44. data/lib/action_dispatch/routing.rb +11 -13
  45. data/lib/action_dispatch/routing/deprecated_mapper.rb +6 -388
  46. data/lib/action_dispatch/routing/mapper.rb +364 -234
  47. data/lib/action_dispatch/routing/polymorphic_routes.rb +186 -0
  48. data/lib/action_dispatch/routing/route.rb +11 -2
  49. data/lib/action_dispatch/routing/route_set.rb +62 -28
  50. data/lib/action_dispatch/routing/url_for.rb +2 -1
  51. data/lib/action_dispatch/testing/assertions.rb +0 -2
  52. data/lib/action_dispatch/testing/assertions/routing.rb +0 -1
  53. data/lib/action_dispatch/testing/assertions/selector.rb +20 -24
  54. data/lib/action_dispatch/testing/integration.rb +2 -2
  55. data/lib/action_dispatch/testing/test_response.rb +2 -2
  56. data/lib/action_pack/version.rb +1 -1
  57. data/lib/action_view.rb +1 -0
  58. data/lib/action_view/base.rb +20 -21
  59. data/lib/action_view/context.rb +9 -12
  60. data/lib/action_view/helpers.rb +0 -2
  61. data/lib/action_view/helpers/active_model_helper.rb +17 -2
  62. data/lib/action_view/helpers/asset_tag_helper.rb +15 -33
  63. data/lib/action_view/helpers/atom_feed_helper.rb +5 -3
  64. data/lib/action_view/helpers/cache_helper.rb +4 -2
  65. data/lib/action_view/helpers/capture_helper.rb +4 -4
  66. data/lib/action_view/helpers/csrf_helper.rb +3 -1
  67. data/lib/action_view/helpers/date_helper.rb +10 -5
  68. data/lib/action_view/helpers/debug_helper.rb +3 -1
  69. data/lib/action_view/helpers/form_helper.rb +36 -30
  70. data/lib/action_view/helpers/form_options_helper.rb +7 -6
  71. data/lib/action_view/helpers/form_tag_helper.rb +17 -6
  72. data/lib/action_view/helpers/javascript_helper.rb +1 -0
  73. data/lib/action_view/helpers/number_helper.rb +16 -45
  74. data/lib/action_view/helpers/prototype_helper.rb +14 -16
  75. data/lib/action_view/helpers/raw_output_helper.rb +9 -0
  76. data/lib/action_view/helpers/record_tag_helper.rb +5 -0
  77. data/lib/action_view/helpers/sanitize_helper.rb +26 -20
  78. data/lib/action_view/helpers/scriptaculous_helper.rb +6 -5
  79. data/lib/action_view/helpers/tag_helper.rb +2 -1
  80. data/lib/action_view/helpers/text_helper.rb +24 -111
  81. data/lib/action_view/helpers/translation_helper.rb +17 -10
  82. data/lib/action_view/helpers/url_helper.rb +26 -33
  83. data/lib/action_view/log_subscriber.rb +28 -0
  84. data/lib/action_view/lookup_context.rb +2 -0
  85. data/lib/action_view/paths.rb +1 -0
  86. data/lib/action_view/railtie.rb +15 -3
  87. data/lib/action_view/render/layouts.rb +2 -1
  88. data/lib/action_view/render/partials.rb +3 -1
  89. data/lib/action_view/render/rendering.rb +2 -1
  90. data/lib/action_view/template.rb +12 -8
  91. data/lib/action_view/template/error.rb +1 -0
  92. data/lib/action_view/template/handlers.rb +1 -0
  93. data/lib/action_view/template/resolver.rb +2 -1
  94. data/lib/action_view/template/text.rb +1 -0
  95. data/lib/action_view/test_case.rb +42 -20
  96. metadata +44 -23
  97. data/lib/action_controller/polymorphic_routes.rb +0 -182
  98. data/lib/action_controller/railties/log_subscriber.rb +0 -56
  99. data/lib/action_controller/railties/url_helpers.rb +0 -14
  100. data/lib/action_dispatch/testing/assertions/model.rb +0 -19
  101. data/lib/action_view/helpers/record_identification_helper.rb +0 -20
  102. data/lib/action_view/railties/log_subscriber.rb +0 -24
@@ -40,7 +40,7 @@ module ActionController
40
40
  ActiveSupport::Notifications.unsubscribe("!render_template.action_view")
41
41
  end
42
42
 
43
- # Asserts that the request was rendered with the appropriate template file or partials
43
+ # Asserts that the request was rendered with the appropriate template file or partials.
44
44
  #
45
45
  # ==== Examples
46
46
  #
@@ -53,6 +53,12 @@ module ActionController
53
53
  # # assert that no partials were rendered
54
54
  # assert_template :partial => false
55
55
  #
56
+ # In a view test case, you can also assert that specific locals are passed
57
+ # to partials:
58
+ #
59
+ # # assert that the "_customer" partial was rendered with a specific object
60
+ # assert_template :partial => '_customer', :locals => { :customer => @customer }
61
+ #
56
62
  def assert_template(options = {}, message = nil)
57
63
  validate_request!
58
64
 
@@ -72,9 +78,13 @@ module ActionController
72
78
  end
73
79
  when Hash
74
80
  if expected_partial = options[:partial]
75
- if expected_count = options[:count]
81
+ if expected_locals = options[:locals]
82
+ actual_locals = @locals[expected_partial.to_s.sub(/^_/,'')]
83
+ expected_locals.each_pair do |k,v|
84
+ assert_equal(v, actual_locals[k])
85
+ end
86
+ elsif expected_count = options[:count]
76
87
  actual_count = @partials[expected_partial]
77
- # actual_count = found.nil? ? 0 : found[1]
78
88
  msg = build_message(message,
79
89
  "expecting ? to be rendered ? time(s) but rendered ? time(s)",
80
90
  expected_partial, expected_count, actual_count)
@@ -183,12 +193,14 @@ module ActionController
183
193
  replace(session.stringify_keys)
184
194
  @loaded = true
185
195
  end
196
+
197
+ def exists?; true; end
186
198
  end
187
199
 
188
200
  # Superclass for ActionController functional tests. Functional tests allow you to
189
201
  # test a single controller action per test method. This should not be confused with
190
202
  # integration tests (see ActionController::IntegrationTest), which are more like
191
- # "stories" that can involve multiple controllers and mutliple actions (i.e. multiple
203
+ # "stories" that can involve multiple controllers and multiple actions (i.e. multiple
192
204
  # different HTTP requests).
193
205
  #
194
206
  # == Basic example
@@ -353,7 +365,7 @@ module ActionController
353
365
  def xml_http_request(request_method, action, parameters = nil, session = nil, flash = nil)
354
366
  @request.env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
355
367
  @request.env['HTTP_ACCEPT'] ||= [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ')
356
- returning __send__(request_method, action, parameters, session, flash) do
368
+ __send__(request_method, action, parameters, session, flash).tap do
357
369
  @request.env.delete 'HTTP_X_REQUESTED_WITH'
358
370
  @request.env.delete 'HTTP_ACCEPT'
359
371
  end
@@ -442,7 +454,7 @@ module ActionController
442
454
  end
443
455
 
444
456
  # When the request.remote_addr remains the default for testing, which is 0.0.0.0, the exception is simply raised inline
445
- # (bystepping the regular exception handling from rescue_action). If the request.remote_addr is anything else, the regular
457
+ # (skipping the regular exception handling from rescue_action). If the request.remote_addr is anything else, the regular
446
458
  # rescue_action process takes place. This means you can test your rescue_action code by setting remote_addr to something else
447
459
  # than 0.0.0.0.
448
460
  #
@@ -177,6 +177,7 @@ module HTML #:nodoc:
177
177
  case text
178
178
  when "\\" then
179
179
  value << text
180
+ break if scanner.eos?
180
181
  value << scanner.getch
181
182
  when delim
182
183
  break
@@ -96,6 +96,7 @@ module HTML #:nodoc:
96
96
  while match = @scanner.scan_until(/[\\#{delim}]/)
97
97
  text << match
98
98
  break if @scanner.matched == delim
99
+ break if @scanner.eos?
99
100
  text << @scanner.getch # skip the escaped character
100
101
  end
101
102
  end
@@ -24,9 +24,14 @@
24
24
  activesupport_path = File.expand_path('../../../activesupport/lib', __FILE__)
25
25
  $:.unshift(activesupport_path) if File.directory?(activesupport_path) && !$:.include?(activesupport_path)
26
26
 
27
+ activemodel_path = File.expand_path('../../../activemodel/lib', __FILE__)
28
+ $:.unshift(activemodel_path) if File.directory?(activemodel_path) && !$:.include?(activemodel_path)
29
+
27
30
  require 'active_support'
28
31
  require 'active_support/dependencies/autoload'
29
32
 
33
+ require 'action_pack'
34
+ require 'active_model'
30
35
  require 'rack'
31
36
 
32
37
  module Rack
@@ -63,6 +68,7 @@ module ActionDispatch
63
68
  autoload :Headers
64
69
  autoload :MimeNegotiation
65
70
  autoload :Parameters
71
+ autoload :ParameterFilter
66
72
  autoload :FilterParameters
67
73
  autoload :Upload
68
74
  autoload :UploadedFile, 'action_dispatch/http/upload'
@@ -89,7 +89,7 @@ module ActionDispatch
89
89
  if etag? || last_modified? || !@cache_control.empty?
90
90
  set_conditional_cache_control!
91
91
  elsif nonempty_ok_response?
92
- self.etag = @body
92
+ self.etag = body
93
93
 
94
94
  if request && request.etag_matches?(etag)
95
95
  self.status = 304
@@ -137,4 +137,4 @@ module ActionDispatch
137
137
  end
138
138
  end
139
139
  end
140
- end
140
+ end
@@ -26,88 +26,32 @@ module ActionDispatch
26
26
  module FilterParameters
27
27
  extend ActiveSupport::Concern
28
28
 
29
- @@compiled_parameter_filter_for = {}
29
+ @@parameter_filter_for = {}
30
30
 
31
31
  # Return a hash of parameters with all sensitive data replaced.
32
32
  def filtered_parameters
33
- @filtered_parameters ||= if filtering_parameters?
34
- process_parameter_filter(parameters)
35
- else
36
- parameters.dup
37
- end
33
+ @filtered_parameters ||= parameter_filter.filter(parameters)
38
34
  end
39
- alias :fitered_params :filtered_parameters
40
35
 
41
36
  # Return a hash of request.env with all sensitive data replaced.
42
37
  def filtered_env
43
- filtered_env = @env.dup
44
- filtered_env.each do |key, value|
45
- if (key =~ /RAW_POST_DATA/i)
46
- filtered_env[key] = '[FILTERED]'
47
- elsif value.is_a?(Hash)
48
- filtered_env[key] = process_parameter_filter(value)
49
- end
50
- end
51
- filtered_env
38
+ @filtered_env ||= env_filter.filter(@env)
52
39
  end
53
40
 
54
41
  protected
55
42
 
56
- def filtering_parameters? #:nodoc:
57
- @env["action_dispatch.parameter_filter"].present?
43
+ def parameter_filter
44
+ parameter_filter_for(@env["action_dispatch.parameter_filter"])
58
45
  end
59
46
 
60
- def process_parameter_filter(params) #:nodoc:
61
- compiled_parameter_filter_for(@env["action_dispatch.parameter_filter"]).call(params)
47
+ def env_filter
48
+ parameter_filter_for(Array.wrap(@env["action_dispatch.parameter_filter"]) << /RAW_POST_DATA/)
62
49
  end
63
50
 
64
- def compile_parameter_filter(filters) #:nodoc:
65
- strings, regexps, blocks = [], [], []
66
-
67
- filters.each do |item|
68
- case item
69
- when NilClass
70
- when Proc
71
- blocks << item
72
- when Regexp
73
- regexps << item
74
- else
75
- strings << item.to_s
76
- end
77
- end
78
-
79
- regexps << Regexp.new(strings.join('|'), true) unless strings.empty?
80
- [regexps, blocks]
81
- end
82
-
83
- def compiled_parameter_filter_for(filters) #:nodoc:
84
- @@compiled_parameter_filter_for[filters] ||= begin
85
- regexps, blocks = compile_parameter_filter(filters)
86
-
87
- lambda do |original_params|
88
- filtered_params = {}
89
-
90
- original_params.each do |key, value|
91
- if regexps.find { |r| key =~ r }
92
- value = '[FILTERED]'
93
- elsif value.is_a?(Hash)
94
- value = process_parameter_filter(value)
95
- elsif value.is_a?(Array)
96
- value = value.map { |v| v.is_a?(Hash) ? process_parameter_filter(v) : v }
97
- elsif blocks.present?
98
- key = key.dup
99
- value = value.dup if value.duplicable?
100
- blocks.each { |b| b.call(key, value) }
101
- end
102
-
103
- filtered_params[key] = value
104
- end
105
-
106
- filtered_params
107
- end
108
- end
51
+ def parameter_filter_for(filters)
52
+ @@parameter_filter_for[filters] ||= ParameterFilter.new(filters)
109
53
  end
110
54
 
111
55
  end
112
56
  end
113
- end
57
+ end
@@ -60,7 +60,7 @@ module Mime
60
60
  def initialize(order, name, q=nil)
61
61
  @order = order
62
62
  @name = name.strip
63
- q ||= 0.0 if @name == Mime::ALL # default wilcard match to end of list
63
+ q ||= 0.0 if @name == Mime::ALL # default wildcard match to end of list
64
64
  @q = ((q || 1.0).to_f * 100).to_i
65
65
  end
66
66
 
@@ -0,0 +1,72 @@
1
+ module ActionDispatch
2
+ module Http
3
+ class ParameterFilter
4
+
5
+ def initialize(filters)
6
+ @filters = filters
7
+ end
8
+
9
+ def filter(params)
10
+ if enabled?
11
+ compiled_filter.call(params)
12
+ else
13
+ params.dup
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def enabled?
20
+ @filters.present?
21
+ end
22
+
23
+ def compiled_filter
24
+ @compiled_filter ||= begin
25
+ regexps, blocks = compile_filter
26
+
27
+ lambda do |original_params|
28
+ filtered_params = {}
29
+
30
+ original_params.each do |key, value|
31
+ if regexps.find { |r| key =~ r }
32
+ value = '[FILTERED]'
33
+ elsif value.is_a?(Hash)
34
+ value = filter(value)
35
+ elsif value.is_a?(Array)
36
+ value = value.map { |v| v.is_a?(Hash) ? filter(v) : v }
37
+ elsif blocks.present?
38
+ key = key.dup
39
+ value = value.dup if value.duplicable?
40
+ blocks.each { |b| b.call(key, value) }
41
+ end
42
+
43
+ filtered_params[key] = value
44
+ end
45
+
46
+ filtered_params
47
+ end
48
+ end
49
+ end
50
+
51
+ def compile_filter
52
+ strings, regexps, blocks = [], [], []
53
+
54
+ @filters.each do |item|
55
+ case item
56
+ when NilClass
57
+ when Proc
58
+ blocks << item
59
+ when Regexp
60
+ regexps << item
61
+ else
62
+ strings << item.to_s
63
+ end
64
+ end
65
+
66
+ regexps << Regexp.new(strings.join('|'), true) unless strings.empty?
67
+ [regexps, blocks]
68
+ end
69
+
70
+ end
71
+ end
72
+ end
@@ -6,7 +6,11 @@ module ActionDispatch
6
6
  module Parameters
7
7
  # Returns both GET and POST \parameters in a single hash.
8
8
  def parameters
9
- @env["action_dispatch.request.parameters"] ||= request_parameters.merge(query_parameters).update(path_parameters).with_indifferent_access
9
+ @env["action_dispatch.request.parameters"] ||= begin
10
+ params = request_parameters.merge(query_parameters)
11
+ params.merge!(path_parameters)
12
+ encode_params(params).with_indifferent_access
13
+ end
10
14
  end
11
15
  alias :params :parameters
12
16
 
@@ -32,7 +36,32 @@ module ActionDispatch
32
36
  end
33
37
 
34
38
  private
35
- # Convert nested Hashs to HashWithIndifferentAccess
39
+
40
+ # TODO: Validate that the characters are UTF-8. If they aren't,
41
+ # you'll get a weird error down the road, but our form handling
42
+ # should really prevent that from happening
43
+ def encode_params(params)
44
+ return params unless "ruby".encoding_aware?
45
+
46
+ if params.is_a?(String)
47
+ return params.force_encoding("UTF-8").encode!
48
+ elsif !params.is_a?(Hash)
49
+ return params
50
+ end
51
+
52
+ params.each do |k, v|
53
+ case v
54
+ when Hash
55
+ encode_params(v)
56
+ when Array
57
+ v.map! {|el| encode_params(el) }
58
+ else
59
+ encode_params(v)
60
+ end
61
+ end
62
+ end
63
+
64
+ # Convert nested Hash to HashWithIndifferentAccess
36
65
  def normalize_parameters(value)
37
66
  case value
38
67
  when Hash
@@ -194,9 +194,12 @@ module ActionDispatch
194
194
  @env['rack.input']
195
195
  end
196
196
 
197
+ # TODO This should be broken apart into AD::Request::Session and probably
198
+ # be included by the session middleware.
197
199
  def reset_session
198
- self.session_options.delete(:id)
200
+ session.destroy if session
199
201
  self.session = {}
202
+ @env['action_dispatch.request.flash_hash'] = nil
200
203
  end
201
204
 
202
205
  def session=(session) #:nodoc:
@@ -31,8 +31,8 @@ module ActionDispatch
31
31
  end
32
32
 
33
33
  module Upload
34
- # Convert nested Hashs to HashWithIndifferentAccess and replace
35
- # file upload hashs with UploadedFile objects
34
+ # Convert nested Hash to HashWithIndifferentAccess and replace
35
+ # file upload hash with UploadedFile objects
36
36
  def normalize_parameters(value)
37
37
  if Hash === value && value.has_key?(:tempfile)
38
38
  upload = value[:tempfile]
@@ -8,7 +8,7 @@ module ActionDispatch
8
8
  class Callbacks
9
9
  include ActiveSupport::Callbacks
10
10
 
11
- define_callbacks :call, :terminator => "result == false", :rescuable => true
11
+ define_callbacks :call, :rescuable => true
12
12
  define_callbacks :prepare, :scope => :name
13
13
 
14
14
  # Add a preparation callback. Preparation callbacks are run before every
@@ -37,12 +37,12 @@ module ActionDispatch
37
37
 
38
38
  def initialize(app, prepare_each_request = false)
39
39
  @app, @prepare_each_request = app, prepare_each_request
40
- run_callbacks(:prepare)
40
+ _run_prepare_callbacks
41
41
  end
42
42
 
43
43
  def call(env)
44
- run_callbacks(:call) do
45
- run_callbacks(:prepare) if @prepare_each_request
44
+ _run_call_callbacks do
45
+ _run_prepare_callbacks if @prepare_each_request
46
46
  @app.call(env)
47
47
  end
48
48
  end
@@ -45,7 +45,16 @@ module ActionDispatch
45
45
  # * <tt>:value</tt> - The cookie's value or list of values (as an array).
46
46
  # * <tt>:path</tt> - The path for which this cookie applies. Defaults to the root
47
47
  # of the application.
48
- # * <tt>:domain</tt> - The domain for which this cookie applies.
48
+ # * <tt>:domain</tt> - The domain for which this cookie applies so you can
49
+ # restrict to the domain level. If you use a schema like www.example.com
50
+ # and want to share session with user.example.com set <tt>:domain</tt>
51
+ # to <tt>:all</tt>. Make sure to specify the <tt>:domain</tt> option with
52
+ # <tt>:all</tt> again when deleting keys.
53
+ #
54
+ # :domain => nil # Does not sets cookie domain. (default)
55
+ # :domain => :all # Allow the cookie for the top most level
56
+ # domain and subdomains.
57
+ #
49
58
  # * <tt>:expires</tt> - The time at which this cookie expires, as a Time object.
50
59
  # * <tt>:secure</tt> - Whether this cookie is a only transmitted to HTTPS servers.
51
60
  # Default is +false+.
@@ -59,17 +68,29 @@ module ActionDispatch
59
68
  class CookieOverflow < StandardError; end
60
69
 
61
70
  class CookieJar < Hash #:nodoc:
71
+
72
+ # This regular expression is used to split the levels of a domain
73
+ # So www.example.co.uk gives:
74
+ # $1 => www.
75
+ # $2 => example
76
+ # $3 => co.uk
77
+ DOMAIN_REGEXP = /^(.*\.)*(.*)\.(...|...\...|....|..\...|..)$/
78
+
62
79
  def self.build(request)
63
80
  secret = request.env[TOKEN_KEY]
64
- new(secret).tap do |hash|
81
+ host = request.env["HTTP_HOST"]
82
+
83
+ new(secret, host).tap do |hash|
65
84
  hash.update(request.cookies)
66
85
  end
67
86
  end
68
87
 
69
- def initialize(secret=nil)
88
+ def initialize(secret = nil, host = nil)
70
89
  @secret = secret
71
90
  @set_cookies = {}
72
91
  @delete_cookies = {}
92
+ @host = host
93
+
73
94
  super()
74
95
  end
75
96
 
@@ -78,6 +99,15 @@ module ActionDispatch
78
99
  super(name.to_s)
79
100
  end
80
101
 
102
+ def handle_options(options) #:nodoc:
103
+ options[:path] ||= "/"
104
+
105
+ if options[:domain] == :all
106
+ @host =~ DOMAIN_REGEXP
107
+ options[:domain] = ".#{$2}.#{$3}"
108
+ end
109
+ end
110
+
81
111
  # Sets the cookie named +name+. The second argument may be the very cookie
82
112
  # value, or a hash of options as documented above.
83
113
  def []=(key, options)
@@ -91,7 +121,8 @@ module ActionDispatch
91
121
 
92
122
  value = super(key.to_s, value)
93
123
 
94
- options[:path] ||= "/"
124
+ handle_options(options)
125
+
95
126
  @set_cookies[key] = options
96
127
  @delete_cookies.delete(key)
97
128
  value
@@ -102,7 +133,9 @@ module ActionDispatch
102
133
  # an options hash to delete cookies with extra data such as a <tt>:path</tt>.
103
134
  def delete(key, options = {})
104
135
  options.symbolize_keys!
105
- options[:path] ||= "/"
136
+
137
+ handle_options(options)
138
+
106
139
  value = super(key.to_s)
107
140
  @delete_cookies[key] = options
108
141
  value
@@ -118,7 +151,7 @@ module ActionDispatch
118
151
  # This jar allows chaining with the signed jar as well, so you can set permanent, signed cookies. Examples:
119
152
  #
120
153
  # cookies.permanent.signed[:remember_me] = current_user.id
121
- # # => Set-Cookie: discount=BAhU--848956038e692d7046deab32b7131856ab20e14e; path=/; expires=Sun, 16-Dec-2029 03:24:16 GMT
154
+ # # => Set-Cookie: remember_me=BAhU--848956038e692d7046deab32b7131856ab20e14e; path=/; expires=Sun, 16-Dec-2029 03:24:16 GMT
122
155
  def permanent
123
156
  @permanent ||= PermanentCookieJar.new(self, @secret)
124
157
  end