Class: ActionController::Routing::RouteSet
- Defined in:
- lib/action_controller/routing.rb
Overview
:nodoc:
Defined Under Namespace
Classes: Mapper, NamedRouteCollection
Instance Attribute Summary collapse
-
#named_routes ⇒ Object
Returns the value of attribute named_routes.
-
#routes ⇒ Object
Returns the value of attribute routes.
Instance Method Summary collapse
- #add_named_route(name, path, options = {}) ⇒ Object
- #add_route(path, options = {}) ⇒ Object
- #build_expiry(options, recall) ⇒ Object
-
#builder ⇒ Object
Subclasses and plugins may override this method to specify a different RouteBuilder instance, so that other route DSL’s can be created.
- #clear! ⇒ Object
- #draw {|Mapper.new(self)| ... } ⇒ Object
- #empty? ⇒ Boolean
-
#extra_keys(options, recall = {}) ⇒ Object
Generate the path indicated by the arguments, and return an array of the keys that were not used to generate it.
-
#extract_request_environment(request) ⇒ Object
Subclasses and plugins may override this method to extract further attributes from the request, for use by route conditions and such.
- #generate(options, recall = {}, method = :generate) ⇒ Object
- #generate_extras(options, recall = {}) ⇒ Object
-
#initialize ⇒ RouteSet
constructor
A new instance of RouteSet.
- #install_helpers(destinations = [ActionController::Base, ActionView::Base], regenerate_code = false) ⇒ Object
- #load! ⇒ Object (also: #reload!)
- #load_routes! ⇒ Object
- #options_as_params(options) ⇒ Object
-
#raise_named_route_error(options, named_route, named_route_name) ⇒ Object
try to give a helpful error message when named route generation fails.
- #recognize(request) ⇒ Object
- #recognize_path(path, environment = {}) ⇒ Object
- #reload ⇒ Object
- #routes_by_controller ⇒ Object
- #routes_for(options, merged, expire_on) ⇒ Object
- #routes_for_controller_and_action(controller, action) ⇒ Object
- #routes_for_controller_and_action_and_keys(controller, action, keys) ⇒ Object
Constructor Details
#initialize ⇒ RouteSet
Returns a new instance of RouteSet.
1237 1238 1239 1240 |
# File 'lib/action_controller/routing.rb', line 1237 def initialize self.routes = [] self.named_routes = NamedRouteCollection.new end |
Instance Attribute Details
#named_routes ⇒ Object
Returns the value of attribute named_routes.
1235 1236 1237 |
# File 'lib/action_controller/routing.rb', line 1235 def named_routes @named_routes end |
#routes ⇒ Object
Returns the value of attribute routes.
1235 1236 1237 |
# File 'lib/action_controller/routing.rb', line 1235 def routes @routes end |
Instance Method Details
#add_named_route(name, path, options = {}) ⇒ Object
1306 1307 1308 1309 1310 |
# File 'lib/action_controller/routing.rb', line 1306 def add_named_route(name, path, = {}) # TODO - is options EVER used? name = [:name_prefix] + name.to_s if [:name_prefix] named_routes[name.to_sym] = add_route(path, ) end |
#add_route(path, options = {}) ⇒ Object
1300 1301 1302 1303 1304 |
# File 'lib/action_controller/routing.rb', line 1300 def add_route(path, = {}) route = builder.build(path, ) routes << route route end |
#build_expiry(options, recall) ⇒ Object
1330 1331 1332 1333 1334 1335 |
# File 'lib/action_controller/routing.rb', line 1330 def build_expiry(, recall) recall.inject({}) do |expiry, (key, recalled_value)| expiry[key] = (.key?(key) && [key].to_param != recalled_value.to_param) expiry end end |
#builder ⇒ Object
Subclasses and plugins may override this method to specify a different RouteBuilder instance, so that other route DSL’s can be created.
1244 1245 1246 |
# File 'lib/action_controller/routing.rb', line 1244 def builder @builder ||= RouteBuilder.new end |
#clear! ⇒ Object
1254 1255 1256 1257 1258 1259 |
# File 'lib/action_controller/routing.rb', line 1254 def clear! routes.clear named_routes.clear @combined_regexp = nil @routes_by_controller = nil end |
#draw {|Mapper.new(self)| ... } ⇒ Object
1248 1249 1250 1251 1252 |
# File 'lib/action_controller/routing.rb', line 1248 def draw clear! yield Mapper.new(self) install_helpers end |
#empty? ⇒ Boolean
1266 1267 1268 |
# File 'lib/action_controller/routing.rb', line 1266 def empty? routes.empty? end |
#extra_keys(options, recall = {}) ⇒ Object
Generate the path indicated by the arguments, and return an array of the keys that were not used to generate it.
1339 1340 1341 |
# File 'lib/action_controller/routing.rb', line 1339 def extra_keys(, recall={}) generate_extras(, recall).last end |
#extract_request_environment(request) ⇒ Object
Subclasses and plugins may override this method to extract further attributes from the request, for use by route conditions and such.
1482 1483 1484 |
# File 'lib/action_controller/routing.rb', line 1482 def extract_request_environment(request) { :method => request.method } end |
#generate(options, recall = {}, method = :generate) ⇒ Object
1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 |
# File 'lib/action_controller/routing.rb', line 1347 def generate(, recall = {}, method=:generate) named_route_name = .delete(:use_route) generate_all = .delete(:generate_all) if named_route_name named_route = named_routes[named_route_name] = named_route.parameter_shell.merge() end = () expire_on = build_expiry(, recall) if [:controller] [:controller] = [:controller].to_s end # if the controller has changed, make sure it changes relative to the # current controller module, if any. In other words, if we're currently # on admin/get, and the new controller is 'set', the new controller # should really be admin/set. if !named_route && expire_on[:controller] && [:controller] && [:controller][0] != ?/ old_parts = recall[:controller].split('/') new_parts = [:controller].split('/') parts = old_parts[0..-(new_parts.length + 1)] + new_parts [:controller] = parts.join('/') end # drop the leading '/' on the controller name [:controller] = [:controller][1..-1] if [:controller] && [:controller][0] == ?/ merged = recall.merge() if named_route path = named_route.generate(, merged, expire_on) if path.nil? raise_named_route_error(, named_route, named_route_name) else return path end else merged[:action] ||= 'index' [:action] ||= 'index' controller = merged[:controller] action = merged[:action] raise RoutingError, "Need controller and action!" unless controller && action if generate_all # Used by caching to expire all paths for a resource return routes.collect do |route| route.send!(method, , merged, expire_on) end.compact end # don't use the recalled keys when determining which routes to check routes = routes_by_controller[controller][action][.keys.sort_by { |x| x.object_id }] routes.each do |route| results = route.send!(method, , merged, expire_on) return results if results && (!results.is_a?(Array) || results.first) end end raise RoutingError, "No route matches #{.inspect}" end |
#generate_extras(options, recall = {}) ⇒ Object
1343 1344 1345 |
# File 'lib/action_controller/routing.rb', line 1343 def generate_extras(, recall={}) generate(, recall, :generate_extras) end |
#install_helpers(destinations = [ActionController::Base, ActionView::Base], regenerate_code = false) ⇒ Object
1261 1262 1263 1264 |
# File 'lib/action_controller/routing.rb', line 1261 def install_helpers(destinations = [ActionController::Base, ActionView::Base], regenerate_code = false) Array(destinations).each { |d| d.module_eval { include Helpers } } named_routes.install(destinations, regenerate_code) end |
#load! ⇒ Object Also known as: reload!
1270 1271 1272 1273 1274 1275 |
# File 'lib/action_controller/routing.rb', line 1270 def load! Routing.use_controllers! nil # Clear the controller cache so we may discover new ones clear! load_routes! install_helpers end |
#load_routes! ⇒ Object
1291 1292 1293 1294 1295 1296 1297 1298 |
# File 'lib/action_controller/routing.rb', line 1291 def load_routes! if defined?(RAILS_ROOT) && defined?(::ActionController::Routing::Routes) && self == ::ActionController::Routing::Routes load File.join("#{RAILS_ROOT}/config/routes.rb") @routes_last_modified = File.stat("#{RAILS_ROOT}/config/routes.rb").mtime else add_route ":controller/:action/:id" end end |
#options_as_params(options) ⇒ Object
1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 |
# File 'lib/action_controller/routing.rb', line 1312 def () # If an explicit :controller was given, always make :action explicit # too, so that action expiry works as expected for things like # # generate({:controller => 'content'}, {:controller => 'content', :action => 'show'}) # # (the above is from the unit tests). In the above case, because the # controller was explicitly given, but no action, the action is implied to # be "index", not the recalled action of "show". # # great fun, eh? = .clone [:action] ||= 'index' if [:controller] [:action] = [:action].to_s if [:action] end |
#raise_named_route_error(options, named_route, named_route_name) ⇒ Object
try to give a helpful error message when named route generation fails
1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 |
# File 'lib/action_controller/routing.rb', line 1412 def raise_named_route_error(, named_route, named_route_name) diff = named_route.requirements.diff() unless diff.empty? raise RoutingError, "#{named_route_name}_url failed to generate from #{.inspect}, expected: #{named_route.requirements.inspect}, diff: #{named_route.requirements.diff().inspect}" else required_segments = named_route.segments.select {|seg| (!seg.optional?) && (!seg.is_a?(DividerSegment)) } required_keys_or_values = required_segments.map { |seg| seg.key rescue seg.value } # we want either the key or the value from the segment raise RoutingError, "#{named_route_name}_url failed to generate from #{.inspect} - you may have ambiguous routes, or you may need to supply additional parameters for this route. content_url has the following required parameters: #{required_keys_or_values.inspect} - are they all satisfied?" end end |
#recognize(request) ⇒ Object
1423 1424 1425 1426 1427 |
# File 'lib/action_controller/routing.rb', line 1423 def recognize(request) params = recognize_path(request.path, extract_request_environment(request)) request.path_parameters = params.with_indifferent_access "#{params[:controller].camelize}Controller".constantize end |
#recognize_path(path, environment = {}) ⇒ Object
1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 |
# File 'lib/action_controller/routing.rb', line 1429 def recognize_path(path, environment={}) routes.each do |route| result = route.recognize(path, environment) and return result end allows = HTTP_METHODS.select { |verb| routes.find { |r| r.recognize(path, :method => verb) } } if environment[:method] && !HTTP_METHODS.include?(environment[:method]) raise NotImplemented.new(*allows) elsif !allows.empty? raise MethodNotAllowed.new(*allows) else raise RoutingError, "No route matches #{path.inspect} with #{environment.inspect}" end end |
#reload ⇒ Object
1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 |
# File 'lib/action_controller/routing.rb', line 1280 def reload if @routes_last_modified && defined?(RAILS_ROOT) mtime = File.stat("#{RAILS_ROOT}/config/routes.rb").mtime # if it hasn't been changed, then just return return if mtime == @routes_last_modified # if it has changed then record the new time and fall to the load! below @routes_last_modified = mtime end load! end |
#routes_by_controller ⇒ Object
1445 1446 1447 1448 1449 1450 1451 1452 1453 |
# File 'lib/action_controller/routing.rb', line 1445 def routes_by_controller @routes_by_controller ||= Hash.new do |controller_hash, controller| controller_hash[controller] = Hash.new do |action_hash, action| action_hash[action] = Hash.new do |key_hash, keys| key_hash[keys] = routes_for_controller_and_action_and_keys(controller, action, keys) end end end end |
#routes_for(options, merged, expire_on) ⇒ Object
1455 1456 1457 1458 1459 1460 1461 1462 |
# File 'lib/action_controller/routing.rb', line 1455 def routes_for(, merged, expire_on) raise "Need controller and action!" unless controller && action controller = merged[:controller] merged = if expire_on[:controller] action = merged[:action] || 'index' routes_by_controller[controller][action][merged.keys] end |
#routes_for_controller_and_action(controller, action) ⇒ Object
1464 1465 1466 1467 1468 1469 |
# File 'lib/action_controller/routing.rb', line 1464 def routes_for_controller_and_action(controller, action) selected = routes.select do |route| route.matches_controller_and_action? controller, action end (selected.length == routes.length) ? routes : selected end |
#routes_for_controller_and_action_and_keys(controller, action, keys) ⇒ Object
1471 1472 1473 1474 1475 1476 1477 1478 |
# File 'lib/action_controller/routing.rb', line 1471 def routes_for_controller_and_action_and_keys(controller, action, keys) selected = routes.select do |route| route.matches_controller_and_action? controller, action end selected.sort_by do |route| (keys - route.significant_keys).length end end |