Class: ActionController::Routing::Route
- Defined in:
- lib/action_controller/routing.rb
Overview
:nodoc:
Instance Attribute Summary collapse
-
#conditions ⇒ Object
Returns the value of attribute conditions.
-
#requirements ⇒ Object
Returns the value of attribute requirements.
-
#segments ⇒ Object
Returns the value of attribute segments.
Instance Method Summary collapse
-
#append_query_string(path, hash, query_keys = nil) ⇒ Object
Generate the query string with any extra keys in the hash and append it to the given path, returning the new path.
-
#build_query_string(hash, only_keys = nil) ⇒ Object
Build a query string from the keys of the given hash.
-
#defaults ⇒ Object
Return a hash of key/value pairs representing the keys in the route that have defaults, or which are specified by non-regexp requirements.
-
#extra_keys(hash, recall = {}) ⇒ Object
Determine which keys in the given hash are “extra”.
-
#generate(options, hash, expire_on = {}) ⇒ Object
Write the real generation implementation and then resend the message.
- #generate_extras(options, hash, expire_on = {}) ⇒ Object
-
#generation_extraction ⇒ Object
Build several lines of code that extract values from the options hash.
-
#generation_requirements ⇒ Object
Produce a condition expression that will check the requirements of this route upon generation.
- #generation_structure ⇒ Object
-
#initialize ⇒ Route
constructor
A new instance of Route.
- #matches_controller_and_action?(controller, action) ⇒ Boolean
-
#parameter_shell ⇒ Object
A route’s parameter shell contains parameter values that are not in the route’s path, but should be placed in the recognized hash.
-
#recognition_conditions ⇒ Object
Plugins may override this method to add other conditions, like checks on host, subdomain, and so forth.
-
#recognition_extraction ⇒ Object
Write the code to extract the parameters from a matched route.
-
#recognition_pattern(wrap = true) ⇒ Object
Build the regular expression pattern that will match this route.
-
#recognize(path, environment = {}) ⇒ Object
Write the real recognition implementation and then resend the message.
-
#significant_keys ⇒ Object
Return an array containing all the keys that are used in this route.
- #to_s ⇒ Object
-
#write_generation ⇒ Object
Write and compile a
generate
method for this Route. -
#write_recognition ⇒ Object
Write and compile a
recognize
method for this Route.
Constructor Details
#initialize ⇒ Route
Returns a new instance of Route.
322 323 324 325 326 |
# File 'lib/action_controller/routing.rb', line 322 def initialize @segments = [] @requirements = {} @conditions = {} end |
Instance Attribute Details
#conditions ⇒ Object
Returns the value of attribute conditions.
320 321 322 |
# File 'lib/action_controller/routing.rb', line 320 def conditions @conditions end |
#requirements ⇒ Object
Returns the value of attribute requirements.
320 321 322 |
# File 'lib/action_controller/routing.rb', line 320 def requirements @requirements end |
#segments ⇒ Object
Returns the value of attribute segments.
320 321 322 |
# File 'lib/action_controller/routing.rb', line 320 def segments @segments end |
Instance Method Details
#append_query_string(path, hash, query_keys = nil) ⇒ Object
Generate the query string with any extra keys in the hash and append it to the given path, returning the new path.
434 435 436 437 438 |
# File 'lib/action_controller/routing.rb', line 434 def append_query_string(path, hash, query_keys=nil) return nil unless path query_keys ||= extra_keys(hash) "#{path}#{build_query_string(hash, query_keys)}" end |
#build_query_string(hash, only_keys = nil) ⇒ Object
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.
454 455 456 457 458 459 460 461 462 463 |
# File 'lib/action_controller/routing.rb', line 454 def build_query_string(hash, only_keys = nil) elements = [] (only_keys || hash.keys).each do |key| if value = hash[key] elements << value.to_query(key) end end elements.empty? ? '' : "?#{elements.sort * '&'}" end |
#defaults ⇒ Object
Return a hash of key/value pairs representing the keys in the route that have defaults, or which are specified by non-regexp requirements.
499 500 501 502 503 504 505 506 507 508 509 510 |
# File 'lib/action_controller/routing.rb', line 499 def defaults @defaults ||= returning({}) do |hash| segments.each do |segment| next unless segment.respond_to? :default hash[segment.key] = segment.default unless segment.default.nil? end requirements.each do |key,req| next if Regexp === req || req.nil? hash[key] = req end end end |
#extra_keys(hash, recall = {}) ⇒ Object
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.)
446 447 448 |
# File 'lib/action_controller/routing.rb', line 446 def extra_keys(hash, recall={}) (hash || {}).keys.map { |k| k.to_sym } - (recall || {}).keys - significant_keys end |
#generate(options, hash, expire_on = {}) ⇒ Object
Write the real generation implementation and then resend the message.
422 423 424 425 |
# File 'lib/action_controller/routing.rb', line 422 def generate(, hash, expire_on = {}) write_generation generate , hash, expire_on end |
#generate_extras(options, hash, expire_on = {}) ⇒ Object
427 428 429 430 |
# File 'lib/action_controller/routing.rb', line 427 def generate_extras(, hash, expire_on = {}) write_generation generate_extras , hash, expire_on end |
#generation_extraction ⇒ Object
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.
357 358 359 360 361 |
# File 'lib/action_controller/routing.rb', line 357 def generation_extraction segments.collect do |segment| segment.extraction_code end.compact * "\n" end |
#generation_requirements ⇒ Object
Produce a condition expression that will check the requirements of this route upon generation.
365 366 367 368 369 370 371 372 373 374 375 |
# File 'lib/action_controller/routing.rb', line 365 def generation_requirements requirement_conditions = requirements.collect do |key, req| if req.is_a? Regexp value_regexp = Regexp.new "\\A#{req.source}\\Z" "hash[:#{key}] && #{value_regexp.inspect} =~ options[:#{key}]" else "hash[:#{key}] == #{req.inspect}" end end requirement_conditions * ' && ' unless requirement_conditions.empty? end |
#generation_structure ⇒ Object
376 377 378 |
# File 'lib/action_controller/routing.rb', line 376 def generation_structure segments.last.string_structure segments[0..-2] end |
#matches_controller_and_action?(controller, action) ⇒ Boolean
512 513 514 515 516 517 518 519 520 521 |
# File 'lib/action_controller/routing.rb', line 512 def matches_controller_and_action?(controller, action) unless @matching_prepared @controller_requirement = requirement_for(:controller) @action_requirement = requirement_for(:action) @matching_prepared = true end (@controller_requirement.nil? || @controller_requirement === controller) && (@action_requirement.nil? || @action_requirement === action) end |
#parameter_shell ⇒ Object
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, +=> ‘pages’, :action => ‘show’ is the shell for the route:
map.connect '/page/:id', :controller => 'pages', :action => 'show', :id => /\d+/
478 479 480 481 482 483 484 |
# File 'lib/action_controller/routing.rb', line 478 def parameter_shell @parameter_shell ||= returning({}) do |shell| requirements.each do |key, requirement| shell[key] = requirement unless requirement.is_a? Regexp end end end |
#recognition_conditions ⇒ Object
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.
395 396 397 398 399 |
# File 'lib/action_controller/routing.rb', line 395 def recognition_conditions result = ["(match = #{Regexp.new(recognition_pattern).inspect}.match(path))"] result << "conditions[:method] === env[:method]" if conditions[:method] result end |
#recognition_extraction ⇒ Object
Write the code to extract the parameters from a matched route.
411 412 413 414 415 416 417 418 419 |
# File 'lib/action_controller/routing.rb', line 411 def recognition_extraction next_capture = 1 extraction = segments.collect do |segment| x = segment.match_extraction next_capture next_capture += Regexp.new(segment.regexp_chunk).number_of_captures x end extraction.compact end |
#recognition_pattern(wrap = true) ⇒ Object
Build the regular expression pattern that will match this route.
402 403 404 405 406 407 408 |
# File 'lib/action_controller/routing.rb', line 402 def recognition_pattern(wrap = true) pattern = '' segments.reverse_each do |segment| pattern = segment.build_pattern pattern end wrap ? ("\\A" + pattern + "\\Z") : pattern end |
#recognize(path, environment = {}) ⇒ Object
Write the real recognition implementation and then resend the message.
466 467 468 469 |
# File 'lib/action_controller/routing.rb', line 466 def recognize(path, environment={}) write_recognition recognize path, environment end |
#significant_keys ⇒ Object
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.
489 490 491 492 493 494 495 |
# File 'lib/action_controller/routing.rb', line 489 def significant_keys @significant_keys ||= returning [] do |sk| segments.each { |segment| sk << segment.key if segment.respond_to? :key } sk.concat requirements.keys sk.uniq! end end |
#to_s ⇒ Object
523 524 525 526 527 528 |
# File 'lib/action_controller/routing.rb', line 523 def to_s @to_s ||= begin segs = segments.inject("") { |str,s| str << s.to_s } "%-6s %-40s %s" % [(conditions[:method] || :any).to_s.upcase, segs, requirements.inspect] end end |
#write_generation ⇒ Object
Write and compile a generate
method for this Route.
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 |
# File 'lib/action_controller/routing.rb', line 329 def write_generation # Build the main body of the generation body = "expired = false\n#{generation_extraction}\n#{generation_structure}" # If we have conditions that must be tested first, nest the body inside an if body = "if #{generation_requirements}\n#{body}\nend" if generation_requirements args = "options, hash, expire_on = {}" # Nest the body inside of a def block, and then compile it. raw_method = method_decl = "def generate_raw(#{args})\npath = begin\n#{body}\nend\n[path, hash]\nend" instance_eval method_decl, "generated code (#{__FILE__}:#{__LINE__})" # expire_on.keys == recall.keys; in other words, the keys in the expire_on hash # are the same as the keys that were recalled from the previous request. Thus, # we can use the expire_on.keys to determine which keys ought to be used to build # the query string. (Never use keys from the recalled request when building the # query string.) method_decl = "def generate(#{args})\npath, hash = generate_raw(options, hash, expire_on)\nappend_query_string(path, hash, extra_keys(options))\nend" instance_eval method_decl, "generated code (#{__FILE__}:#{__LINE__})" method_decl = "def generate_extras(#{args})\npath, hash = generate_raw(options, hash, expire_on)\n[path, extra_keys(options)]\nend" instance_eval method_decl, "generated code (#{__FILE__}:#{__LINE__})" raw_method end |
#write_recognition ⇒ Object
Write and compile a recognize
method for this Route.
381 382 383 384 385 386 387 388 389 390 |
# File 'lib/action_controller/routing.rb', line 381 def write_recognition # Create an if structure to extract the params from a match if it occurs. body = "params = parameter_shell.dup\n#{recognition_extraction * "\n"}\nparams" body = "if #{recognition_conditions.join(" && ")}\n#{body}\nend" # Build the method declaration and compile it method_decl = "def recognize(path, env={})\n#{body}\nend" instance_eval method_decl, "generated code (#{__FILE__}:#{__LINE__})" method_decl end |