在Rails中缓存昂贵的非渲染数据列表的最佳实践

时间:2011-10-20 15:42:30

标签: ruby-on-rails ruby-on-rails-3 caching

这是一个普遍的问题,但为了解决这个问题,我们来讨论一个具体的例子。假设您的应用程序经常使用包含世界上所有国家/地区列表的表单。这些国家/地区存储在数据库的countries表中,但此表很少更新,只能通过seeds.rb文件进行更新。

为了能够在每个请求中节省一点时间,我通常按如下方式处理这类事情:

module ApplicationHelper

    def self.get_countries
        countries = Country.order("name asc").all.collect{|country| [country.name, country.name]}
        countries.unshift(["",""])
        countries
    end

    # In production mode (cache_classes = true) this is executed only once, and 
    # will remain cached until you restart your application server
    @@COUNTRIES =  ApplicationHelper.get_countries

    # This would be called from various views
    def countries_for_select(country)
        selected = country.name unless country.nil?
        options_for_select(@@COUNTRIES, selected)
    end
end

这是一种合理的方法吗?

请不要建议存储数据库中的国家/地区列表。我知道还有其他方法可以管理国家/地区列表。我并不是真的关心国家 - 这是我能想到的最容易理解的例子来说明这个一般性的问题。

1 个答案:

答案 0 :(得分:0)

我不确定“非渲染数据”是什么意思。使用您的方法,表单视图仍然需要遍历所有国家/地区,并为每个国家/地区呈现选项。

<select id="user_country" name="user[country]">
  <option value="US">United States</option>
  <option value="CA">Canada</option>
  <option value="ET">Etcetera</option>

但是,如果将select包装在片段缓存中,那么第一次在最后一次部署后呈现表单时,将呈现选择选项,然后将其缓存到/ tmp / cache中的单独文件中。然后在每次后续加载表单时,rails将使用该缓存文件,就像它是部分文件一样并插入到表单中。

<% form_for @user do |form| %>
  <% cache('user_countries_selector') do %>
    <% form.select :country, Country.order("name asc").all.collect{|country [country.name, country.name]}
  <% end %>
  <% etc, etc, etc %>
<% end %>

虽然在实践中,我可能会将Country.order...代码移出到辅助方法。使用此方法完全不需要将国家/地区列表缓存到@@ COUNTRIES。

如果您需要以其他形式呈现国家/地区,则应将不同的密钥传递给cache(),因为呈现的选择标记的ID和名称将是特定于表单的。