I have overrode Rails' ActionDispatch::Routing::RouteSet::Dispatcher.controller_reference
method to check if a controller exists by checking for the required constants and then creating them based upon a controller with the same name in the Generic
namespace.
The problem w/ my code is that it is using begin/rescue
, it won't work w/ deeply namespaced controllers, and it's rather verbose.
Can anyone provide some improvements to this code?
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
1 Answer 1
Disclaimer: this should be a comment, my reputation at the moment does not allow me to comment your question
What about exploiting const_missing
?
https://apidock.com/ruby/Module/const_missing
I used it in an app to declare ActiveRecord
models at runtime. If you are interested in this approach I suggest you to namespace all Dynamic controllers i.e.
module Dyn
def self.const_missing(sym)
# Declare class Dyn::MyDynamicController
# without overriding or patching Rails classes
end
end
const_defined?
instead of the begin/rescue, the rest looks just fine... :-) \$\endgroup\$NameError
to avoid suppressing errors not related to this patch. \$\endgroup\$