在模块前面加上 ActiveSupport::Concern ?红宝石 2+

Posted

技术标签:

【中文标题】在模块前面加上 ActiveSupport::Concern ?红宝石 2+【英文标题】:prepend module with ActiveSupport::Concern ? ruby 2+ 【发布时间】:2018-10-07 07:07:04 【问题描述】:
Module Baz
   def foo
     super
     :baz
   end
end


Class A
   prepend Baz

   def foo
     :bar
   end
end

A.new.foo //works fine

现在,如果我将我的模块转换为关注模块,那不是...

module BazConcern
  extend ActiveSupport::Concern

  included do    
    def foo
      super
      :baz
    end
  end
end

那么 我们如何在 ActiveSupport::Concern 中使用 prepend ? 在 ruby​​ 2+ 中使用

【问题讨论】:

因为不是inlcuded,而是prepended,这是两个不同的钩子。 ActiveSupport::Concern 似乎没有使用它公开included 的块语法公开prepended 如果我只是替换为前置 => ArgumentError: wrong number of arguments (given 0, expected 1) 正如我之前的评论中提到的 “ActiveSupport::Concern 似乎没有在其公开的块语法之前公开。” 我觉得可能的原因是这是因为前置模块脱离了ActiveSupport::Concern 的目的。这样做的设计模式似乎是为了更好地组织代码并远离“胖模型”概念,即使该步骤比文字更具形象性。 A Concern 旨在允许支持单一职责主体但随后包含在类中的模块,本质上使它们成为超类(它们被注入模型上方的继承链中)。然而,前置实际上通过取消移位将模块本身置于继承链中,并且所有内容都将首先通过它(通常使用super 调用)。如果您希望您的方法 foo 执行相同的操作,请从关注点中删除 super,将关注点包含在您的模型中并在 A#foo 中的 :bar 之后添加 super 调用 【参考方案1】:

prependActiveSupport::Concern(Rails 6.1+)

Rails 6.1 添加了对prependActiveSupport::Concern 的支持。

请看下面的例子:

module Imposter
  extend ActiveSupport::Concern

  # Same as `included`, except only run when prepended.
  prepended do
    
  end
end

class Person
  prepend Imposter
end

另外值得一提的是concerning也更新了:

class Person
  concerning :Imposter, prepend: true do

  end
end

来源:

对应commit的链接。

Rails allows a module with extend ActiveSupport::Concern to be prepended.

prepend 和 concerning 文档。

【讨论】:

【参考方案2】:

似乎有一个支持前置的ActiveSupport::Concern 版本:https://gist.github.com/bcardarella/5735987。

我还没有尝试过,但我可能有一天会尝试。

(链接至https://groups.google.com/forum/#!topic/rubyonrails-core/sSk9IEW74Ro)

【讨论】:

以上是关于在模块前面加上 ActiveSupport::Concern ?红宝石 2+的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Google 在前面加上 while(1);到他们的 JSON 响应?

PHP在关联数组前面加上文字键?

JS引用路劲为什么在前面加上两个斜杠

在 WebdriverIO 中,为啥 `expect` 行需要在其前面加上 `await` 才能正确测试某些内容?

如何在ping 命令结果前面加上时间日期

jQuery animate() - 使用相对值 在值的前面加上 += 或 -=