2011-07-24 38 views
2

我正在为具有200多个模块的Rails应用程序开发ApplicationModel。该应用程序非常庞大,当我们rails s它实际上需要40秒加载我们的应用程序。因此,在开发过程中,我们经常更换大量模块,并查看我们必须重新加载应用程序的更改。扩展ActiveRecord - send和extend之间有什么区别?

因此,我创建了一个ApplicationModel并将所有初始化器移入该模型,以便在开发中重新加载更改,并且不必每天都重新启动服务器,节省大量时间。

我使ApplicationModel继承自ActiveRecord::Base,并将其设为抽象类。所有其他模型都从此模型继承。所以现在我们可以把我们的ActiveRecord扩展器放入这个模型中。

因为我正在开发一个其他人开始的项目,所以我不知道这两种扩展方法之间的区别ActiveRecord并想知道它们之间的区别。

ActiveRecord::Base.send(:include, someModule) 
ActiveRecord::Base.extend(ClassMethods) 

回答

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

+1,但你得到的第一部分是错误的。我们尝试重新加载初始化程序。他们在'config/initializers'中,所以'reload!'不会碰它们。但是现在使用一个应用程序模型'reload!'可以工作,或者只是在开发中的任何响应。 – s84

+0

Gotcha - 这对我来说并不是很明显,因为你说“我正在为拥有200多个模型的Rails应用程序开发ApplicationModel。”谢谢澄清! –

+0

(啊,我发现它已经在几分钟前被修正为“超过200个模块”。) –

4

你看到的可能是:

ActiveRecord::Base.send(:include, InstanceMethods) 
ActiveRecord::Base.extend(ClassMethods) 

当你有一个模块,它的方法成为你的类的实例方法,当你扩展模块,该模块的方法得到插入你扩展它们的实例变量。在这种情况下,你需要扩展ActiveRecord :: Base的“class”实例(表示ActiveRecord :: Base对象的Class对象),这意味着这些方法将成为“class”方法。

你可以在这里得到一个完整的解释:"Including and extending modules in Ruby"

+0

正确的,我更新了我的代码,以便它更有意义:) – s84

相关问题