扩展ActiveRecord - send,extend之间有什么区别?

时间:2011-07-24 20:34:17

标签: ruby-on-rails activerecord

我正在为一个拥有200多个模块的Rails应用程序开发ApplicationModel。该应用程序非常庞大,当我们rails s时,它需要40秒才能加载我们的应用。因此,在开发过程中,我们经常更改模块,并查看我们重新加载应用程序所需的更改。

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

我使ApplicationModel继承自ActiveRecord::Base并使其成为一个抽象类。所有其他模型都继承自此模型。所以现在我们可以把我们的初始化器扩展到ActiveRecord这个模型。

由于我正在开展一个其他人开始的项目,我不知道这两种扩展方式ActiveRecord之间的区别,并且想知道它们之间的差异。

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

2 个答案:

答案 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"