在我的gem中有一个Component基类:
module Component
class Base
def self.inherited(component_class)
Component.class_eval do
define_method(component_class.to_s.underscore) do |*args, &block|
component_class.new(*args, &block)
end
end
end
end
end
对于从此基类继承的每个类(例如FancyComponent < Component::Base
),应在Component模块中定义一个帮助器(例如fancy_component
)。
这适用于随我的宝石一起提供的任何组件,即Component.instance_methods.include? :fancy_component #=> true
我希望我的gem用户能够添加组件。这些内容存储在app/components
。
此文件夹包含在以下所有内容中:
新组件UserComponent < Component::Base
存储在app/components/user_component.rb
。
如果我启动rails控制台,情况如下:
Loading development environment (Rails 3.0.4, ruby-1.9.2-p0)
Component.instance_methods.include? :fancy_component #=> true
Component.instance_methods.include? :user_component #=> false
UserComponent #=> UserComponent
Component.instance_methods.include? :user_component #=> true
因此,在以某种方式访问组件类之前,辅助方法不可用。
那么如何强制加载该类以便继承执行?
答案 0 :(得分:0)
你的想法很好但是我非常建议你不要实现这样的东西,`这通常是通过在Rails注意到它们之前预加载模型来完成的,这可能导致难以计算加载问题你的应用程序(就像应该重新加载但不是的类)。
这是一个基本的例子,你实现这个功能的方法是,在你的“root”gem文件中(如果你的gem命名为“my_component”,“lib / my_component.rb”文件)做类似的事情这样:
require 'component/base/component'
# require here all other classes necessary for your gem
rb_files = File.join( Rails.root, 'app', 'components', '**', '*.rb' )
Dir.glob( rb_files ).each do |file|
require file.gsub('.rb')
end
有了这个你将加载“app / components”下的所有文件,但是Rails不会重新加载这些对象,因为它们不是Rails所要求的,而是你自己的宝石。如果您不介意无法更改这些文件,这可能没问题,但是您可能会在开发环境(或任何“cache_classes”设置为false的环境)中遇到问题。
答案 1 :(得分:0)
这是rails中的一个错误(但是wontfix),请参阅此票证: