2011-03-08 6 views
1

개발 중에 나는 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

내 엔진 내에서 특정 클래스를 캐시하는 방법은 없나요? 또는 모델 자체에 후크가있는 모델을 등록하는 방식에 결함이 있습니까?

답변

2

문제는 개발 환경에서 모든 요청에 ​​모델이 다시로드되어 이러한 클래스의 변경 사항이 적용되고 소스 코드를 변경할 때마다 서버를 다시 부팅 할 필요가 없다는 것입니다. 당신은 콘솔에서이 동작을 볼 수 있습니다

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을 사용하면됩니다.

+0

나는 이것을 시험해보고 어떻게되는지 알려줄 것이다. 고마워! 나는 그것을 올바른 것으로 표시 하겠지만, 먼저 시도해보고 싶습니다. 마음에 들지 않으면 :) – Garrett

+0

이 작품은 더 논리적이라고 느낍니다. 특정 장소에서. 다시 한 번 감사드립니다! – Garrett

관련 문제