我正在为一个拥有200多个模块的Rails应用程序开发ApplicationModel。该应用程序非常庞大,当我们rails s
时,它需要40秒才能加载我们的应用。因此,在开发过程中,我们经常更改模块,并查看我们重新加载应用程序所需的更改。
所以我创建了一个ApplicationModel并将所有初始化程序移动到该模型中,以便在开发中重新加载更改,我们不必再次重新启动服务器,每天节省大量时间。
我使ApplicationModel继承自ActiveRecord::Base
并使其成为一个抽象类。所有其他模型都继承自此模型。所以现在我们可以把我们的初始化器扩展到ActiveRecord这个模型。
由于我正在开展一个其他人开始的项目,我不知道这两种扩展方式ActiveRecord
之间的区别,并且想知道它们之间的差异。
ActiveRecord::Base.send(:include, someModule)
ActiveRecord::Base.extend(ClassMethods)
答案 0 :(得分:7)
首先,我认为你有点过于复杂。如果要在控制台中重新加载应用程序的模型,最好的选择是运行reload!
,而不是复杂的自定义解决方案。
其次,这两种选择之间存在差异:
ActiveRecord::Base.send :include, M
ActiveRecord::Base.extend M
是include
将模块添加到类中,就像您将模块中的实例方法复制粘贴到类的定义中一样。
相比之下,extend
会将模块添加到元类中,就像您将模块中的实例方法复制粘贴到类中的class << self
块一样。
以下是一个说明性示例:
module InstanceMethods
def foo; "foo"; end
end
class ActiveRecord::Base
include InstanceMethods
end
ActiveRecord::Base.instance_methods.include? :foo
=> true
可是:
module ClassMethods
def bar; "bar"; end
end
class ActiveRecord::Base
extend ClassMethods
end
ActiveRecord::Base.instance_methods.include? :bar
=> false # hmm, it's not an instance method...
ActiveRecord::Base.singleton_class.instance_methods.include? :bar
=> true # ... it's a class method, aka an
# instance method on the metaclass
答案 1 :(得分:4)
你所看到的可能是:
ActiveRecord::Base.send( :include, InstanceMethods )
ActiveRecord::Base.extend( ClassMethods )
当你包含一个模块时,它的方法成为你的类中的实例方法,当你扩展模块时,模块方法会被插入到你“扩展”它们的实例变量中。在这种情况下,您将扩展ActiveRecord :: Base“类”实例(表示ActiveRecord :: Base对象的Class对象),这意味着这些方法将成为“类”方法。
您可以在此处获得有关此内容的完整说明:"Including and extending modules in Ruby"。