Rails двигатель не кешируется - PullRequest
1 голос
/ 08 марта 2011

В процессе разработки я пытаюсь собрать все модели в своем приложении, включив метод в классы ActiveRecord::Base, чтобы они могли настраивать модели, и это даст мне возможность добавить эту модель в глобальный массив.

module EngineName
  module ActiveRecordExtensions
    extend ActiveSupport::Concern

    included do
      def self.inherited(klass) #:nodoc:
        klass.class_eval do
          def self.config_block(&block)
            abstract_model = EngineName::AbstractModel.new(self)
            abstract_model.instance_eval(&block) if block

            EngineName::Models.add(abstract_model)
          end
        end
      end
    end
  end
end

Мой EngineName::Models класс - это просто оболочка, которая содержит все модели.

module EngineName
  class Models
    class << self
      def all
        @models ||= []
      end
      alias_method :models, :all

      def navigation
        @models - excluded_navigation_models
      end

      def routed
        @models - excluded_route_models
      end

      # Creates an array of models if none exists. Appends new models
      # if the instance variable already exists.
      def register(klass)
        if @models.nil?
          @models = [klass]
        else
          @models << klass unless @models.include?(klass) || excluded_models.include?(klass)
        end
      end
      alias_method :add, :register
    end
  end
end

При каждом обновлении вызывается метод config_block в моей модели, который, в свою очередь, снова и снова добавляет одну и ту же модель в мой глобальный массив моделей.

Как вы можете видеть внизу, всякий раз, когда я перебираю все свои модели, он продолжает добавлять себя.

enter image description here

Есть ли способ кэшировать определенные классы в моем движке? Или в моем подходе есть недостатки при регистрации моделей с помощью крючка внутри самой модели?

1 Ответ

2 голосов
/ 08 марта 2011

Проблема в том, что в вашей среде разработки ваши модели перезагружаются при каждом запросе, так что изменения в этих классах вступают в силу, и вам не нужно перезагружать сервер каждый раз, когда вы вносите изменения в исходный код.Вы можете увидеть это поведение в консоли:

User.object_id
=> 2203143360
reload!
=> true
User.object_id
=> 2212653160

Это означает, что когда вы вызываете @models.include?(klass), вы фактически проверяете текущее создание этого объекта по сравнению с предыдущим запросом.Что вы заметите, так это то, что со временем ваша память становится раздутой, потому что эти объекты не будут удалены - поскольку сборщик мусора будет держать их рядом из-за ссылки на них в переменной экземпляра @models.Это не будет проблемой в работе, потому что классы загружаются только один раз, но это вызовет у вас проблемы при разработке.

Чтобы обойти это, я бы рекомендовал сделать что-то вроде этого:

module EngineName
  class Models
    class << self
      def all
        @models ||= {}
      end
      alias_method :models, :all

      def register(klass)
        if @models.nil?
          @models = {klass.name => klass}
        else
          @models[klass.name] = klass unless excluded_models.keys.include?(klass.name)
        end
      end
      alias_method :add, :register
    end
  end
end

Использование хэша позволит вам отслеживать модели по их именам, и всякий раз, когда появляется новая версия модели, она заменяет старую устаревшую версию.Это должно помочь в вашей среде разработки.Чтобы получить список всех моделей, вы просто используете @models.values, а для получения списка названий моделей вы просто используете @models.keys.

...