Rails(ERB):如果条件失败,我可以取消片段缓存吗?

时间:2016-11-02 19:53:53

标签: ruby-on-rails ruby caching erb

如果条件失败,我正在寻找一种简单有效的方法来取消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天,而不是在下次加载时重试服务器。

(通常情况下这不会发生在视图中,但在这种情况下我会为更大的rails应用程序编写插件并且无法修改控制器,只能修改视图。)

这就是我想要做的事情:

<% 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 %>

有没有人建议如何做到这一点?

2 个答案:

答案 0 :(得分:0)

由于您不希望在出现异常时缓存结果,因此应将异常处理代码放在cache块之外:

<% 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 :(得分:-1)

  

计算机科学存在两个难题:命名事物,缓存失效和逐个错误。

欢迎来到第二个难题。

尝试使用Rails.cache代替cache - 我不是百分之百的差异,或者是否有一个,但Rails.cache为您提供了一些更明显的缓存方法操作

Rails.cache.fetch有三个选项:缓存键,选项哈希和块。如果指定的密钥存在于缓存中且未过期,则它将返回缓存的内容;否则,它将执行该块并将其结果存储在缓存中。

<% 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块中被删除,但是当整个块已经删除时重新添加完成执行。在这种情况下,试试这个:

<% 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 %>