rails 3.1动态控制器实例化

时间:2011-09-25 14:27:44

标签: ruby reflection ruby-on-rails-3.1 gem rails-engines

我有一个Rails Engine gem,我想从初始化器动态加载HomeController类定义。我可以正确地实例化该类,但是当我去调用索引操作时,我收到此错误:

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?'

我在动作包部分之后剪掉了痕迹,因为它真的很长,但我认为这是所有相关的信息。

这是我的Engine类定义:

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

这是我将根路径设置为home #index。如果我在应用程序或gem中的app / controllers中创建一个home_controller.rb,如下所示:

class HomeController < ApplicationController
end

然后一切正常,索引操作正确呈现,所以我确信我的路由,视图或应用程序控制器没有问题。

对此问题的任何亮点都将不胜感激。 修改

的输出

HomeController.view_paths.join " : "

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

1 个答案:

答案 0 :(得分:0)

我不确定你从哪里获得DSL“初始化程序”......但这似乎会导致问题。它不会在new()

上执行

这似乎对我在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

并运行代码:

 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