@@ -14,7 +14,7 @@ def initialize(routes)
1414
1515 def generate ( name , options , path_parameters , parameterize = nil )
1616 constraints = path_parameters . merge ( options )
17- missing_keys = [ ]
17+ missing_keys = nil # need for variable scope
1818
1919 match_route ( name , constraints ) do |route |
2020 parameterized_parts = extract_parameterized_parts ( route , options , path_parameters , parameterize )
@@ -25,22 +25,22 @@ def generate(name, options, path_parameters, parameterize = nil)
2525 next unless name || route . dispatcher?
2626
2727 missing_keys = missing_keys ( route , parameterized_parts )
28- next unless missing_keys . empty ?
28+ next if missing_keys && missing_keys . any ?
2929 params = options . dup . delete_if do |key , _ |
3030 parameterized_parts . key? ( key ) || route . defaults . key? ( key )
3131 end
3232
3333 defaults = route . defaults
3434 required_parts = route . required_parts
35- parameterized_parts . delete_if do |key , value |
36- value . to_s == defaults [ key ] . to_s && ! required_parts . include? ( key )
35+ parameterized_parts . keep_if do |key , value |
36+ defaults [ key ] . nil? || value . to_s != defaults [ key ] . to_s || required_parts . include? ( key )
3737 end
3838
3939 return [ route . format ( parameterized_parts ) , params ]
4040 end
4141
4242 message = "No route matches #{ Hash [ constraints . sort_by { |k , v | k . to_s } ] . inspect } "
43- message << " missing required keys: #{ missing_keys . sort . inspect } " unless missing_keys . empty ?
43+ message << " missing required keys: #{ missing_keys . sort . inspect } " if missing_keys && missing_keys . any ?
4444
4545 raise ActionController ::UrlGenerationError , message
4646 end
@@ -54,12 +54,12 @@ def clear
5454 def extract_parameterized_parts ( route , options , recall , parameterize = nil )
5555 parameterized_parts = recall . merge ( options )
5656
57- keys_to_keep = route . parts . reverse . drop_while { |part |
57+ keys_to_keep = route . parts . reverse_each . drop_while { |part |
5858 !options . key? ( part ) || ( options [ part ] || recall [ part ] ) . nil?
5959 } | route . required_parts
6060
61- ( parameterized_parts . keys - keys_to_keep ) . each do |bad_key |
62- parameterized_parts . delete ( bad_key )
61+ parameterized_parts . delete_if do |bad_key , _ |
62+ ! keys_to_keep . include? ( bad_key )
6363 end
6464
6565 if parameterize
@@ -110,15 +110,36 @@ def non_recursive(cache, options)
110110 routes
111111 end
112112
113+ module RegexCaseComparator
114+ DEFAULT_INPUT = /[-_.a-zA-Z0-9]+\/ [-_.a-zA-Z0-9]+/
115+ DEFAULT_REGEX = /\A #{ DEFAULT_INPUT } \Z /
116+
117+ def self . ===( regex )
118+ DEFAULT_INPUT == regex
119+ end
120+ end
121+
113122 # Returns an array populated with missing keys if any are present.
114123 def missing_keys ( route , parts )
115- missing_keys = [ ]
124+ missing_keys = nil
116125 tests = route . path . requirements
117126 route . required_parts . each { |key |
118- if tests . key? ( key )
119- missing_keys << key unless /\A #{ tests [ key ] } \Z / === parts [ key ]
127+ case tests [ key ]
128+ when nil
129+ unless parts [ key ]
130+ missing_keys ||= [ ]
131+ missing_keys << key
132+ end
133+ when RegexCaseComparator
134+ unless RegexCaseComparator ::DEFAULT_REGEX === parts [ key ]
135+ missing_keys ||= [ ]
136+ missing_keys << key
137+ end
120138 else
121- missing_keys << key unless parts [ key ]
139+ unless /\A #{ tests [ key ] } \Z / === parts [ key ]
140+ missing_keys ||= [ ]
141+ missing_keys << key
142+ end
122143 end
123144 }
124145 missing_keys
0 commit comments