简体   繁体   English

Ruby线程安全的类变量

[英]Ruby thread-safe class variables

I have a number of models that load a collection of strings, based on the user's i18n locale. 我有许多基于用户的i18n语言环境加载字符串集合的模型。 In order to simplify things, each model that does so includes the following module: 为了简化操作,每个模型都包括以下模块:

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

I am running into a problem, however, because @strings is a class variable, and thus, the strings from one person's chosen locale are "bleeding" over into another user with a different locale. 但是,我遇到了一个问题,因为@strings是一个类变量,因此,一个人选择的语言环境中的字符串被“渗出”到另一个具有不同语言环境的用户中。 Is there a way to setup the @strings variable so that it lives only within the context of the current request? 有没有办法设置@strings变量,使其只存在于当前请求的上下文中?

I tried replacing @strings with Thread.current["#{self.name}_strings"] (so that there's a different thread variable per class), but in that case the variable was retained over multiple requests and strings weren't reloaded when the locale was changed. 我尝试用Thread.current["#{self.name}_strings"]替换@strings (这样每个类都有一个不同的线程变量),但是在那种情况下,该变量保留在多个请求中,并且当语言环境已更改。

I see two options. 我看到两个选择。 The first is to make @strings an instance variable. 首先是使@strings成为实例变量。

But then you may be loading them more than once on a single request, so instead, you can turn @strings into a hash of locale against a string set. 但是随后您可能会在单个请求中多次加载它们,因此,您可以将@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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM