14

作成する必要がある別の Web サービスへの高価な (時間のかかる) 外部要求があり、それをキャッシュしたいと考えています。そこで、アプリケーションコントローラーに以下を入れて、このイディオムを使用しようとしました:

def get_listings
  cache(:get_listings!)
end

def get_listings!
  return Hpricot.XML(open(xml_feed))
end

get_listings!コントローラーを呼び出すとすべて問題ありget_listingsませんが、Rails を呼び出すと、ブロックが指定されていないと不平を言います。そして、そのメソッドを調べると、実際にブロックが必要であることがわかり、さらに、そのメソッドはビューでのみ使用されるように見えますか? したがって、明記されていませんが、例は単なる疑似コードであると推測しています。

だから私の質問は、このようなものをどのようにキャッシュするのですか? 他の方法をいろいろ試しましたが、わかりませんでした。ありがとう!

4

8 に答える 8

18

コード内アプローチは次のようになります。

def get_listings
  @listings ||= get_listings!
end

def get_listings!
  Hpricot.XML(open(xml_feed))
end

これは、リクエストごとに結果をキャッシュします (リクエストごとの新しいコントローラー インスタンス)。

リクエスト間で共有したい場合は、クラスオブジェクトにデータを保存しないでください。並行プログラミングが得意でない限り、アプリはスレッドセーフではないため、スレッドが共有への相互のデータアクセスを妨げないようにしてください。変数。

リクエスト間でキャッシュする「Rails の方法」はRails.cache storeです。Memcached は頻繁に使用されますが、ファイル ストアまたはメモリ ストアがニーズに合う場合があります。それは、展開方法と、キャッシュ ヒット、応答時間、ストレージ (RAM) を優先するか、ホスト ソリューション (heroku アドオンなど) を使用するかによって大きく異なります。

于 2010-08-30T17:07:18.980 に答える
12

nruth が示唆するように、Rails のビルトイン キャッシュ ストアはおそらく必要なものです。

試す:

def get_listings
  Rails.cache.fetch(:listings) { get_listings! }
end

def get_listings!
  Hpricot.XML(open(xml_feed))
end

fetch() は、指定されたキーのキャッシュされた値を取得するか、ブロックの結果が存在しない場合はキャッシュに書き込みます。

デフォルトでは、Rails キャッシュはファイル ストアを使用しますが、実稼働環境では memcached が推奨されるオプションです。

詳細については、http: //guides.rubyonrails.org/caching_with_rails.htmlのセクション 2 を参照してください。

于 2010-08-31T15:24:29.290 に答える
3

cache_method gemを使用できます。

gem install cache_method
require 'cache_method'

あなたのコードで:

def get_listings
  Hpricot.XML(open(xml_feed))
end
cache_method :get_listings

を削除したことに気付くかもしれませんget_listings!。データを手動で更新する方法が必要な場合は、次のことをお勧めします。

def refresh
  clear_method_cache :get_listings
end

ここに別のヒントがあります:

def get_listings
  Hpricot.XML(open(xml_feed))
end
cache_method :get_listings, (60*60) # automatically expire cache after an hour
于 2011-03-17T01:41:09.840 に答える
1

cachethod gem ( https://github.com/reneklacan/cachethod )も使用できます。

gem 'cachethod'

次に、メソッドの結果をキャッシュするのは非常に簡単です

class Dog
  cache_method :some_method, expires_in: 1.minutes

  def some_method arg1
    ..
  end
end

また、引数レベルのキャッシュもサポートしています

于 2014-06-09T23:33:44.307 に答える
0

他の答えは素晴らしいですが、単純な手巻きのアプローチが必要な場合は、これを行うことができます. クラスで以下のようなメソッドを定義します...

def use_cache_if_available(method_name,&hard_way)
 @cached_retvals ||= {}  # or initialize in constructor
 return @cached_retvals[method_name] if @cached_retvals.has_key?(method_name)
 @cached_retvals[method_name] = hard_way.call
end

その後、キャッシュしたいメソッドごとに、メソッド本体を次のようにラップすることができます...

def some_expensive_method(arg1, arg2, arg3)
  use_cache_if_available(__method__) {
    calculate_it_the_hard_way_here
  }
end

これが上記の最も単純な方法よりも優れていることの 1 つは、nil をキャッシュすることです。重複するメソッドを作成する必要がないという便利さがあります。ただし、おそらく gem のアプローチの方がクリーンです。

于 2016-02-15T04:28:42.697 に答える
0

私自身の宝石を提案したいと思います https://github.com/igorkasyanchuk/rails_cached_method

例えば:

class A
  def A.get_listings
    ....
  end
end

ただ電話してください:

A.cached.get_listings
于 2021-06-23T14:24:35.093 に答える