2017-06-27 7 views
0

私は現在、すべてのオブジェクトが "同じ" inital値のインスタンス変数を使用しており、私はこの問題のみを読んでいるという問題に直面しています。Ruby/Railsのクラス変数はいつinitilal化されますか?

def initialize 
    @available_ids = read_only_value 
end 

しかし、ここでは難しいことがあります。この「read_only_value」はAPIから取得されます。簡単にするために、値がintの配列で、月に1回変更されると仮定しましょう。

しかし、オブジェクトを作成するたびに値を取得することでAPIをDoSしたくありません。代わりにクラス変数を使用するとどうなりますか?

class Foo 
    @@available_ids = read_only_value 
    def initialize 
     @available_ids = @@available_ids //weird but let's go with it 
    end 
end 

は私が...変数が初期化される一度それが唯一の実行だから、これはAPIをスパムの問題を解決します

しかしこれが起こるんと仮定しますか? Railsアプリケーションを起動するとき、最初のオブジェクトを作成するとき?更新されますか?値は月に一度変わるので、どのように更新を入手できますか?

PS:IDをデータベースに保存し、idsをしばらくまたは必要に応じて一度チェックすることをお勧めします。

答えて

3

クラスがロードされるときには(読み:Railsの起動時に。)が起こる。また、あなたはクラス変数は必要ありません

。クラスインスタンス変数は十分です:

class Foo 
    @available_ids = read_only_value 
    def initialize 
     @available_ids = self.class.instance_variable_get :@available_ids 
    end 
end 
0

redis/memcacheの使用はいかがですか? redis/memcacheにapi値をキャッシュし、有効期限を1ヶ月に設定するか、少し短く設定します。イニシャライザでは常にキャッシュから引き出します。キャッシュがnilの場合は、実際のAPIを呼び出すメソッドを呼び出して再びキャッシュします。

0

あなたのコードの場合は、クラスが定義されます場合は、APIは、あなたがあなたのアプリを起動したとき、それは、一度だけアクセスされることを意味する、アクセスすることでしょう。

puts "starting app" 

def read_only_value 
    puts "API accessed!" 
    "my value" 
end 


class Foo 
    @@available_ids = read_only_value 
    def initialize 
    @available_ids = @@available_ids 
    puts "initializing with value: #{@available_ids}" 
    end 
end 

puts "initializing two objects: " 
Foo.new 
Foo.new 

#=> starting app 
#=> API accessed! 
#=> initializing two objects: 
#=> initializing with value: my value 
#=> initializing with value: my value 

APIアクセスを管理しようとするときは、APIを独自のクラスにラップすることをおすすめします。そうすることで、あなたが独立してAPIを使用してオブジェクトのAPIコールとキャッシュ値を追跡することができます:

class API 

    def self.instance 
    @@instance ||= API.new 
    end 

    def read_only_value 
    if @read_only_value.nil? || (Time.now - @cached_time) > 86400 # one day, in seconds 
     puts "accessing api" 
     @read_only_value = "access api here" 
     @cached_time = Time.now 
    end 
    @read_only_value 
    end 

end 


class Foo 

    def initialize 
    @available_ids = API.instance.read_only_value 
    puts "initializing with value: #{@available_ids}" 
    end 

end 

puts "initializing two objects: " 

Foo.new 
Foo.new 

#=> initializing two objects: 
#=> accessing api 
#=> initializing with value: access api here 
#=> initializing with value: access api here 
2

Railsはcacheを内蔵しているので、これらの線に沿って何か作業をする必要があります:(例に基づいて、ドキュメント)

class Foo 
    def available_ids 
    Rails.cache.fetch('available_ids', expires_in: 24.hours) do 
     API.fetch_ids 
    end 
    end 
end 
+1

この回答は私の問題を解決しますが、@ mudasobwaが私の質問に最初に答えました。私は彼の答えを受け入れるでしょう。とにかくありがとう! –

+0

@ 0lli.rocksこれはF1トーナメントではなく、競争条件は避けるべきです。 _this_答えがあなたの問題を解決するなら、_this_答えは正しいとマークされるべきです。してください。 – mudasobwa

+0

@mudasobwaおそらくあなたは私のコメントを誤解していました。私の元々の質問は「変数はいつ初期化されたのですか?」でした。 Stefanのこの答えは、この質問に全く答えません。私がこれを受け入れると、質問を見つけた人は正しい答えを見つけるためにあなたの答えにスクロールする必要があります。とにかくStefanのこの答えは、私の問題ではなく、私の問題を解決します。 –

関連する問題