2015-08-15 3 views
0

Даже Bar включен после модуля по умолчанию, он по-прежнему не может переопределить Default.foo. Это способ сделать это?Ruby `define_singleton_method` в` included` block vs `ClassMethods`

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 

ответ

0

Если мы добавим некоторые отладочные в вашем коде, мы увидим, что порядок определения и включения модулей является то, как показано ниже:

Defined => Default 
Defined => Bar 
Defined => ClassMethods 
Included => Default 
Included => Bar 
41 

Поскольку событие включения модуля Default происходит после определения модуля Bar, определение недействительного foo, которое является недействительным, определено в блоке included модуля Default.

код отладочные заявления добавил

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 определение 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 

Выпуск вышеуказанной программы

Defined => Default 
Defined => Bar 
Defined => ClassMethods 
Included => Default 
Included => Bar 
42 
Смежные вопросы