【问题标题】:Is it dangerous to mix ActiveSupport::Concern modules with vanilla modules?将 ActiveSupport::Concern 模块与 vanilla 模块混合使用是否危险?
【发布时间】:2017-03-31 08:47:53
【问题描述】:

我知道ActiveSupport::Concern 后面隐藏着一个依赖管理系统。我不完全理解它(我不确定我是否准备好了),但简而言之:是否可以将ActiveSupport::Concern 与香草(非ActiveSupport::Concern)模块混合使用,还是有陷阱?

这里有一些我能想到的不同用法的例子

module Vanilla
  module ModuleIncludedInASC
    # Vanilla module
  end

  module ModuleIncludedInClass
    # Vanilla module
  end

module ASC
  module ConcernIncludedInClass
    extend ActiveSupport::Concern
    ...
  end

  module ConcernIncludedInASC
    extend ActiveSupport::Concern
    ...
  end

  module ConcernIncludingVanillaModulesIncludedInClass
    extend ActiveSupport::Concern
    include Vanilla::VanillaConcernIncludedInASC
  end
  module ConcernIncludingASCConcernIncludedInASC
    extend ActiveSupport::Concern
    include ConcernIncludedInASC
  end
end

class MyFoo
  include Vanilla::ModuleIncludedInClass
  include ASC::ConcernIncludedInClass
  include ASC::ConcernIncludingVanillaModulesIncludedInClass
end

# Ans also possibly, ActiveSupport::Concern modules included in vanilla modules...?

这可能会导致问题吗?

【问题讨论】:

    标签: ruby ruby-on-rails-5 activesupport activesupport-concern


    【解决方案1】:

    应该没问题。

    我无法谈论深入的技术细节,但我从未见过有人提到它有风险,而且我一直都这样做。我有一些型号有 10+ includes。其中一些模块正在使用ActiveSupport::Concern,有些则没有。从来没有遇到过任何问题。

    我建议尝试一下,如果确实引起问题,请发布一个新问题。

    【讨论】:

      【解决方案2】:

      我还没有遇到任何问题,但是是的,理论上存在潜在问题。

      如果您在类中包含该模块,则在普通模块中定义的方法附加到方法查找链中。所以类中定义的方法会覆盖普通模块中的方法。

      在关注点的included 块中定义的方法将直接添加到包含关注点的类中。

      结果是,即使您在普通模块之前包含关注点,关注点中的方法将始终覆盖普通模块中的方法。

      示例

      module Normal
        def foo
          'normal'
        end
      end
      
      module Concern
        extend ActiveSupport::Concern
        included do
          def foo
            'concern'
          end
        end
      end
      
      class Bar
        include Concern  # include concern first
        include Normal   # then include normal
      end
      
      Bar.new.foo  #=> "concern"
      

      也许您会期望 "normal" 会被返回,但这永远不会发生。

      【讨论】:

      • 感谢这个例子!在实践中它实际上可能会发生在我身上:当我编写“抽象”模块时,我有时会用def foo; raise NotImplementedError 明确定义接口,并且我希望其他模块用实现来覆盖它。如果那些其他模块不关心,那么我最终可能根本不会覆盖。
      猜你喜欢
      • 1970-01-01
      • 2012-01-30
      • 2011-09-30
      • 2011-09-05
      • 1970-01-01
      • 2018-10-07
      • 1970-01-01
      • 1970-01-01
      • 2020-11-06
      相关资源
      最近更新 更多