2016-11-02 4 views
1

条件が失敗した場合、ERBビュー内の名前付きフラグメントのキャッシュ書き込みをキャンセルする簡単で効率的な方法を探しています。Rails(ERB):条件が失敗した場合にフラグメントキャッシュをキャンセルできますか?

私は現在、これをやっている:

<% cache("header_#{$I18n.locale}", expires_in: 1.day) do %> 
    <% begin %> 
     <%= raw open("https://mywebsite.org/remote/fragment", :read_timeout => 10).read %> 
    <% rescue OpenURI::HTTPError => e %> 
    Error Loading Remote File: <%= e.message %> 
    <% end %> 
<% end %> 

明らかにこれのいくつかは、生産コードのためのベストプラクティスを表示しないように、ちょうど私の問題を実証することです。

ここに問題があります:上記のエラーメッセージがキャッシュされ、次回のロード時にサーバーを再試行するのではなく、1日間表示されます。

(通常、これはビューでは起こっていないだろうが、この場合には、私は大きなレールのアプリのためのプラグインを書いていると、コントローラ、ちょうどビューを変更することはできません。)

です私は何をしたいのですが:

<% cache("header_#{$I18n.locale}", expires_in: 1.day) do %> 
    <% begin %> 
     <%= raw open("https://mywebsite.org/remote/fragment", :read_timeout => 10).read %> 
    <% rescue OpenURI::HTTPError => e %> 
    --> Some command to cancel the cache action started above 
    --> Show a backup something to the user (I'll provide) 
    <% end %> 
<% end %> 

誰もがこれを行う方法についての提案を持っていますか?

+0

私はこれに完全な答えを得る時間がありませんが、私の2つの提案は、a) 'cache'呼び出しを_inside_' begin'ブロックに置きます。そうすると例外が発生し、 'cache'必要に応じて、['expire_fragment'メソッド(http://edgeapi.rubyonrails.org/classes/ActionController/Caching/Fragments.html#method-i-expire_fragment)も使用してください。 – philomory

+0

@philomory私のテストでは、キャッシュブロックをbeginブロック内に置くことをお勧めします。これを正解とすることができますか? –

答えて

0

:その場合は、これを試して

<% begin %> 
    <% cache("header_#{$I18n.locale}", expires_in: 1.day) do %> 
    <%= raw open("https://mywebsite.org/remote/fragment", :read_timeout => 10).read %> 
    <% end %> 
<% rescue OpenURI::HTTPError => e %> 
    Error Loading Remote File: <%= e.message %> 
<% end %> 

ことキャッシュブロック内で例外が発生すると、そのブロックは完了する前に終了し、キャッシングは発生しません。

-1

コンピュータサイエンスには、名前を付けること、キャッシュの無効化、オフバイワンエラーという2つの問題があります。

第2の難しい問題にようこそ。

Rails.cache代わりのcacheを使用してみてください - 私は、違いは何であるかまたは存在した場合は100%ないんだけど一つでもありますが、あなたのキャッシュ操作のためのいくつかのより多くの明白な方法をRails.cache取得します。

Rails.cache.fetchは、キャッシュキー、オプションハッシュ、およびブロックの3つのオプションをとります。指定されたキーがキャッシュに存在し、期限切れでない場合は、キャッシュの内容を返します。それ以外の場合は、ブロックを実行し、その結果をキャッシュに格納します。

<% Rails.cache.fetch "header_#{$I18n.locale}", :expires_in => 1.day do %> 
    <% begin %> 
    <%= raw open("https://mywebsite.org/remote/fragment", :read_timeout => 10).read %> 
    <% rescue OpenURI::HTTPError => e %> 
    <% Rails.cache.delete "header_#{$I18n.locale}" # removes the cache entry %> 
    <!-- Show your backup here --> 
    <% end %> 
<% end %> 

問題が解決しない場合は、キャッシュ操作がで行われている順序まで可能性があります - それは全体のブロックがある場合、エントリがあなたのrescueブロックで削除が、その後再追加されるのかもしれ実行を終了しました。あなたは例外があるときの結果をキャッシュしたくないので、あなたはcacheブロックの外側で、あなたの例外処理コードを配置する必要があり

<% remove_cache_entry = false %> 

<% Rails.cache.fetch "header_#{$I18n.locale}", :expires_in => 1.day do %> 
    <% begin %> 
    <%= raw open("https://mywebsite.org/remote/fragment", :read_timeout => 10).read %> 
    <% rescue OpenURI::HTTPError => e %> 
    <% remove_cache_entry = true %> 
    <!-- Show your backup here --> 
    <% end %> 
<% end %> 

<% Rails.cache.delete "header_#{$I18n.locale}" if remove_cache_entry %> 
+0

私は最初の方法をテストし、これが機能しないことを確認できます。私はプロセスの各ステップでキャッシュキーを監視し、キャッシュブロックの最後の前にキーが書き込まれていないため、Rails.cache.deleteにはまだ削除するキーがありません。私は2番目のブロックをテストしませんでしたが、それがうまくいくとわかっていることに基づいており、場合によってはベストかもしれません。例外を扱う際の最も簡単な解決策ではありません。彼のコメントでは@philomoryに行くことになります。書き込みはブロックの最後まで実行されないので、発生した例外は書き込みが起こらないようにします。 –

関連する問題