2009-09-01 69 views
1

私は、ユーザーのi18nロケールに基づいて、文字列のコレクションをロードするいくつかのモデルを用意しています。物事を単純化するために、各モデルので、以下のモジュールが含まれないもの: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はクラス変数であるので、私は、しかし、問題に実行しています、したがって、1人の選ばれたロケールからの文字列があります異なるロケールを持つ別のユーザーに「出血」する現在の要求のコンテキスト内にのみ存在するように、@strings変数を設定する方法はありますか?

Thread.current["#{self.name}_strings"]に置き換えようとしましたが(そのため、クラスごとに異なるスレッド変数があります)、その場合、変数は複数の要求にわたって保持され、ロケールが変更されたときに文字列は再ロードされませんでした。

+0

これは開発中であるのか、プロダクションであるのか、あるいはその両方ですか? –

+0

生産。開発時には、クラスごとにリクエストがリロードされるため、問題はありません。 –

答えて

3

2つのオプションがあります。最初は@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

私はインスタンス変数から遠ざかりたいのですが、それは論理コンテキストで意味をなさないため、再利用があるからです。私はハッシュのアイデアが好きです –

関連する問題