开发者

rails 3.1 dynamic controller instantiation

I have a Rails Engine gem in which I want to load a HomeController class definition dynamically from an initializer. I can instantiate the class correctly, but when I go to call the index action, I get this error :

TypeError in HomeController#index

can't convert nil into String
Rails.root: /home/chris/test_app

Full Trace:
actionpack (3.1.0) lib/action_view/template/resolver.rb:16:in `<<'
actionpack (3.1.0) lib/action_view/template/resolver.rb:16:in `build'
actionpack (3.1.0) lib/action_view/template/resolver.rb:127:in `find_templates'
actionpack (3.1.0) lib/action_view/template/resolver.rb:45:in `find_all'
actionpack (3.1.0) lib/action_view/template/resolver.rb:76:in `cached'
actionpack (3.1.0) lib/action_view/template/resolver.rb:44:in `find_all'
actionpack (3.1.0) lib/action_view/path_set.rb:21:in `find_all'
actionpack (3.1.0) lib/action_view/path_set.rb:20:in `each'
actionpack (3.1.0) lib/action_view/path_set.rb:20:in `find_all'
actionpack (3.1.0) lib/action_view/path_set.rb:19:in `each'
actionpack (3.1.0) lib/action_view/path_set.rb:19:in `find_all'
actionpack (3.1.0) lib/action_view/path_set.rb:29:in `exists?'
actionpack (3.1.0) lib/action_view/lookup_context.rb:94:in `template_exists?'

I cut the trace off after the actionpack part because it was really long, but I think this is all the relevant information.

Here is my Engine class definition:

module MyGem
   class Engine < Rails::Engine

      initializer 'my_gem.load_middleware' do |app|
        home_controller = create_controller 'HomeController'
      end

      def create_controller(class_name, &block)
        klass = Class.new ApplicationController, &block
        Object.const_set class_name, klass
        return klass
      end
   end
end

this is when i have the root path set to home#index . if I create a home_controller.rb in app/controllers in either the application or the gem like so:

class HomeController < Applicati开发者_JS百科onController
end

then everything works fine and the index action is rendered appropriately, so I'm sure there is no problem with my routes, views, or application controller.

Any light shed on this issue would be much appreciated. edit the output of

HomeController.view_paths.join " : "

is

/home/chris/gems/my_gem/app/views : /home/chris/test_app/app/views


I'm not sure where you get the DSL "initializer" from... but that seems to cause a problem. It doesn't get executed on new()

This seems to work for me in Rails 3.0.7:

module MyGem
   class Engine < Rails::Engine

     def initialize
        home_controller = create_controller 'HomeController'
     end

# this doesn't seem to do anything...
#
#      initializer 'my_gem.load_middleware' do |app|
#        home_controller = create_controller 'HomeController'
#      end

      def create_controller(class_name, &block)
        klass = Class.new ApplicationController::Base , &block # shouldn't this be ApplicationController::Base ?

#        Object.const_set class_name, klass     # module of superclass is ApplicationController, not Object

        ApplicationController.const_set(class_name, klass)  # name of the module containing superclass
        puts "Klass created! : #{Object.constants}"
        return klass
      end
   end
end

and running the code:

 h = MyGem::Engine.new
Klass created! : [:Object, :Module, :Class, :Kernel, :NilClass, :NIL, :Data, :TrueClass, :TRUE, :FalseClass, :FALSE, :Encoding ... :BasicObject]
 => #<MyGem::Engine:0x00000006de9878> 


> ApplicationController.const_get("HomeController")
 => ApplicationController::HomeController 
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜