GitHub Sale: sign up for any paid plan this week and pay nothing until January 1, 2009!  [ hide ]

public
Rubygem
Description: Merb Core: All you need. None you don't.
Homepage: http://www.merbivore.com
Clone URL: git://github.com/wycats/merb-core.git
Merged in new-sessions branch
fabien (author)
Sun Sep 07 09:41:29 -0700 2008
commit  2369da6c785948026e4c90a1e53ad2f485ee8c21
tree    152b17c6ff74bb11542e5068873e4e8e28224944
parent  3b6a8d5fdf5040cbb17890260e3a8fe67acf8b21
...
 
 
 
 
 
 
 
1
2
3
...
1
2
3
4
5
6
7
8
9
10
0
@@ -1,3 +1,10 @@
0
+8/20/2008:
0
+* Plugins that implement custom session stores should now conform to the base
0
+ class Merb::SessionStore and implement the stub methods defined there.
0
+* Merb::SessionMixin.finalize_session_exception_callbacks and
0
+ Merb::SessionMixin.persist_exception_callbacks are gone - implement
0
+ recovery strategies in the SessionStore subclass itself.
0
+
0
 6/18/2008:
0
 
0
 * Modified the public interface to Merb::Template.inline_template to accept a File or VirtualFile
...
18
19
20
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
22
23
...
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
0
@@ -18,6 +18,32 @@
0
   
0
   proc { a_controller_method }
0
 
0
+8/27/2008:
0
+* Merb::Request#protocol now returns valid protocol names: http, not http://.
0
+
0
+8/22/2008:
0
+* controller.cookies['foo'] = { ... } (Hash with options) is now deprecated;
0
+ use controller.cookies['foo'] = 'bar' for simple cookies without options, or
0
+ use controller.cookies.set_cookie('foo', 'bar', options) for more control.
0
+
0
+8/21/2008:
0
+* Memcached sessions are now configured by assignment to
0
+ Merb::MemcachedSession.store (previously the CACHE constant was used)
0
+* Added Merb::Config[:ignore_tampered_cookies] option to skip cookie warnings
0
+ during development. This defaults to 'on' in the development environment.
0
+* Merb::Config[:session_store] or Merb::Config[:session_stores] now accept an
0
+ Array (or String); when an Array is given, multiple session stores will be
0
+ available to the application.
0
+* If you have custom session stores (that inherit from Merb::SessionContainer)
0
+ be sure to require them in your init.rb
0
+
0
+8/20/2008:
0
+* Merb::Config[:session_cookie_domain] is now
0
+ Merb::Config[:default_cookie_domain]
0
+* Merb.registered_session_types is now Merb::Request.registered_session_types
0
+* When running in :development env, cookie-based sessions won't bother you
0
+ by raising TamperedWithCookie anymore.
0
+
0
 8/14/2008:
0
 * Merb.orm_generator_scope and friends are renamed.
0
 ** Merb.orm_generator_scope => Merb.orm
...
184
185
186
187
 
 
 
188
189
 
190
191
192
...
196
197
198
199
 
200
201
202
...
211
212
213
214
 
215
216
217
...
184
185
186
 
187
188
189
190
 
191
192
193
194
...
198
199
200
 
201
202
203
204
...
213
214
215
 
216
217
218
219
0
@@ -184,9 +184,11 @@ task :aok => [:specs, :rcov]
0
 def setup_specs(name, spec_cmd='spec', run_opts = "-c")
0
   desc "Run all specs (#{name})"
0
   task "specs:#{name}" do
0
- run_specs("spec/**/*_spec.rb", spec_cmd, ENV['RSPEC_OPTS'] || run_opts)
0
+ except = []
0
+ except += Dir["spec/**/memcache*_spec.rb"] if ENV['MEMCACHED'] == 'no'
0
+ run_specs("spec/**/*_spec.rb", spec_cmd, ENV['RSPEC_OPTS'] || run_opts, except)
0
   end
0
-
0
+
0
   desc "Run private specs (#{name})"
0
   task "specs:#{name}:private" do
0
     run_specs("spec/private/**/*_spec.rb", spec_cmd, ENV['RSPEC_OPTS'] || run_opts)
0
@@ -196,7 +198,7 @@ def setup_specs(name, spec_cmd='spec', run_opts = "-c")
0
   task "specs:#{name}:public" do
0
     run_specs("spec/public/**/*_spec.rb", spec_cmd, ENV['RSPEC_OPTS'] || run_opts)
0
   end
0
-
0
+
0
   # With profiling formatter
0
   desc "Run all specs (#{name}) with profiling formatter"
0
   task "specs:#{name}_profiled" do
0
@@ -211,7 +213,7 @@ def setup_specs(name, spec_cmd='spec', run_opts = "-c")
0
   desc "Run public specs (#{name}) with profiling formatter"
0
   task "specs:#{name}_profiled:public" do
0
     run_specs("spec/public/**/*_spec.rb", spec_cmd, "-c -f o")
0
- end
0
+ end
0
 end
0
 
0
 setup_specs("mri", "spec")
...
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
...
424
425
426
427
428
429
430
431
432
433
434
435
...
518
519
520
521
522
523
524
525
...
354
355
356
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
357
358
359
...
406
407
408
 
 
 
 
 
 
409
410
411
...
494
495
496
 
 
497
498
499
0
@@ -354,24 +354,6 @@ module Merb
0
 
0
     Merb.klass_hashes = []
0
 
0
- attr_reader :registered_session_types
0
-
0
- # ==== Parameters
0
- # name<~to_s>:: Name of the session type to register.
0
- # file<String>:: The file that defines this session type.
0
- # description<String>:: An optional description of the session type.
0
- #
0
- # ==== Notes
0
- # Merb currently supports memory, cookie and memcache session
0
- # types.
0
- def register_session_type(name, file, description = nil)
0
- @registered_session_types ||= Dictionary.new
0
- @registered_session_types[name] = {
0
- :file => file,
0
- :description => (description || "Using #{name} sessions")
0
- }
0
- end
0
-
0
     attr_accessor :frozen
0
 
0
     # ==== Returns
0
@@ -424,12 +406,6 @@ module Merb
0
     # :use_mutex<Boolean>:: turns action dispatch synchronization
0
     # on or off, default is on (true)
0
     #
0
- # :session_id_key<String>:: session identifier,
0
- # default is _session_id
0
- #
0
- # :session_store<String>:: session store to use (one of cookies,
0
- # memcache or memory)
0
- #
0
     # :log_delimiter<String>:: what Merb logger uses as delimiter
0
     # between message sections, default is " ~ "
0
     #
0
@@ -518,8 +494,6 @@ module Merb
0
     # environment "development"
0
     # log_level "debug"
0
     # use_mutex false
0
- # session_store "cookie"
0
- # session_secret_key "0d05a226affa226623eb18700"
0
     # exception_details true
0
     # reload_classes true
0
     # reload_time 0.5
...
5
6
7
8
9
10
11
...
16
17
18
19
20
21
22
...
5
6
7
 
8
9
10
...
15
16
17
 
18
19
20
0
@@ -5,7 +5,6 @@ module Merb
0
   autoload :Const, "merb-core/constants"
0
   autoload :ControllerMixin, "merb-core/controller/mixins/controller"
0
   autoload :ControllerExceptions, "merb-core/controller/exceptions"
0
- autoload :Cookies, "merb-core/dispatch/cookies"
0
   autoload :Dispatcher, "merb-core/dispatch/dispatcher"
0
   autoload :AuthenticationMixin, "merb-core/controller/mixins/authentication"
0
   autoload :BasicAuthenticationMixin, "merb-core/controller/mixins/authentication/basic"
0
@@ -16,7 +15,6 @@ module Merb
0
   autoload :Request, "merb-core/dispatch/request"
0
   autoload :ResponderMixin, "merb-core/controller/mixins/responder"
0
   autoload :Router, "merb-core/dispatch/router"
0
- autoload :SessionMixin, "merb-core/dispatch/session"
0
   autoload :Test, "merb-core/test"
0
   autoload :Worker, "merb-core/dispatch/worker"
0
 end
...
58
59
60
 
61
62
63
...
261
262
263
264
265
266
267
...
279
280
281
282
283
284
285
286
287
288
289
...
318
319
320
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
321
322
323
...
548
549
550
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
551
552
553
...
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
...
58
59
60
61
62
63
64
...
262
263
264
 
265
266
267
...
279
280
281
 
 
 
 
 
282
283
284
...
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
...
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
...
627
628
629
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
630
631
632
0
@@ -58,6 +58,7 @@ module Merb
0
 
0
       # Runs all boot loader classes by calling their run methods.
0
       def run
0
+ Merb.started = true
0
         subklasses = subclasses.dup
0
         until subclasses.empty?
0
           time = Time.now.to_i
0
@@ -261,7 +262,6 @@ class Merb::BootLoader::Dependencies < Merb::BootLoader
0
     enable_json_gem unless Merb::disabled?(:json)
0
     load_dependencies
0
     update_logger
0
- update_session_cookie_attributes
0
   end
0
 
0
   def self.load_dependencies
0
@@ -279,11 +279,6 @@ class Merb::BootLoader::Dependencies < Merb::BootLoader
0
     Merb::BootLoader::Logger.run if updated_logger_options != Merb.logger.init_args
0
   end
0
 
0
- def self.update_session_cookie_attributes
0
- Merb::Controller._session_expiry = Merb::Config[:session_expiry] || Merb::Const::WEEK * 2
0
- Merb::Controller._session_cookie_domain = Merb::Config[:session_cookie_domain]
0
- end
0
-
0
   private
0
 
0
     # Determines the path for the environment configuration file
0
@@ -318,6 +313,23 @@ class Merb::BootLoader::Dependencies < Merb::BootLoader
0
 
0
 end
0
 
0
+class Merb::BootLoader::MixinSession < Merb::BootLoader
0
+
0
+ # Mixin the session functionality; this is done before BeforeAppLoads
0
+ # so that SessionContainer and SessionStoreContainer can be subclassed by
0
+ # plugin session stores for example - these need to be loaded in a
0
+ # before_app_loads block or a BootLoader that runs after MixinSession.
0
+ #
0
+ # Note: access to Merb::Config is needed, so it needs to run after
0
+ # Merb::BootLoader::Dependencies is done.
0
+ def self.run
0
+ require 'merb-core/dispatch/session'
0
+ Merb::Controller.send(:include, ::Merb::SessionMixin)
0
+ Merb::Request.send(:include, ::Merb::SessionMixin::RequestMixin)
0
+ end
0
+
0
+end
0
+
0
 class Merb::BootLoader::BeforeAppLoads < Merb::BootLoader
0
 
0
   # Call any before_app_loads hooks that were registered via before_app_loads
0
@@ -548,6 +560,48 @@ class Merb::BootLoader::MimeTypes < Merb::BootLoader
0
   end
0
 end
0
 
0
+class Merb::BootLoader::Cookies < Merb::BootLoader
0
+
0
+ def self.run
0
+ require 'merb-core/dispatch/cookies'
0
+ Merb::Controller.send(:include, Merb::CookiesMixin)
0
+ Merb::Request.send(:include, Merb::CookiesMixin::RequestMixin)
0
+ end
0
+
0
+end
0
+
0
+class Merb::BootLoader::SetupSession < Merb::BootLoader
0
+
0
+ # Enable the configured session container(s); any class that inherits from
0
+ # SessionContainer will be considered by its session_store_type attribute.
0
+ def self.run
0
+ # Require all standard session containers.
0
+ Dir[Merb.framework_root / "merb-core" / "dispatch" / "session" / "*.rb"].each do |file|
0
+ base_name = File.basename(file, ".rb")
0
+ require file unless base_name == "container" || base_name == "store_container"
0
+ end
0
+
0
+ # Set some defaults.
0
+ Merb::Config[:session_id_key] ||= "_session_id"
0
+
0
+ # List of all session_stores from :session_stores and :session_store config options.
0
+ config_stores = Merb::Config.session_stores
0
+
0
+ # Register all configured session stores - any loaded session container class
0
+ # (subclassed from Merb::SessionContainer) will be available for registration.
0
+ Merb::SessionContainer.subclasses.each do |class_name|
0
+ if(store = Object.full_const_get(class_name)) &&
0
+ config_stores.include?(store.session_store_type)
0
+ Merb::Request.register_session_type(store.session_store_type, class_name)
0
+ end
0
+ end
0
+
0
+ # Mixin the Merb::Session module to add app-level functionality to sessions
0
+ Merb::SessionContainer.send(:include, Merb::Session)
0
+ end
0
+
0
+end
0
+
0
 class Merb::BootLoader::AfterAppLoads < Merb::BootLoader
0
 
0
   # Call any after_app_loads hooks that were registered via after_app_loads in
0
@@ -573,66 +627,6 @@ class Merb::BootLoader::SetupStubClasses < Merb::BootLoader
0
   end
0
 end
0
 
0
-class Merb::BootLoader::MixinSessionContainer < Merb::BootLoader
0
-
0
- # Mixin the correct session container.
0
- def self.run
0
- Merb.register_session_type('memory',
0
- Merb.framework_root / "merb-core" / "dispatch" / "session" / "memory",
0
- "Using in-memory sessions; sessions will be lost whenever the server stops.")
0
-
0
- Merb.register_session_type('memcache',
0
- Merb.framework_root / "merb-core" / "dispatch" / "session" / "memcached",
0
- "Using 'memcached' sessions")
0
-
0
- Merb.register_session_type('cookie', # Last session type becomes the default
0
- Merb.framework_root / "merb-core" / "dispatch" / "session" / "cookie",
0
- "Using 'share-nothing' cookie sessions (4kb limit per client)")
0
-
0
-
0
-
0
- Merb::Controller.class_eval do
0
- session_store = Merb::Config[:session_store].to_s
0
- if ["", "false", "none"].include?(session_store)
0
- Merb.logger.warn "Not Using Sessions"
0
- elsif reg = Merb.registered_session_types[session_store]
0
- Merb::BootLoader::MixinSessionContainer.check_for_secret_key if session_store == "cookie"
0
- Merb::BootLoader::MixinSessionContainer.check_for_session_id_key
0
- require reg[:file]
0
- include ::Merb::SessionMixin
0
- Merb.logger.warn reg[:description]
0
- else
0
- Merb.logger.warn "Session store not found, '#{Merb::Config[:session_store]}'."
0
- Merb.logger.warn "Defaulting to CookieStore Sessions"
0
- Merb::BootLoader::MixinSessionContainer.check_for_secret_key
0
- Merb::BootLoader::MixinSessionContainer.check_for_session_id_key
0
- require Merb.registered_session_types['cookie'][:file]
0
- include ::Merb::SessionMixin
0
- Merb.logger.warn "(plugin not installed?)"
0
- end
0
- end
0
-
0
- Merb.logger.flush
0
- end
0
-
0
- # Sets the controller session ID key if it has been set in config.
0
- def self.check_for_session_id_key
0
- if Merb::Config[:session_id_key]
0
- Merb::Controller._session_id_key = Merb::Config[:session_id_key]
0
- end
0
- end
0
-
0
- # Attempts to set the session secret key. This method will exit if the key
0
- # does not exist or is shorter than 16 charaters.
0
- def self.check_for_secret_key
0
- unless Merb::Config[:session_secret_key] && (Merb::Config[:session_secret_key].length >= 16)
0
- Merb.logger.warn("You must specify a session_secret_key in your init file, and it must be at least 16 characters\nbailing out...")
0
- exit!
0
- end
0
- Merb::Controller._session_secret_key = Merb::Config[:session_secret_key]
0
- end
0
-end
0
-
0
 class Merb::BootLoader::ChooseAdapter < Merb::BootLoader
0
 
0
   # Choose the Rack adapter/server to use and set Merb.adapter.
...
17
18
19
20
21
22
23
...
17
18
19
 
20
21
22
0
@@ -17,7 +17,6 @@ module Merb
0
           :environment => "development",
0
           :merb_root => Dir.pwd,
0
           :use_mutex => true,
0
- :session_id_key => "_session_id",
0
           :log_delimiter => " ~ ",
0
           :log_auto_flush => false,
0
           :log_level => :info,
...
98
99
100
 
101
102
103
...
113
114
115
 
116
117
118
...
217
218
219
220
 
221
222
223
...
228
229
230
231
 
232
233
234
...
238
239
240
241
 
242
243
244
...
260
261
262
263
 
 
 
264
265
266
...
412
413
414
415
416
417
418
419
420
421
422
423
424
425
...
98
99
100
101
102
103
104
...
114
115
116
117
118
119
120
...
219
220
221
 
222
223
224
225
...
230
231
232
 
233
234
235
236
...
240
241
242
 
243
244
245
246
...
262
263
264
 
265
266
267
268
269
270
...
416
417
418
 
 
 
 
 
 
 
 
419
420
421
0
@@ -98,6 +98,7 @@ class Merb::AbstractController
0
   
0
   class_inheritable_accessor :_layout, :_template_root, :template_roots
0
   class_inheritable_accessor :_before_filters, :_after_filters
0
+ class_inheritable_accessor :_before_dispatch_callbacks, :_after_dispatch_callbacks
0
 
0
   cattr_accessor :_abstract_subclasses
0
 
0
@@ -113,6 +114,7 @@ class Merb::AbstractController
0
   FILTER_OPTIONS = [:only, :exclude, :if, :unless, :with]
0
 
0
   self._before_filters, self._after_filters = [], []
0
+ self._before_dispatch_callbacks, self._after_dispatch_callbacks = [], []
0
 
0
   #---
0
   # We're using abstract_subclasses so that Merb::Controller can have its
0
@@ -217,7 +219,7 @@ class Merb::AbstractController
0
         include Object.full_const_get("#{helper_module_name}") rescue nil
0
       HERE
0
       super
0
- end
0
+ end
0
   end
0
   
0
   # ==== Parameters
0
@@ -228,7 +230,7 @@ class Merb::AbstractController
0
     @_template_stack = []
0
   end
0
   
0
- # This will dispatch the request, calling setup_session and finalize_session
0
+ # This will dispatch the request, calling internal before/after dispatch_callbacks
0
   #
0
   # ==== Parameters
0
   # action<~to_s>::
0
@@ -238,7 +240,7 @@ class Merb::AbstractController
0
   # ==== Raises
0
   # MerbControllerError:: Invalid body content caught.
0
   def _dispatch(action)
0
- setup_session
0
+ self._before_dispatch_callbacks.each { |cb| cb.call(self) }
0
     self.action_name = action
0
     
0
     caught = catch(:halt) do
0
@@ -260,7 +262,9 @@ class Merb::AbstractController
0
     start = Time.now
0
     _call_filters(_after_filters)
0
     @_benchmarks[:after_filters_time] = Time.now - start if _after_filters
0
- finalize_session
0
+
0
+ self._after_dispatch_callbacks.each { |cb| cb.call(self) }
0
+
0
     @body
0
   end
0
   
0
@@ -412,14 +416,6 @@ class Merb::AbstractController
0
   #---
0
   # Defaults that can be overridden by plugins, other mixins, or subclasses
0
   def _filters_halted() "<html><body><h1>Filter Chain Halted!</h1></body></html>" end
0
-
0
- # Method stub for setting up the session. This will be overriden by session
0
- # modules.
0
- def setup_session() end
0
-
0
- # Method stub for finalizing up the session. This will be overriden by
0
- # session modules.
0
- def finalize_session() end
0
   
0
   # ==== Parameters
0
   # name<~to_sym, Hash>:: The name of the URL to generate.
...
1
2
3
4
 
5
6
7
 
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
163
164
165
166
167
168
169
170
 
171
172
173
...
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
...
259
260
261
262
263
264
265
266
267
268
...
1
2
 
 
3
4
5
 
6
7
8
9
10
11
12
 
 
 
 
 
13
14
15
...
157
158
159
 
 
 
160
 
161
162
163
164
...
217
218
219
 
 
 
 
 
 
 
 
 
 
 
 
 
 
220
221
222
...
236
237
238
 
 
 
 
 
239
240
0
@@ -1,21 +1,15 @@
0
 class Merb::Controller < Merb::AbstractController
0
 
0
- class_inheritable_accessor :_hidden_actions, :_shown_actions,
0
- :_session_id_key, :_session_secret_key, :_session_expiry, :_session_cookie_domain
0
+ class_inheritable_accessor :_hidden_actions, :_shown_actions
0
 
0
   self._hidden_actions ||= []
0
- self._shown_actions ||= []
0
+ self._shown_actions ||= []
0
   
0
   cattr_accessor :_subclasses
0
   self._subclasses = Set.new
0
 
0
   def self.subclasses_list() _subclasses end
0
 
0
- self._session_secret_key = nil
0
- self._session_id_key = Merb::Config[:session_id_key] || '_session_id'
0
- self._session_expiry = Merb::Config[:session_expiry] || Merb::Const::WEEK * 2
0
- self._session_cookie_domain = Merb::Config[:session_cookie_domain]
0
-
0
   include Merb::ResponderMixin
0
   include Merb::ControllerMixin
0
   include Merb::AuthenticationMixin
0
@@ -163,11 +157,8 @@ class Merb::Controller < Merb::AbstractController
0
   # Sets the variables that came in through the dispatch as available to
0
   # the controller.
0
   #
0
- # This method uses the :session_id_cookie_only and :query_string_whitelist
0
- # configuration options. See CONFIG for more details.
0
- #
0
   # ==== Parameters
0
- # request<Merb::Request>:: The Merb::Request that came in from Mongrel.
0
+ # request<Merb::Request>:: The Merb::Request that came in from Rack.
0
   # status<Integer>:: An integer code for the status. Defaults to 200.
0
   # headers<Hash{header => value}>::
0
   # A hash of headers to start the controller with. These headers can be
0
@@ -226,20 +217,6 @@ class Merb::Controller < Merb::AbstractController
0
   # ==== Returns
0
   # Hash:: The parameters from the request object
0
   def params() request.params end
0
-
0
- # ==== Returns
0
- # Merb::Cookies::
0
- # A new Merb::Cookies instance representing the cookies that came in
0
- # from the request object
0
- #
0
- # ==== Notes
0
- # Headers are passed into the cookie object so that you can do:
0
- # cookies[:foo] = "bar"
0
- def cookies() @_cookies ||= _setup_cookies end
0
-
0
- # ==== Returns
0
- # Hash:: The session that was extracted from the request object.
0
- def session() request.session end
0
   
0
   # The results of the controller's render, to be returned to Rack.
0
   #
0
@@ -259,9 +236,4 @@ class Merb::Controller < Merb::AbstractController
0
   def _conditionally_append_extension(template, type)
0
     type && !template.match(/\.#{type.to_s.escape_regexp}$/) ? "#{template}.#{type}" : template
0
   end
0
-
0
- # Create a default cookie jar, and pre-set a fixation cookie if fixation is enabled.
0
- def _setup_cookies
0
- ::Merb::Cookies.new(request.cookies, @headers)
0
- end
0
 end
0
\ No newline at end of file
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 
 
 
 
 
 
16
17
 
 
 
18
19
 
20
21
22
23
24
 
 
 
 
 
 
25
26
 
 
 
27
28
29
 
 
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
 
 
 
 
 
 
58
59
 
60
61
62
...
64
65
66
67
68
69
70
71
72
73
74
75
76
77
 
78
79
80
81
82
83
 
84
85
86
87
88
89
90
91
92
93
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
 
 
 
 
 
 
 
 
 
 
 
95
96
97
 
 
 
 
98
99
100
101
102
103
104
105
106
107
108
109
110
111
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
 
113
...
1
2
 
 
 
 
 
 
 
 
 
 
 
 
 
3
4
5
6
7
8
9
 
10
11
12
13
14
15
16
 
 
 
 
17
18
19
20
21
22
23
 
24
25
26
27
28
 
29
30
31
32
 
33
34
35
36
37
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
39
40
41
42
43
44
 
45
46
47
48
...
50
51
52
 
 
 
 
 
 
 
 
 
 
 
53
54
55
 
 
 
 
56
57
 
 
 
 
 
 
 
 
 
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
 
 
88
89
90
91
92
 
 
 
 
 
 
 
 
 
 
 
 
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
0
@@ -1,62 +1,48 @@
0
 module Merb
0
 
0
- # Cookies are read and written through Merb::Controller#cookies. The cookies
0
- # you read are those received in request along with those that have been set
0
- # during the current request. The cookies you write will be sent out with the
0
- # response. Cookies are read by value (so you won't get the cookie object
0
- # itself back -- just the value it holds).
0
- class Cookies
0
-
0
- # ==== Parameters
0
- # request_cookies<Hash>:: Initial cookie store.
0
- # headers<Hash>:: The response headers.
0
- def initialize(request_cookies, headers)
0
- @_cookies = request_cookies
0
- @_headers = headers
0
+ class Cookies < Mash
0
+
0
+ def initialize(constructor = {}, cookie_defaults = {})
0
+ @_options_lookup = Mash.new
0
+ @_cookie_defaults = cookie_defaults
0
+ super constructor
0
     end
0
-
0
+
0
+ # Implicit assignment of cookie key and value.
0
+ #
0
     # ==== Parameters
0
     # name<~to_s>:: Name of the cookie.
0
+ # value<~to_s>:: Value of the cookie.
0
     #
0
- # ==== Returns
0
- # String:: Value of the cookie.
0
- def [](name)
0
- @_cookies[name]
0
+ # ==== Notes
0
+ # By using this method, a cookie key is marked for being
0
+ # included in the Set-Cookie response header.
0
+ def []=(key, value)
0
+ @_options_lookup[key] ||= {}
0
+ super
0
     end
0
-
0
+
0
+ # Explicit assignment of cookie key, value and options
0
+ #
0
     # ==== Parameters
0
     # name<~to_s>:: Name of the cookie.
0
- # options<Hash, ~to_s>:: Options for the cookie being set (see below).
0
+ # value<~to_s>:: Value of the cookie.
0
+ # options<Hash>:: Additional options for the cookie (see below).
0
     #
0
     # ==== Options (options)
0
- # :value<~to_s>:: Value of the cookie
0
     # :path<String>:: The path for which this cookie applies. Defaults to "/".
0
     # :expires<Time>:: Cookie expiry date.
0
     # :domain<String>:: The domain for which this cookie applies.
0
     # :secure<Boolean>:: Security flag.
0
     #
0
- # ==== Alternatives
0
- # If options is not a hash, it will be used as the cookie value directly.
0
- #
0
- # ==== Examples
0
- # cookies[:user] = "dave" # => Sets a simple session cookie
0
- # cookies[:token] = { :value => user.token, :expires => Time.now + 2.weeks }
0
- # # => Will set a cookie that expires in 2 weeks
0
- def []=(name, options)
0
- value = ''
0
-