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.
311 312 313 314 315 |
# File 'lib/action_controller/routing.rb', line 311 def initialize @segments = [] @requirements = {} @conditions = {} end |
Instance Attribute Details
#conditions ⇒ Object
Returns the value of attribute conditions.
309 310 311 |
# File 'lib/action_controller/routing.rb', line 309 def conditions @conditions end |
#requirements ⇒ Object
Returns the value of attribute requirements.
309 310 311 |
# File 'lib/action_controller/routing.rb', line 309 def requirements @requirements end |
#segments ⇒ Object
Returns the value of attribute segments.
309 310 311 |
# File 'lib/action_controller/routing.rb', line 309 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.
423 424 425 426 427 |
# File 'lib/action_controller/routing.rb', line 423 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.
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 |
# File 'lib/action_controller/routing.rb', line 443 def build_query_string(hash, only_keys=nil) elements = [] only_keys ||= hash.keys only_keys.each do |key| value = hash[key] or next key = CGI.escape key.to_s if value.class == Array key << '[]' else value = [ value ] end value.each { |val| elements << "#{key}=#{CGI.escape(val.to_param.to_s)}" } end query_string = "?#{elements.join("&")}" unless elements.empty? query_string || "" 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.
497 498 499 500 501 502 503 504 505 506 507 508 |
# File 'lib/action_controller/routing.rb', line 497 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.)
435 436 437 |
# File 'lib/action_controller/routing.rb', line 435 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.
411 412 413 414 |
# File 'lib/action_controller/routing.rb', line 411 def generate(, hash, expire_on = {}) write_generation generate , hash, expire_on end |
#generate_extras(options, hash, expire_on = {}) ⇒ Object
416 417 418 419 |
# File 'lib/action_controller/routing.rb', line 416 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.
346 347 348 349 350 |
# File 'lib/action_controller/routing.rb', line 346 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.
354 355 356 357 358 359 360 361 362 363 364 |
# File 'lib/action_controller/routing.rb', line 354 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
365 366 367 |
# File 'lib/action_controller/routing.rb', line 365 def generation_structure segments.last.string_structure segments[0..-2] end |
#matches_controller_and_action?(controller, action) ⇒ Boolean
510 511 512 513 514 515 516 517 518 519 |
# File 'lib/action_controller/routing.rb', line 510 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+/
476 477 478 479 480 481 482 |
# File 'lib/action_controller/routing.rb', line 476 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.
384 385 386 387 388 |
# File 'lib/action_controller/routing.rb', line 384 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.
400 401 402 403 404 405 406 407 408 |
# File 'lib/action_controller/routing.rb', line 400 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.
391 392 393 394 395 396 397 |
# File 'lib/action_controller/routing.rb', line 391 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.
464 465 466 467 |
# File 'lib/action_controller/routing.rb', line 464 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.
487 488 489 490 491 492 493 |
# File 'lib/action_controller/routing.rb', line 487 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
521 522 523 524 525 526 |
# File 'lib/action_controller/routing.rb', line 521 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.
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 |
# File 'lib/action_controller/routing.rb', line 318 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(hash, expire_on))\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(hash, expire_on)]\nend" instance_eval method_decl, "generated code (#{__FILE__}:#{__LINE__})" raw_method end |
#write_recognition ⇒ Object
Write and compile a recognize
method for this Route.
370 371 372 373 374 375 376 377 378 379 |
# File 'lib/action_controller/routing.rb', line 370 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 |