Rails中的全局实例变量
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Rails中的全局实例变量相关的知识,希望对你有一定的参考价值。
在我的应用中,用户可以通过表单提交食谱,该表格将在网站上发布。在食谱发布之前,他们通过主持人进行审核。
因此,我的应用程序在导航栏中显示主持人所有当前未发布的食谱的计数,如下所示:
为实现这一目标,我将执行以下操作:
application.rb中
before_action :count_unpublished
def count_unpublished
@unpublished_count = Recipe.where(:published => false).count
end
_navbar.html.erb
<li>
<%= link_to recipes_path do %>
Recipes <span class="badge" style="background-color:#ff7373"><%= @unpublished_count %></span>
<% end %>
</li>
它有效,但我现在想知道这是一个很好的做法,现在每个动作我的应用程序命中配方数据库(这可能不是很优雅)。
有没有更好的解决方案来实现这一目标?
为避免命中数据库,您可以引入缓存。它有多种形式:更快的存储(memcached,redis),进程内缓存(全局/类变量)等。并且它们都有相同的问题:您需要知道何时使缓存无效。
看看本指南,了解一些想法:Caching with Rails。
如果我是你,我不会关心这个,直到我的剖析器告诉我这是一个性能问题。相反,我会努力开发其余的功能。
cache_key = "#{current_user.id}_#{unpublished_count}"
@unpublished_count = Rails.cache.fetch(cache_key, expires_in: 12.hours) do
Recipe.where(:published => false).count
end
更多:http://guides.rubyonrails.org/caching_with_rails.html#low-level-caching
你陷入了过早优化的陷阱。在进行任何优化之前(大多数情况下会增加代码复杂性),您必须分析代码以找到瓶颈。改善计算总响应时间的一小部分的SQL请求是没用的。相反,如果SQL花费了大量时间,那就是一个很大的改进。
为此,我可以推荐这两颗宝石:
- https://github.com/miniProfiler/rack-mini-profiler
- https://github.com/BaseSecrete/rorvswild(免责声明:我是这个人的作者)
要回答您的问题,更好的方法是:
# app/models/recipe.rb
class Recipe < AR::base
# A nice scope that you can reuse anywhere
scope :unpublished, -> { where(published: false) }
end
然后在你的navbar.html.erb中:
<li>
<%= link_to recipes_path do %>
Recipes <span class="badge" style="background-color:#ff7373"><%= Recipe.unpublished.count %></span>
<% end %>
</li>
你在控制器中没有这些丑陋的回调和实例变量。
除非你有很多食谱(类似于100K或更多),否则性能不会成为问题。在这种情况下,您可以添加索引:
CREATE INDEX index_recipes_unpblished ON recipes(published) WHERE published='f'
请注意,仅当发布为false时,索引才适用。否则会产生反作用。
我认为在你的情况下缓存并不好,因为失效是非常复杂的,并导致可怕的易破坏代码。不要担心打到数据库,我们永远不会写比PostgreSQL / mysql更快的代码等。
以上是关于Rails中的全局实例变量的主要内容,如果未能解决你的问题,请参考以下文章