从包含该模块的类中的重写方法调用模块中定义的方法

时间:2019-06-06 18:41:17

标签: ruby-on-rails ruby

如果已在类中重写该方法,是否可以调用模块中定义的方法。

Class A
 include bmodule
 def greeting
  super if some_condition_is_true
 end
end

module bmodule
  included do
    has_many :greeters
    def greeting
     puts 'hi'
    end
  end
end

A.new.greeting如果some_condition_is_true为true,则需要打bmodule的问候

我尝试在模块前面加上它,但它没有用。有可能这样做吗?

4 个答案:

答案 0 :(得分:1)

您必须先保存原始方法,然后再覆盖它:

Class A
  include bmodule

  alias_method :original_greeting, :greeting

  def greeting
    original_greeting if some_condition_is_true
  end
end

这是文档https://apidock.com/ruby/Module/alias_method

的示例

答案 1 :(得分:0)

module B
  def x
    1
  end
end

class A
  include B
  def x
    super + 1
  end
end

puts A.new.x
# => 2

带有Rails问题的included do块是,因此您可以在基础上调用类方法。因此,我认为您无需在这种情况下使用它。

答案 2 :(得分:0)

您可以使用方法Method#super_method,该方法提供了很大的灵活性。

module M1
  def meth(arg)
    yield arg
  end
end

module M2
  def meth(arg)
    yield arg
  end
end

class C
  include M1
  include M2

  def meth(arg)
    yield arg
  end

  def test(cond, &block)
    case cond
    when :C
      meth(cond, &block)
    when :M2
      method(:meth).super_method.call(cond, &block)
    when :M1
      (method(:meth).super_method).super_method.call(cond, &block)
    end
  end      
end

C.ancestors
  #=> [C, M2, M1, Object, Kernel, BasicObject]

c = C.new
c.test(:C)  { |m| "meth is from #{m}" }
  #=> "meth is from C" 
c.test(:M2) { |m| "meth is from #{m}" }
  #=> "meth is from M2" 
c.test(:M1) { |m| "meth is from #{m}" }
  #=> "meth is from M1" 

如果由于某种原因您想使用prepend而不是include,则C.ancesors如下:

class C
  prepend M1
  prepend M2
end

C.ancestors
  #=> [M2, M1, C, Object, Kernel, BasicObject] 

所以您只需相应地修改test

答案 3 :(得分:0)

是的,您可以做到,而且您几乎正确。只需1)大写Bmodule,以便红宝石不会对您大叫,2)定义A时使用小写的class,3)包含ActiveSupport ::关注是否使用included,以及4 )将greeting方法从包含的块中移出。包含的块用于在类级别运行事物,并且实例方法定义不应位于其中。

module Bmodule
  extend ActiveSupport::Concern

  included do
    has_many :greeters
  end

  def greeting
    puts 'hi'
  end
end

class A
  include Bmodule
  def greeting
    super if some_condition_is_true
  end
end

A.new.greeting