This file is indexed.

/usr/lib/ruby/vendor_ruby/merb-core/dispatch/router/behavior.rb is in ruby-merb-core 1.1.3+dfsg-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
 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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
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
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
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
module Merb
  
  class Router
    
    class Behavior
      
      class Error < StandardError; end
      
      # Proxy catches any methods and proxies them to the current behavior.
      # This allows building routes without constantly having to catching the
      # yielded behavior object
      # 
      # :api: private
      class Proxy
        
        # Undefine as many methods as possible so that everything can be proxied
        # along to the behavior
        instance_methods.each { |m| undef_method m unless %w[ object_id __id__ __send__ class kind_of? respond_to? assert_kind_of should should_not instance_variable_set instance_variable_get instance_eval].include?(m.to_s) }
        
        # :api: private
        def initialize
          @behaviors = []
        end
        
        # Puts a behavior on the bottom of the stack.
        # 
        # ==== Notes
        # The behaviors keep track of nested scopes.
        # 
        # :api: private
        def push(behavior)
          @behaviors.push(behavior)
        end
        
        # Removes the top-most behavior.
        # 
        # ==== Notes
        # This occurs at the end of a nested scope (namespace, etc).
        # 
        # :api: private
        def pop
          @behaviors.pop
        end
        
        # Tests whether the top-most behavior responds to the arguments.
        # 
        # ==== Notes
        # Behaviors contain the actual functionality of the proxy.
        # 
        # :api: private
        def respond_to?(*args)
          super || @behaviors.last.respond_to?(*args)
        end
        
        # Rake does some stuff with methods in the global namespace, so if I don't
        # explicitly define the Behavior methods to proxy here (specifically namespace)
        # Rake's methods take precedence.
        # 
        # Removing the following:
        # name full_name fixatable redirect
        %w(
          match to with register default defaults options option namespace identify
          default_routes defer defer_to capture resources resource
        ).each do |method|
          class_eval %{
            def #{method}(*args, &block)
              @behaviors.last.#{method}(*args, &block)
            end
          }
        end
        
        # == These methods are to be used in defer_to blocks
        
        # There are three possible ways to use this method.  First, if you have a named route, 
        # you can specify the route as the first parameter as a symbol and any paramters in a 
        # hash.  Second, you can generate the default route by just passing the params hash, 
        # just passing the params hash.  Finally, you can use the anonymous parameters.  This 
        # allows you to specify the parameters to a named route in the order they appear in the 
        # router.  
        #
        # ==== Parameters(Named Route)
        # name<Symbol>:: 
        #   The name of the route. 
        # args<Hash>:: 
        #   Parameters for the route generation.
        #
        # ==== Parameters(Default Route)
        # args<Hash>:: 
        #   Parameters for the route generation.  This route will use the default route. 
        #
        # ==== Parameters(Anonymous Parameters)
        # name<Symbol>::
        #   The name of the route.  
        # args<Array>:: 
        #   An array of anonymous parameters to generate the route
        #   with. These parameters are assigned to the route parameters
        #   in the order that they are passed.
        #
        # ==== Returns
        # String:: The generated URL.
        #
        # ==== Examples
        # Named Route
        #
        # Merb::Router.prepare do
        #   match("/articles/:title").to(:controller => :articles, :action => :show).name("articles")
        # end
        #
        # url(:articles, :title => "new_article")
        #
        # Default Route
        #
        # Merb::Router.prepare do
        #   default_routes
        # end
        #
        # url(:controller => "articles", :action => "new")
        #
        # Anonymous Paramters
        #
        # Merb::Router.prepare do
        #   match("/articles/:year/:month/:title").to(:controller => :articles, :action => :show).name("articles")
        # end
        #
        # url(:articles, 2008, 10, "test_article")
        #
        # :api: public
        def url(name, *args)
          args << {}
          Merb::Router.url(name, *args)
        end
        
        # Generates a Rack redirection response.
        # 
        # ==== Notes
        # Refer to Merb::Rack::Helpers.redirect for documentation.
        # 
        # :api: public
        def redirect(url, opts = {})
          Merb::Rack::Helpers.redirect(url, opts)
        end
        
        private
        
        # Proxies the method calls to the behavior.
        # 
        # ==== Notes
        # Please refer to:
        # http://ruby-doc.org/core/classes/Kernel.html#M005951
        # 
        # :api: private
        def method_missing(method, *args, &block)
          behavior = @behaviors.last
          
          if behavior.respond_to?(method)
            behavior.send(method, *args, &block)
          else
            super
          end
        end
      end
      
      # Behavior objects are used for the Route building DSL. Each object keeps
      # track of the current definitions for the level at which it is defined.
      # Each time a method is called on a Behavior object that accepts a block,
      # a new instance of the Behavior class is created.
      # 
      # ==== Parameters
      # 
      # proxy<Proxy>::
      #   This is the object initialized by Merb::Router.prepare that tracks the
      #   current Behavior object stack so that Behavior methods can be called
      #   without explicitly calling them on an instance of Behavior.
      # conditions<Hash>::
      #   The initial route conditions. See #match.
      # params<Hash>::
      #   The initial route parameters. See #to.
      # defaults<Hash>::
      #   The initial route default parameters. See #defaults.
      # options<Hash>::
      #   The initial route options. See #options.
      # blocks<Array>::
      #   The stack of deferred routing blocks for the route
      # 
      # ==== Returns
      # Behavior:: The initialized Behavior object
      # 
      # :api: private
      def initialize(proxy = nil, conditions = {}, params = {}, defaults = {}, identifiers = {}, options = {}, blocks = []) #:nodoc:
        @proxy       = proxy
        @conditions  = conditions
        @params      = params
        @defaults    = defaults
        @identifiers = identifiers
        @options     = options
        @blocks      = blocks
        
        stringify_condition_values
      end
      
      # Defines the +conditions+ that are required to match a Request. Each
      # +condition+ is applied to a method of the Request object. Conditions
      # can also be applied to segments of the +path+.
      # 
      # If #match is passed a block, it will create a new route scope with
      # the conditions passed to it and yield to the block such that all
      # routes that are defined in the block have the conditions applied
      # to them.
      # 
      # ==== Parameters
      # 
      # path<String, Regexp>::
      #   The pattern against which Merb::Request path is matched.
      # 
      #   When +path+ is a String, any substring that is wrapped in parenthesis
      #   is considered optional and any segment that begins with a colon, ex.:
      #   ":login", defines both a capture and a named param. Extra conditions
      #   can then be applied each named param individually.
      # 
      #   When +path+ is a Regexp, the pattern is left untouched and the
      #   Merb::Request path is matched against it as is.
      #
      #   +path+ is optional.
      # 
      # conditions<Hash>::
      #   Additional conditions that the request must meet in order to match.
      #   The keys must be the names of previously defined path segments or
      #   be methods that the Merb::Request instance will respond to.  The
      #   value is the string or regexp that matched the returned value.
      #   Conditions are inherited by child routes.
      # 
      # &block::
      #   All routes defined in the block will be scoped to the conditions
      #   defined by the #match method.
      # 
      # ==== Block parameters
      # r<Behavior>:: +optional+ - The match behavior object.
      # 
      # ==== Returns
      # Behavior::
      #   A new instance of Behavior with the specified path and conditions.
      # 
      # +Tip+: When nesting always make sure the most inner sub-match registers
      # a Route and doesn't just return new Behaviors.
      # 
      # ==== Examples
      # 
      #   # registers /foo/bar to controller => "foo", :action => "bar"
      #   # and /foo/baz to controller => "foo", :action => "baz"
      #   match("/foo") do
      #     match("/bar").to(:controller => "foo", :action => "bar")
      #     match("/baz").to(:controller => "foo", :action => "caz")
      #   end
      # 
      #   # Checks the format of the segments against the specified Regexp
      #   match("/:string/:number", :string => /[a-z]+/, :number => /\d+/).
      #     to(:controller => "string_or_numbers")
      # 
      #   # Equivalent to the default_route
      #   match("/:controller(/:action(:id))(.:format)").register
      # 
      #   #match only if the browser string contains MSIE or Gecko
      #   match("/foo", :user_agent => /(MSIE|Gecko)/ )
      #        .to(:controller => 'foo', :action => 'popular')
      # 
      #   # Route GET and POST requests to different actions (see also #resources)
      #   r.match('/foo', :method => :get).to(:action => 'show')
      #   r.match('/foo', :method => :post).to(:action => 'create')
      # 
      #   # match also takes regular expressions
      # 
      #   r.match(%r[/account/([a-z]{4,6})]).to(:controller => "account",
      #      :action => "show", :id => "[1]")
      # 
      #   r.match(%r{/?(en|es|fr|be|nl)?}).to(:language => "[1]") do
      #     match("/guides/:action/:id").to(:controller => "tour_guides")
      #   end
      # 
      # :api: public
      def match(path = {}, conditions = {}, &block)
        path, conditions = path[:path], path if path.is_a?(Hash)
        
        raise Error, "The route has already been committed. Further conditions cannot be specified" if @route
        
        conditions.delete_if { |k, v| v.nil? }
        conditions[:path] = merge_paths(path)
        
        behavior = Behavior.new(@proxy, @conditions.merge(conditions), @params, @defaults, @identifiers, @options, @blocks)
        with_behavior_context(behavior, &block)
      end
      
      # Creates a Route from one or more Behavior objects, unless a +block+ is
      # passed in.
      # 
      # ==== Parameters
      # params<Hash>:: The parameters the route maps to.
      # 
      # &block::
      #   All routes defined in the block will be scoped to the params
      #   defined by the #to method.
      # 
      # ==== Block parameters
      # r<Behavior>:: +optional+ - The to behavior object.
      # 
      # ==== Returns
      # Behavior:: The route definition behavior defining the created route
      # 
      # ==== Examples
      #   match('/:controller/:id).to(:action => 'show')
      # 
      #   to(:controller => 'simple') do
      #     match('/test').to(:action => 'index')
      #     match('/other').to(:action => 'other')
      #   end
      # 
      # :api: public
      def to(params = {}, &block)
        raise Error, "The route has already been committed. Further params cannot be specified" if @route
        
        behavior = Behavior.new(@proxy, @conditions, @params.merge(params), @defaults, @identifiers, @options, @blocks)
        
        if block_given?
          with_behavior_context(behavior, &block)
        else
          behavior.to_route
        end
      end
      
      # Equivalent of #to. Allows for some nicer syntax when scoping blocks
      # 
      # ==== Examples
      # Merb::Router.prepare do
      #   with(:controller => "users") do
      #     match("/signup").to(:action => "signup")
      #     match("/login").to(:action => "login")
      #     match("/logout").to(:action => "logout")
      #   end
      # end
      alias :with :to
      
      # Equivalent of #to. Allows for nicer syntax when registering routes with no params
      # 
      # ==== Examples
      # Merb::Router.prepare do
      #   match("/:controller(/:action(/:id))(.:format)").register
      # end
      alias :register :to
      
      # Sets default values for route parameters. If no value for the key
      # can be extracted from the request, then the value provided here
      # will be used.
      # 
      # ==== Parameters
      # defaults<Hash>::
      #   The default values for named segments.
      # 
      # &block::
      #   All routes defined in the block will be scoped to the defaults defined
      #   by the #default method.
      # 
      # ==== Block parameters
      # r<Behavior>:: +optional+ - The defaults behavior object.
      # 
      # :api: public
      def default(defaults = {}, &block)
        behavior = Behavior.new(@proxy, @conditions, @params, @defaults.merge(defaults), @identifiers, @options, @blocks)
        with_behavior_context(behavior, &block)
      end
      
      alias_method :defaults, :default
      
      # Allows the fine tuning of certain router options.
      # 
      # ==== Parameters
      # options<Hash>::
      #   The options to set for all routes defined in the scope. The currently
      #   supported options are:
      #   * :controller_prefix - The module that the controller is included in.
      #   * :name_prefix       - The prefix added to all routes named with #name
      # 
      # &block::
      #   All routes defined in the block will be scoped to the options defined
      #   by the #options method.
      # 
      # ==== Block parameters
      # r<Behavior>:: The options behavior object. This is optional
      # 
      # ==== Examples
      #   # If :group is not matched in the path, it will be "registered" instead
      #   # of nil.
      #   match("/users(/:group)").default(:group => "registered")
      # 
      # :api: public
      def options(opts = {}, &block)
        options = @options.dup
        
        opts.each_pair do |key, value|
          options[key] = (options[key] || []) + [value.freeze] if value
        end
        
        behavior = Behavior.new(@proxy, @conditions, @params, @defaults, @identifiers, options, @blocks)
        with_behavior_context(behavior, &block)
      end
      
      alias_method :options, :options
      
      # Creates a namespace for a route. This way you can have logical
      # separation to your routes.
      # 
      # ==== Parameters
      # name_or_path<String, Symbol>::
      #   The name or path of the namespace.
      # 
      # options<Hash>::
      #   Optional hash (see below)
      # 
      # &block::
      #   All routes defined in the block will be scoped to the namespace defined
      #   by the #namespace method.
      # 
      # ==== Options (opts)
      # :path<String>:: match against this url
      # 
      # ==== Block parameters
      # r<Behavior>:: The namespace behavior object. This is optional
      # 
      # ==== Examples
      #   namespace :admin do
      #     resources :accounts
      #     resource :email
      #   end
      # 
      #   # /super_admin/accounts
      #   namespace(:admin, :path=>"super_admin") do
      #     resources :accounts
      #   end
      # 
      # :api: public
      def namespace(name_or_path, opts = {}, &block)
        name = name_or_path.to_s # We don't want this modified ever
        path = opts.has_key?(:path) ? opts[:path] : name
        
        raise Error, "The route has already been committed. Further options cannot be specified" if @route
        
        # option keys could be nil
        opts[:controller_prefix] = name unless opts.has_key?(:controller_prefix)
        opts[:name_prefix]       = name unless opts.has_key?(:name_prefix)
        opts[:resource_prefix]   = opts[:name_prefix] unless opts.has_key?(:resource_prefix)
        
        behavior = self
        behavior = behavior.match("/#{path}") unless path.nil? || path.empty?
        behavior.options(opts, &block)
      end
      
      # Sets a method for instances of specified Classes to be called before
      # insertion into a route. This is useful when using models and want a
      # specific method to be called on it (For example, for ActiveRecord::Base
      # it would be #to_param).
      # 
      # The default method called on objects is #to_s.
      # 
      # ==== Paramters
      # identifiers<Hash>::
      #   The keys are Classes and the values are the method that instances of the specified
      #   class should have called on.
      # 
      # &block::
      #   All routes defined in the block will be call the specified methods during
      #   generation.
      # 
      # ==== Block parameters
      # r<Behavior>:: The identify behavior object. This is optional
      # 
      # :api: public
      def identify(identifiers = {}, &block)
        identifiers = if Hash === identifiers
          @identifiers.merge(identifiers)
        else
          { Object => identifiers }
        end
        
        behavior = Behavior.new(@proxy, @conditions, @params, @defaults, identifiers.freeze, @options, @blocks)
        with_behavior_context(behavior, &block)
      end
      
      # Creates the most common routes /:controller/:action/:id.format when
      # called with no arguments. You can pass a hash or a block to add parameters
      # or override the default behavior.
      # 
      # ==== Parameters
      # params<Hash>::
      #   This optional hash can be used to augment the default settings
      # 
      # &block::
      #   When passing a block a new behavior is yielded and more refinement is
      #   possible.
      # 
      # ==== Returns
      # Route:: the default route
      # 
      # ==== Examples
      # 
      #   # Passing an extra parameter "mode" to all matches
      #   r.default_routes :mode => "default"
      # 
      #   # specifying exceptions within a block
      #   r.default_routes do |nr|
      #     nr.defer_to do |request, params|
      #       nr.match(:protocol => "http://").to(:controller => "login",
      #         :action => "new") if request.env["REQUEST_URI"] =~ /\/private\//
      #     end
      #   end
      # 
      # :api: public
      def default_routes(params = {}, &block)
        match("/:controller(/:action(/:id))(.:format)").to(params, &block).name(:default)
      end
      
      # Takes a block and stores it for deferred conditional routes. The block
      # takes the +request+ object and the +params+ hash as parameters.
      # 
      # ==== Parameters
      # params<Hash>:: Parameters and conditions associated with this behavior.
      # &conditional_block::
      #   A block with the conditions to be met for the behavior to take
      #   effect.
      # 
      # ==== Returns
      # Route :: The default route.
      # 
      # ==== Note
      # The block takes two parameters, request and params. The params that
      # are passed into the block are *just* the placeholder params from the
      # route. If you want the full parsed params, use request.params.
      #
      # The rationale for this is that request.params is a fairly slow
      # operation, and if the full params parsing is not required, we would
      # rather not do the full parsing.
      # 
      # ==== Examples
      #   defer_to do |request, params|
      #     params.merge :controller => 'here',
      #       :action => 'there' if request.xhr?
      #   end
      # 
      # :api: public
      def defer_to(params = {}, &block)
        defer(block).to(params)
      end
      
      # Takes a Proc as a parameter and applies it as a deferred proc for all the
      # routes defined in the block. This is mostly interesting for plugin
      # developers.
      # 
      # ==== Examples
      #   defered_block = proc do |r, p|
      #     p.merge :controller => 'api/comments' if request.xhr?
      #   end
      #   defer(defered_block) do
      #     resources :comments
      #   end
      # 
      # :api: public
      def defer(deferred_block, &block)
        blocks = @blocks + [CachedProc.new(deferred_block)]
        behavior = Behavior.new(@proxy, @conditions, @params, @defaults, @identifiers, @options, blocks)
        with_behavior_context(behavior, &block)
      end
      
      # Registers the route as a named route with the name given.
      # 
      # ==== Parameters
      # symbol<Symbol>:: the name of the route.
      # 
      # ==== Raises
      # ArgumentError:: symbol is not a Symbol.
      # 
      # :api: public
      def name(prefix, name = nil)
        unless name
          name, prefix = prefix, nil
        end
        
        full_name([prefix, @options[:name_prefix], name].flatten.compact.join('_'))
      end
      
      # Names this route in Router. Name must be a Symbol. The current
      # name_prefix is ignored.
      #
      # ==== Parameters
      # symbol<Symbol>:: The name of the route.
      #
      # ==== Raises
      # ArgumentError:: symbol is not a Symbol.
      # 
      # :api: private
      def full_name(name)
        raise Error, ":this is reserved. Please pick another name." if name == :this
        
        if @route
          @route.name = name
          self
        else
          register.full_name(name)
        end
      end
      
      # Specifies that a route can be fixatable.
      # 
      # ==== Parameters
      # enabled<Boolean>:: True enables fixation on the route.
      # 
      # :api: public
      def fixatable(enable = true)
        @route.fixation = enable
        self
      end
      
      # Redirects the current route.
      # 
      # ==== Parameters
      # path<String>:: The path to redirect to.
      # 
      # options<Hash>::
      #   Options (see below)
      # 
      # ==== Options (opts)
      # :permanent<Boolean>::
      #   Whether or not the redirect should be permanent.
      #   The default value is false.
      # 
      # :api: public
      def redirect(url, opts = {})
        raise Error, "The route has already been committed." if @route
        
        status = opts[:permanent] ? 301 : 302
        @route = Route.new(@conditions, {:url => url.freeze, :status => status.freeze}, @blocks, :redirects => true)
        @route.register
        self
      end
      
      # Capture any new routes that have been added within the block.
      #
      # This utility method lets you track routes that have been added;
      # it doesn't affect how/which routes are added.
      #
      # &block:: A context in which routes are generated.
      # 
      # :api: public
      def capture(&block)
        captured_routes = {}
        name_prefix     = [@options[:name_prefix]].flatten.compact.map { |p| "#{p}_"}
        current_names   = Merb::Router.named_routes.keys
        
        behavior = Behavior.new(@proxy, @conditions, @params, @defaults, @identifiers, @options, @blocks)
        with_behavior_context(behavior, &block)
        
        Merb::Router.named_routes.reject { |k,v| current_names.include?(k) }.each do |name, route|
          name = route.name.to_s.sub(/^#{name_prefix.join('|')}/, '').to_sym unless name_prefix.empty?
          captured_routes[name] = route
        end
        
        captured_routes
      end
      
      # Proxy routes with the default behaviors.
      # 
      # ==== Parameters
      # &block:: defines routes within the provided context.
      # 
      # :api: private
      def _with_proxy(&block)
        proxy = Proxy.new
        proxy.push Behavior.new(proxy, @conditions, @params, @defaults, @identifiers, @options, @blocks)
        proxy.instance_eval(&block)
        proxy
      end
      
      protected
      
      # Returns the current route.
      # 
      # ==== Returns
      # Route:: the route.
      # 
      # :api: private
      def _route
        @route
      end
      
      # Turns a route definition into a Route object.
      # 
      # ==== Returns
      # Route:: the route generated.
      # 
      # :api: private
      def to_route
        raise Error, "The route has already been committed." if @route
        
        controller = @params[:controller]
        
        if prefixes = @options[:controller_prefix]
          controller ||= ":controller"
          
          prefixes.reverse_each do |prefix|
            break if controller =~ %r{^/(.*)} && controller = $1
            controller = "#{prefix}/#{controller}"
          end
        end
        
        @params.merge!(:controller => controller.to_s.gsub(%r{^/}, '')) if controller

        # Normalise action into a string
        @params[:action] = @params[:action].to_s if @params.has_key?(:action)
        
        # Sorts the identifiers so that modules that are at the bottom of the
        # inheritance chain come first (more specific modules first). Object
        # should always be last.
        identifiers = @identifiers.sort { |(first,_),(sec,_)| first <=> sec || 1 }
        
        @route = Route.new(@conditions.dup,@params, @blocks, :defaults => @defaults.dup, :identifiers => identifiers)
        
        if before = @options[:before] && @options[:before].last
          @route.register_at(Router.routes.index(before))
        else
          @route.register
        end
        self
      end
      
      # Allows to insert the route at a certain spot in the list of routes
      # instead of appending to the list.
      # 
      # ==== Params
      # route<Route>:: the route to insert before.
      # &block:: the route definition to insert.
      # 
      # :api: plugin
      def before(route, &block)
        options(:before => route, &block)
      end
      
      private
      
      # Takes @conditions and turns values into strings (except for Regexp and
      # Array values).
      # 
      # :api: private
      def stringify_condition_values # :nodoc:
        @conditions.each do |key, value|
          unless value.nil? || Regexp === value || Array === value
            @conditions[key] = value.to_s
          end
        end
      end
      
      # Creates a new context with a given behavior for the route definition in
      # the block.
      # 
      # ==== Params
      # behavior<Behavior>:: the behavior to proxy the calls in the block.
      # &block:: the routing definitions to be nested within the behavior.
      # 
      # ==== Returns
      # Behavior:: the behavior wrapping.
      # 
      # :api: private
      def with_behavior_context(behavior, &block) # :nodoc:
        if block_given?
          @proxy.push(behavior)
          retval = yield(behavior)
          @proxy.pop
        end
        behavior
      end
      
      # Merges the path elements together into an array to be joined for
      # generating named routes.
      # 
      # ==== Parameters
      # path<String>:: the path to merge at the end.
      # 
      # ==== Returns
      # Array:: array of path elements.
      # 
      # ==== Notes
      # An array of ['a', 'b'] (the 'a' namespace with the 'b' action) will
      # produce a name of :a_b.
      # 
      # :api: private
      def merge_paths(path) # :nodoc:
        [@conditions[:path], path.freeze].flatten.compact
      end
      
    end
  end
end