在 Rails 中缓存昂贵的非渲染数据列表的最佳实践
这是一个一般性问题,但为了理解这一点,让我们讨论一个具体的例子。假设您有一个经常使用包含世界上所有国家/地区列表的表单的应用程序。这些国家/地区存储在数据库的 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
这是一个合理的方法吗?
请不要建议不将国家/地区列表存储在数据库中。我知道还有其他方法可以管理国家/地区列表。我并不真正关心国家 - 这只是我能想到的最容易理解的例子来说明这个一般性问题。
This is a general question, but to get the point across, let's discuss a specific example. Suppose you have an application that frequently uses forms that include a list of all the countries in the world. The countries are stored in the countries
table in your DB, but this table is updated very very rarely, and only through your seeds.rb file.
In order to be able to shave off a little time in each request, I typically manage this sort of thing as follows:
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
Is this a reasonable approach?
Please don't suggest not storing the list of countries in the database. I'm aware there are other ways to manage lists of countries. I'm not really concerned with countries - it's just the easiest to understand example I could think of to illustrate this general question.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我不确定“非渲染数据”是什么意思。使用您的方法,表单视图仍然需要遍历所有国家/地区并为每个国家/地区的选择呈现一个选项。
但是,如果您将选择包装在片段缓存中,则在上次部署后第一次呈现表单时,将呈现选择选项,然后将其缓存到 /tmp/cache 中的单独文件中。然后,在每次加载表单时,rails 将使用该缓存文件,就好像它是部分文件并插入到表单中一样。
尽管在实践中,我可能会将
Country.order...
代码移至辅助方法中。使用此方法完全不需要将国家/地区列表缓存到@@COUNTRIES。如果您需要以其他形式呈现国家/地区选择,则应将不同的键传递给
cache()
,因为呈现的选择标记的 ID 和名称将是特定于形式的。I'm not sure what you mean by "non-rendered data". With your method, the form view still needs to loop through all of the countries and render an option for the select for each one.
If, however, you wrapped the select in a fragment cache, then the first time the form was rendered after the last deploy, the select options would be rendered and then cached into a separate file in /tmp/cache. Then on every subsequent time the form is loaded, that cached file would be used by rails as if it were a partial and inserted into the form.
although, in practice, I would probably move the
Country.order...
code out to a helper method. Caching the list of countries to @@COUNTRIES is completely unnecessary with this method.If you need to render a country select in other forms, you should pass a different key to
cache()
since the id and name of the rendered select tag will be form specific.