繁体   English   中英

在 Rails 中进行计数的正确方法是什么?

[英]What's the right way to do counts in Rails?

我有一个 Rails 应用程序,其中包含许多以下代码:

Our active community of <%= Account.find_all_by_admin(false).count %>

我的问题是,这是对视图进行计数的正确方法吗? 看起来如此“肮脏”有没有更荒谬的计数方法? 我可能在考虑命名范围,但我只想确保这些类型的东西不会对性能产生更大的影响。

谢谢你,

您不需要名称范围来执行计数。

Account.where(:admin => false).count

但是命名范围是使代码更可重用的极好方法。

命名范围对您的应用程序没有任何明显的性能影响。

我建议你避免在我的模板中直接访问数据库,因为那样你会在缓存方面失去一些灵活性。

尝试准备您需要在操作中呈现的所有数据,然后使用有意义的实例变量,例如@number_of_accounts@accounts.count

如果您以不同的格式(html、json 等)呈现动作,这将使您的视图更清晰、更易于调试,并且也会更 DRY

至于你如何得到你的数字 - 它并不那么重要,只是从 find_* 方法转向范围和编写可读的代码

在 rails 3 中,一个简单的 count 调用会发出一个简单的 count 请求:

Contact.count

被解析为:

SELECT COUNT(*) AS count_id FROM "contacts"

find all by field name 将解析为:

Contact.find_all_by_country("Canada")

SELECT "contacts".* FROM "contacts" WHERE ("contacts"."country" = 'Canada')

我建议为您的管理列建立索引以加快查找速度,这可以转换为命名范围,但它本身只会预定义查询,而不是优化它。

重要的是要注意,如果您发出

Contact.find_all_by_country("Canada").count

count是数组类上的一个方法,实际上并不对数据库发出计数:

Contact.find_all_by_country("Canada").count

SELECT "contacts".* FROM "contacts" WHERE ("contacts"."country" = 'Canada')

命名范围不应影响性能

scope :not_admin, where(:admin => false)

然后你可以有Account.not_admin.count

根据 DGM 的评论进行编辑:要在控制台中检查生成的 SQL, Account.find_all_by_admin(false).to_sql Account.not_admin.to_sqlAccount.find_all_by_admin(false).to_sql进行比较

您可以使用以下查询代替Account.where(:admin => false).count

Account.select(:id).where(:admin => false).count

只需选择一列,而不是选择全部。 它生成以下查询,并且比前一个查询更快:

SELECT COUNT("accounts"."id") FROM "accounts" where admin = false

您应该在控制器中创建一个instance variable并在视图中使用它。 这会让你看得清楚。

@accounts_count = Account.where(admin: false).count

并在视图中使用它,如 `<%= @accounts_count %>

如果要循环遍历结果和计数,可以使用以下方式:

@accounts = Account.where(admin: false)

鉴于,写如下:

<%= @accounts.count %>
// For looping account
<% @accounts.each do |account| %>
  # do some stuff
<% end %>

但上述方式将触发 2 个查询,1 个用于计数,另一个用于循环。

正确的做法

使用size而不是count 它将触发 1 个查询,但您需要更改视图中的计数顺序,例如:

// For looping account
<% @accounts.each do |account| %>
  # do some stuff
<% end %>
<%= @accounts.size %>

如果你想要相同的顺序,那么首先加载用户对象,如下所示

<%= @accounts.load.size %>
// For looping account
<% @accounts.each do |account| %>
  # do some stuff
<% end %>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM