If this is a default_controller (i.e. a controller
specified by the user) we should raise an error in case it’s not found,
because it usually means a user error. However, if the controller
was retrieved through a dynamic segment, as in :controller(/:action),
we should simply return nil and delegate the control back to Rack cascade. Besides, if this is not a default
controller, it means we should respect the @scope[:module] parameter.

Possible with following snippet of code (for instance if each branch has
some different controller
logic, but if the controller
is not present, it should fallback to default controller).

Advantages are so we do not have to make blank inherited controllers and
routes for them, to do it with plain inheritance.

class ActionDispatch::Routing::RouteSet::CustomDispatcher<ActionDispatch::Routing::RouteSet::Dispatcher# These are the controllers that we should attempt fallbacks onFALLBACK_CONTROLLERS=/customer\/branch\/(projects|events)$/def controller(params,default_controller=true)# This defines when we want to attempt fallbacks patternsuperunlessparams[:branch_id]&&params[:controller].try(:match,FALLBACK_CONTROLLERS)controller_param=params[:controller]# Having these supplied, we handle controller evaluation by our own method...controller_reference_with_fallbacks(params[:branch_id],controller_param)rescueNameError=>eraiseActionController::RoutingError,e.message,e.backtraceifdefault_controllerendprivatedef controller_reference_with_fallbacks(branch_id,controller_param)# This is how fallbacks are evaluated controller_name="#{controller_param.sub('/branch', "/branch/#{branch_id}").camelize}Controller"controller=ActiveSupport::Dependencies.reference(controller_name)begincontroller.get(controller_name)rescueNameError=>e# If there is no specific class for given branch, fallback to original classcontroller_reference(controller_param)endendendActionDispatch::Routing::Mapper::Mapping.class_evaldoprivate# We do overwrite dispatcher class, that is used to evaluate controller classes from paramsdef appActionDispatch::Routing::Mapper::Constraints.new(to.respond_to?(:call)?to:::ActionDispatch::Routing::RouteSet::CustomDispatcher.new(:defaults=>defaults),blocks,@set.request_class)endend