重新定义self.included和传递块到包含之间的区别

时间:2013-12-19 02:02:55

标签: ruby-on-rails ruby

之间有什么区别
module A
  def self.included(klass)
    puts klass
  end
end

module A
  include ActiveSupport::Concern
  included do
    puts self
  end
end

哪一个更好,哪个更好?

2 个答案:

答案 0 :(得分:2)

两个片段都会产生相同的结果。但是,有一个小但重要的区别。

第一个代码是纯Ruby。这意味着它可以毫无依赖地工作。

第二段代码依赖于ActiveSupport,它是一个外部依赖项。如果要使用它,则需要在项目中包含gem。在Rails应用程序中,几乎没有开销,因为应用程序已经依赖于ActiveSupport。但是在非Rails应用程序中,它可能不方便。

此外,ActiveSupport::Concern不仅仅为Ruby包含的钩子添加一些语法糖。实际上,此类模块的主要范围是管理模块之间的多个依赖关系。

在Rails代码库中,将小块功能定义为单独的模块是很常见的。一个很好的例子是ActiveSupport本身。但是,您可能要求功能A可能需要在模块B中定义某些功能,因此如果您在代码中包含B,那么模块应确保要求并混合还A,否则你的代码会崩溃。

它还基于包含的钩子:类级别扩展实现了一个非常常见的模式。以下Ruby代码

module A
  def self.included(base)
    base.extend ClassMethods
  end

  module ClassMethods
    def bar
      "bar"
    end
  end
end

class Foo
  include A
end

Foo.bar
# => "bar"

变为

module A
  extend ActiveSupport::Concern

  module ClassMethods
    def bar
      "bar"
    end
  end
end

class Foo
  include A
end

Foo.bar
# => "bar"

我个人的建议是避免使用ActiveSupport::Concern if

  • 您无需使用其高级功能
  • 您正在编写的代码可以使用少量代码轻松编写,而不依赖于Concern
  • 该应用尚未包含ActiveSupport作为依赖

答案 1 :(得分:0)

在您的第二段代码中,included在定义A期间被调用一次。除非您已定义included来执行某些操作,否则它不会执行任何操作。传递给included的块将无效,除非您已覆盖included以阻止并执行某些操作。简而言之,你的第二段代码没有意义。