route.rb 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. module Journey
  2. class Route
  3. attr_reader :app, :path, :verb, :defaults, :ip, :name
  4. attr_reader :constraints
  5. alias :conditions :constraints
  6. attr_accessor :precedence
  7. ##
  8. # +path+ is a path constraint.
  9. # +constraints+ is a hash of constraints to be applied to this route.
  10. def initialize name, app, path, constraints, defaults = {}
  11. constraints = constraints.dup
  12. @name = name
  13. @app = app
  14. @path = path
  15. @verb = constraints[:request_method] || //
  16. @ip = constraints.delete(:ip) || //
  17. @constraints = constraints
  18. @constraints.keep_if { |_,v| Regexp === v || String === v }
  19. @defaults = defaults
  20. @required_defaults = nil
  21. @required_parts = nil
  22. @parts = nil
  23. @decorated_ast = nil
  24. @precedence = 0
  25. end
  26. def ast
  27. return @decorated_ast if @decorated_ast
  28. @decorated_ast = path.ast
  29. @decorated_ast.grep(Nodes::Terminal).each { |n| n.memo = self }
  30. @decorated_ast
  31. end
  32. def requirements # :nodoc:
  33. # needed for rails `rake routes`
  34. path.requirements.merge(@defaults).delete_if { |_,v|
  35. /.+?/ == v
  36. }
  37. end
  38. def segments
  39. @path.names
  40. end
  41. def required_keys
  42. path.required_names.map { |x| x.to_sym } + required_defaults.keys
  43. end
  44. def score constraints
  45. required_keys = path.required_names
  46. supplied_keys = constraints.map { |k,v| v && k.to_s }.compact
  47. return -1 unless (required_keys - supplied_keys).empty?
  48. score = (supplied_keys & path.names).length
  49. score + (required_defaults.length * 2)
  50. end
  51. def parts
  52. @parts ||= segments.map { |n| n.to_sym }
  53. end
  54. alias :segment_keys :parts
  55. def format path_options
  56. (defaults.keys - required_parts).each do |key|
  57. path_options.delete key if defaults[key].to_s == path_options[key].to_s
  58. end
  59. formatter = Visitors::Formatter.new(path_options)
  60. formatted_path = formatter.accept(path.spec)
  61. formatted_path.gsub(/\/\x00/, '')
  62. end
  63. def optional_parts
  64. path.optional_names.map { |n| n.to_sym }
  65. end
  66. def required_parts
  67. @required_parts ||= path.required_names.map { |n| n.to_sym }
  68. end
  69. def required_defaults
  70. @required_defaults ||= begin
  71. matches = parts
  72. @defaults.dup.delete_if { |k,_| matches.include? k }
  73. end
  74. end
  75. end
  76. end