Class ActionController::Routing::Route
In: vendor/rails/actionpack/lib/action_controller/routing.rb
Parent: Object

Methods

Attributes

conditions  [RW] 
requirements  [RW] 
segments  [RW] 

Public Class methods

[Source]

     # File vendor/rails/actionpack/lib/action_controller/routing.rb, line 310
310:       def initialize
311:         @segments = []
312:         @requirements = {}
313:         @conditions = {}
314:       end

Public Instance methods

Generate the query string with any extra keys in the hash and append it to the given path, returning the new path.

[Source]

     # File vendor/rails/actionpack/lib/action_controller/routing.rb, line 422
422:       def append_query_string(path, hash, query_keys=nil)
423:         return nil unless path
424:         query_keys ||= extra_keys(hash)
425:         "#{path}#{build_query_string(hash, query_keys)}"
426:       end

Build a query string from the keys of the given hash. If only_keys is given (as an array), only the keys indicated will be used to build the query string. The query string will correctly build array parameter values.

[Source]

     # File vendor/rails/actionpack/lib/action_controller/routing.rb, line 442
442:       def build_query_string(hash, only_keys=nil)
443:         elements = []
444: 
445:         only_keys ||= hash.keys
446:         
447:         only_keys.each do |key|
448:           value = hash[key] or next
449:           key = CGI.escape key.to_s
450:           if value.class == Array
451:             key <<  '[]'
452:           else    
453:             value = [ value ] 
454:           end     
455:           value.each { |val| elements << "#{key}=#{CGI.escape(val.to_param.to_s)}" }
456:         end     
457:         
458:         query_string = "?#{elements.join("&")}" unless elements.empty?
459:         query_string || ""
460:       end

Return a hash of key/value pairs representing the keys in the route that have defaults, or which are specified by non-regexp requirements.

[Source]

     # File vendor/rails/actionpack/lib/action_controller/routing.rb, line 496
496:       def defaults
497:         @defaults ||= returning({}) do |hash|
498:           segments.each do |segment|
499:             next unless segment.respond_to? :default
500:             hash[segment.key] = segment.default unless segment.default.nil?
501:           end
502:           requirements.each do |key,req|
503:             next if Regexp === req || req.nil?
504:             hash[key] = req
505:           end
506:         end
507:       end

Determine which keys in the given hash are "extra". Extra keys are those that were not used to generate a particular route. The extra keys also do not include those recalled from the prior request, nor do they include any keys that were implied in the route (like a :controller that is required, but not explicitly used in the text of the route.)

[Source]

     # File vendor/rails/actionpack/lib/action_controller/routing.rb, line 434
434:       def extra_keys(hash, recall={})
435:         (hash || {}).keys.map { |k| k.to_sym } - (recall || {}).keys - significant_keys
436:       end

Write the real generation implementation and then resend the message.

[Source]

     # File vendor/rails/actionpack/lib/action_controller/routing.rb, line 410
410:       def generate(options, hash, expire_on = {})
411:         write_generation
412:         generate options, hash, expire_on
413:       end

[Source]

     # File vendor/rails/actionpack/lib/action_controller/routing.rb, line 415
415:       def generate_extras(options, hash, expire_on = {})
416:         write_generation
417:         generate_extras options, hash, expire_on
418:       end

Build several lines of code that extract values from the options hash. If any of the values are missing or rejected then a return will be executed.

[Source]

     # File vendor/rails/actionpack/lib/action_controller/routing.rb, line 345
345:       def generation_extraction
346:         segments.collect do |segment|
347:           segment.extraction_code
348:         end.compact * "\n"
349:       end

Produce a condition expression that will check the requirements of this route upon generation.

[Source]

     # File vendor/rails/actionpack/lib/action_controller/routing.rb, line 353
353:       def generation_requirements
354:         requirement_conditions = requirements.collect do |key, req|
355:           if req.is_a? Regexp
356:             value_regexp = Regexp.new "\\A#{req.source}\\Z"
357:             "hash[:#{key}] && #{value_regexp.inspect} =~ options[:#{key}]"
358:           else
359:             "hash[:#{key}] == #{req.inspect}"
360:           end
361:         end
362:         requirement_conditions * ' && ' unless requirement_conditions.empty?
363:       end

[Source]

     # File vendor/rails/actionpack/lib/action_controller/routing.rb, line 364
364:       def generation_structure
365:         segments.last.string_structure segments[0..-2]
366:       end

[Source]

     # File vendor/rails/actionpack/lib/action_controller/routing.rb, line 509
509:       def matches_controller_and_action?(controller, action)
510:         unless @matching_prepared
511:           @controller_requirement = requirement_for(:controller)
512:           @action_requirement = requirement_for(:action)
513:           @matching_prepared = true
514:         end
515: 
516:         (@controller_requirement.nil? || @controller_requirement === controller) &&
517:         (@action_requirement.nil? || @action_requirement === action)
518:       end

A route’s parameter shell contains parameter values that are not in the route’s path, but should be placed in the recognized hash.

For example, +{:controller => ‘pages’, :action => ‘show’} is the shell for the route:

  map.connect '/page/:id', :controller => 'pages', :action => 'show', :id => /\d+/

[Source]

     # File vendor/rails/actionpack/lib/action_controller/routing.rb, line 475
475:       def parameter_shell
476:         @parameter_shell ||= returning({}) do |shell|
477:           requirements.each do |key, requirement|
478:             shell[key] = requirement unless requirement.is_a? Regexp
479:           end
480:         end
481:       end

Plugins may override this method to add other conditions, like checks on host, subdomain, and so forth. Note that changes here only affect route recognition, not generation.

[Source]

     # File vendor/rails/actionpack/lib/action_controller/routing.rb, line 383
383:       def recognition_conditions
384:         result = ["(match = #{Regexp.new(recognition_pattern).inspect}.match(path))"]
385:         result << "conditions[:method] === env[:method]" if conditions[:method]
386:         result
387:       end

Write the code to extract the parameters from a matched route.

[Source]

     # File vendor/rails/actionpack/lib/action_controller/routing.rb, line 399
399:       def recognition_extraction
400:         next_capture = 1
401:         extraction = segments.collect do |segment|
402:           x = segment.match_extraction next_capture
403:           next_capture += Regexp.new(segment.regexp_chunk).number_of_captures
404:           x
405:         end
406:         extraction.compact
407:       end

Build the regular expression pattern that will match this route.

[Source]

     # File vendor/rails/actionpack/lib/action_controller/routing.rb, line 390
390:       def recognition_pattern(wrap = true)
391:         pattern = ''
392:         segments.reverse_each do |segment|
393:           pattern = segment.build_pattern pattern
394:         end
395:         wrap ? ("\\A" + pattern + "\\Z") : pattern
396:       end

Write the real recognition implementation and then resend the message.

[Source]

     # File vendor/rails/actionpack/lib/action_controller/routing.rb, line 463
463:       def recognize(path, environment={})
464:         write_recognition
465:         recognize path, environment
466:       end

Return an array containing all the keys that are used in this route. This includes keys that appear inside the path, and keys that have requirements placed upon them.

[Source]

     # File vendor/rails/actionpack/lib/action_controller/routing.rb, line 486
486:       def significant_keys
487:         @significant_keys ||= returning [] do |sk|
488:           segments.each { |segment| sk << segment.key if segment.respond_to? :key }
489:           sk.concat requirements.keys
490:           sk.uniq!
491:         end
492:       end

[Source]

     # File vendor/rails/actionpack/lib/action_controller/routing.rb, line 520
520:       def to_s
521:         @to_s ||= begin
522:           segs = segments.inject("") { |str,s| str << s.to_s }
523:           "%-6s %-40s %s" % [(conditions[:method] || :any).to_s.upcase, segs, requirements.inspect]
524:         end
525:       end

Write and compile a generate method for this Route.

[Source]

     # File vendor/rails/actionpack/lib/action_controller/routing.rb, line 317
317:       def write_generation
318:         # Build the main body of the generation
319:         body = "not_expired = true\n#{generation_extraction}\n#{generation_structure}"
320:     
321:         # If we have conditions that must be tested first, nest the body inside an if
322:         body = "if #{generation_requirements}\n#{body}\nend" if generation_requirements
323:         args = "options, hash, expire_on = {}"
324: 
325:         # Nest the body inside of a def block, and then compile it.
326:         raw_method = method_decl = "def generate_raw(#{args})\npath = begin\n#{body}\nend\n[path, hash]\nend"
327:         instance_eval method_decl, "generated code (#{__FILE__}:#{__LINE__})"
328: 
329:         # expire_on.keys == recall.keys; in other words, the keys in the expire_on hash
330:         # are the same as the keys that were recalled from the previous request. Thus,
331:         # we can use the expire_on.keys to determine which keys ought to be used to build
332:         # the query string. (Never use keys from the recalled request when building the
333:         # query string.)
334: 
335:         method_decl = "def generate(#{args})\npath, hash = generate_raw(options, hash, expire_on)\nappend_query_string(path, hash, extra_keys(hash, expire_on))\nend"
336:         instance_eval method_decl, "generated code (#{__FILE__}:#{__LINE__})"
337: 
338:         method_decl = "def generate_extras(#{args})\npath, hash = generate_raw(options, hash, expire_on)\n[path, extra_keys(hash, expire_on)]\nend"
339:         instance_eval method_decl, "generated code (#{__FILE__}:#{__LINE__})"
340:         raw_method
341:       end

Write and compile a recognize method for this Route.

[Source]

     # File vendor/rails/actionpack/lib/action_controller/routing.rb, line 369
369:       def write_recognition
370:         # Create an if structure to extract the params from a match if it occurs.
371:         body = "params = parameter_shell.dup\n#{recognition_extraction * "\n"}\nparams"
372:         body = "if #{recognition_conditions.join(" && ")}\n#{body}\nend"
373:     
374:         # Build the method declaration and compile it
375:         method_decl = "def recognize(path, env={})\n#{body}\nend"
376:         instance_eval method_decl, "generated code (#{__FILE__}:#{__LINE__})"
377:         method_decl
378:       end

Protected Instance methods

[Source]

     # File vendor/rails/actionpack/lib/action_controller/routing.rb, line 528
528:       def requirement_for(key)
529:         return requirements[key] if requirements.key? key
530:         segments.each do |segment|
531:           return segment.regexp if segment.respond_to?(:key) && segment.key == key
532:         end
533:         nil
534:       end

[Validate]