2009-09-01 6 views
1

사용자의 i18n 로켈을 기반으로 문자열 모음을로드하는 여러 모델이 있습니다. @strings 따라서, 한 사람의 선택 로케일에서 문자열은 클래스 변수이며, 때문에,Ruby 스레드로부터 안전한 클래스 변수

module HasStrings 
    def self.included(klass) 
    klass.extend ClassMethods 
    end 

    module ClassMethods 
    def strings 
     @strings ||= reload_strings! 
    end 

    def reload_strings! 
     @strings = 
     begin 
      File.open(RAILS_ROOT/'config'/'locales'/self.name.pluralize.downcase/I18n.locale.to_s + ".yml") { |f| YAML.load(f) } 
     rescue Errno::ENOENT 
      # Load the English strings if the current language doesn't have a strings file 
      File.open(RAILS_ROOT/'config'/'locales'/self.name.pluralize.downcase/'en.yml') { |f| YAML.load(f) } 
     end 
    end 
    end 
end 

나는 그러나, 문제로 실행하고 있습니다 : 사물을 단순화하기 위해, 그렇게 각각의 모델은 다음과 같은 모듈을 포함 다른 로케일을 가진 다른 사용자에게 "출혈"합니다. @strings 변수를 설정하여 현재 요청의 컨텍스트에서만 존재하도록 할 수 있습니까?

Thread.current["#{self.name}_strings"]으로 바꾸려고했는데 (클래스별로 다른 스레드 변수가 있음)이 경우 변수가 여러 요청에 걸쳐 유지되었으며 로캘이 변경되면 문자열이 다시로드되지 않았습니다.

+0

개발 중이거나 프로덕션 중입니까? 아니면 둘 다입니까? –

+0

생산. 개발 중에 클래스는 각 요청을 다시로드하므로 문제가되지 않습니다. –

답변

3

두 가지 옵션이 있습니다. 첫 번째는 @strings을 인스턴스 변수로 만드는 것입니다.

하지만 한 번만 요청하면 두 번 이상로드 될 수 있으므로 @strings을 문자열 집합에 대한 로캘 해시로 바꿀 수 있습니다.

module HasStrings 
    def self.included(klass) 
    klass.extend ClassMethods 
    end 

    module ClassMethods 
    def strings 
     @strings ||= {} 
     string_locale = File.exists?(locale_filename(I18n.locale.to_s)) ? I18n.locale.to_s : 'en' 
     @strings[string_locale] ||= File.open(locale_filename(string_locale)) { |f| YAML.load(f) } 
    end 

    def locale_filename(locale) 
     "#{RAILS_ROOT}/config/locales/#{self.name.pluralize.downcase}/#{locale}.yml" 
    end 
    end 
end 
+0

논리적 컨텍스트에서 의미가 없기 때문에 인스턴스 변수에서 벗어나고 싶습니다. 재사용도 가능합니다. 해시 아이디어가 마음에 들지만 –

관련 문제