Почему в Rails::Application есть много повторяющихся инициализаторов, которые определены в Rails::Engine?

Работая в процессе инициализации rails 3, я обнаружил, что все инициализаторы, определенные в Rails::Engine(их 10), были добавлены в экземпляр Rails::Application более одного раза. Это означает, что эти инициализаторы будут выполняться много раз. Ниже приведен анализ: 1. Rails::Application#initializer:

def initializers #:nodoc:           
  Bootstrap.initializers_for(self) +
  super +                           
  Finisher.initializers_for(self)   
end

Он вызовет метод super(Rails::Engine), который определен следующим образом:

def initializers
  initializers = []
  ordered_railties.each do |r|
    if r == self
      initializers += super
    else
      initializers += r.initializers 
    end                              
  end
  initializers
end

Из инициализаторов Rails:: Engine # видно, что каждый движок (класс, унаследованный от Rails:: Engine) будет добавлять к нему инициализаторы Rails:: Engine, включая Rails::Application. Но все остальные движки включены в Rails::Application order_railties, поэтому их инициализаторы также добавляются в Rails::Application. Мы можем заключить, что инициализаторы Rails:: Engine добавляются много раз в Rails::Application. Мы можем увидеть из консоли информацию:

1.9.3p194 :002 > Rails.application.initializers.map(&:name).size
 => 119 
1.9.3p194 :001 > Rails.application.initializers.map(&:name).uniq.size
 => 79

Таким образом, каждый инициализатор в Rails:: Engine добавляется 5 раз в Rails::Application. Интересно, почему это происходит? Есть ли какая-то особая причина?

1 ответ

Решение

Инициализатор имеет несколько других атрибутов, кроме name: context, block и т. Д. Поэтому всякий раз, когда движок, унаследованный от Rails:: Engine, все инициализаторы Rails:: Engine добавляются в дочерний движок с другим контекстом. То есть, хотя в Rails::Application есть повторяющиеся инициализаторы с одинаковыми именами, они действительно являются разными инициализаторами, которые будут работать в другом контексте:

def run(*args)                         
  @context.instance_exec(*args, &block)
end 
Другие вопросы по тегам