【问题标题】:Refine gem's class method细化 gem 的类方法
【发布时间】:2017-11-10 12:43:37
【问题描述】:

我必须以优雅和孤立的方式将一些行为包裹在外部 gem 周围。鉴于下面的抽象,一切都运行顺利,但从来没有打印'bar'。 谁能告诉我为什么?

我的代码:

module RefineGem
  refine GemMainModule::GemClass do
    def self.foo
      p 'bar'
      super
    end
  end
end

module Test
  using RefineGem

  def test
    GemMainModule::GemClass.foo
  end
end

class Testing
  include Test
end

Testing.new.test

宝石代码:

module GemMainModule
  class Base
    include GemMainModule::Fooable
  end

  class GemClass < Base
  end
end

module GemMainModule
  module Fooable
    extend ActiveSupport::Concern

    class_methods do
      def foo
        p 'zoo'
      end
    end
  end
end

【问题讨论】:

  • 我从来没有使用过refinements,因为前置模块是一种更干净、健壮和智能的方法;但我建议你refine GemMainModule::GemClass.singleton_class { def foo ... end }。我怀疑改进是否适用于类方法。
  • 无论如何,然后使用模块作为答案发布您的解决方案,我会接受它。
  • “使用模型”是什么意思?
  • 这是一个错字,我的意思是模块

标签: ruby ruby-on-rails-5 refinements


【解决方案1】:

我怀疑改进是否适用于类方法。不过,您可以改进 singleton_class

module RefineGem
  refine GemMainModule::GemClass.singleton_class do
    def foo
      p 'bar'
      super
    end
  end
end

我个人更喜欢使用Module#prepend 来实现相同的功能:

GemMainModule::GemClass.singleton_class.prepend(Module.new do
  def foo
    p 'bar'
    super
  end
end)

【讨论】:

  • 我喜欢这个并且它有效,如果我可能会烦人并针对我的情况提出一个缺失点:我可以控制使用范围吗? (就像使用“使用”关键字进行改进一样),我希望在特定位置而不是其他任何地方覆盖该行为。
  • 不,Module#prepend 你不能这样做。老实说,我从来没有觉得有必要处理使用范围。更重要的是:这听起来违反直觉,对我来说更容易出错,foo 以这种方式工作,在那里它以这种方式工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-06
  • 1970-01-01
  • 2015-08-21
  • 1970-01-01
相关资源
最近更新 更多