在`included`块vs`ClassMethods`中的Ruby`define_singleton_method`

时间:2015-08-15 09:10:13

标签: ruby activesupport

在默认模块之后包含偶数栏,它仍然无法覆盖Default.foo。这是一种方法吗?

module Default
  extend ActiveSupport::Concern
  included do
    define_singleton_method :foo do
      41
    end
  end
end
module Bar
  extend ActiveSupport::Concern
  module ClassMethods
    def foo
      42
    end
  end
end
class Foo
  include Default
  include Bar
end

Foo.foo
=> 41  #From Default.foo

1 个答案:

答案 0 :(得分:0)

如果我们在您的代码中添加一些调试语句,我们将看到定义和包含模块的顺序如下所示:

Default

由于在定义模块Bar之后发生了包含模块foo的事件,因此有效的included的定义是定义的定义在模块Default的{​​{1}}块中。

添加了调试语句的代码

require "rails"

module Default
  extend ActiveSupport::Concern
  puts "Defined => Default"
  included do
    define_singleton_method :foo do
      41
    end
    puts "Included => Default"
  end
end
module Bar
  extend ActiveSupport::Concern
  puts "Defined => Bar"
  module ClassMethods
    puts "Defined => ClassMethods"
    def foo
      42
    end
  end
  included do
    puts "Included => Bar"
  end
end
class Foo
  include Default
  include Bar
end

p Foo.foo

如果您希望foo的{​​{1}}定义生效,那么您也可以在Bar included块中定义它,如图所示以下

Bar

以上程序的输出

require "rails"

module Default
  extend ActiveSupport::Concern
  puts "Defined => Default"
  included do
    define_singleton_method :foo do
      41
    end
    puts "Included => Default"
  end
end
module Bar
  extend ActiveSupport::Concern
  puts "Defined => Bar"
  module ClassMethods
    puts "Defined => ClassMethods"
    def foo
      42
    end
  end
  included do
    puts "Included => Bar"
    define_singleton_method :foo do
      42
    end
  end
end
class Foo
  include Default
  include Bar
end

p Foo.foo