Rails 中具有回退功能的动态命名空间控制器 [英] Dynamic namespaced controllers w/ fallback in Rails
问题描述
我对新的 Rails 应用程序有一个有点奇怪的需求.我需要构建一个应用程序,其中所有路由都定义在多个命名空间中(让我解释一下).我想要一个应用程序,其中学校科目(数学、英语等)是命名空间:
I have a somewhat bizarre requirement for a new Rails application. I need to build an application in which all routes are defined in multiple namespaces (let me explain). I want to have an application in which school subjects (math, english, etc) are the namespaces:
%w[math english].each do |subject|
namespace subject.to_sym do
resources :students
end
end
这很棒而且有效,但它需要我为每个主题创建一个命名空间 StudentsController
,这意味着如果我添加一个新主题,那么我需要创建一个新控制器.
This is great and it works but it requires me to create a namespaced StudentsController
for each subject which means if I add a new subject then I need to create a new controller.
我想要的是创建一个 Base::StudentsController
,如果 Math::StudentsController
存在,那么它将被使用,如果它不存在't 存在,那么我们可以动态创建这个控制器并继承自 Base::StudentsController
.
What I would like is to create a Base::StudentsController
and if, let's say the Math::StudentsController
exists then it will be used and if it doesn't exist, then we can dynamically create this controller and inherit from Base::StudentsController
.
这是可能的吗?如果是这样,那么我将如何实施?
Is this something that is possible? If so then how would I go about implementing this?
推荐答案
我最终将一些自定义逻辑写入了 ActionDispatch::Routing::RouteSet::Dispatcher.controller_reference
.我尝试查找给定控制器所需的所有常量,并在它们丢失时创建它们.此代码离完美远,因此请随时进行编辑和改进.
I ended up writing some custom logic into ActionDispatch::Routing::RouteSet::Dispatcher.controller_reference
. I attempt to look up all of the constants required for the given controller and create them if they're missing. This code is FAR from perfect so please feel free to edit w/ improvements.
class ActionDispatch::Routing::RouteSet::Dispatcher
private
def controller_reference(controller_param)
const_name = @controller_class_names[controller_param] ||= "#{controller_param.camelize}Controller"
obj = Object
const_name.split('::').each do |cn|
begin
obj = obj.const_get(cn)
rescue
if obj == Object
obj = obj.const_set(cn, Class.new(ApplicationController))
else
puts "Creating #{obj}::#{cn} based on Generic::#{cn}"
obj = obj.const_set(cn, Class.new("Generic::#{cn}".constantize))
end
end
end
ActiveSupport::Dependencies.constantize(const_name)
end
end
这篇关于Rails 中具有回退功能的动态命名空间控制器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!