在Rails中做正确的方法是什么?

时间:2010-12-14 13:42:32

标签: sql ruby-on-rails ruby count

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

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

我的问题是这是对观点进行统计的正确方法吗?看起来如此“肮脏”是否有更多的铁路,做点算的方法?我可能正在考虑命名范围,但我只是想确保这些类型的事情不会对性能产生更大的影响。

谢谢,

6 个答案:

答案 0 :(得分:9)

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

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

但命名范围是使代码更具可重用性的绝佳方法。

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

答案 1 :(得分:6)

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

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

这将使您的视图更清晰,更容易调试,如果您以不同的格式(html,json等)渲染动作,也会更加干燥

至于你如何得到你的数字 - 这并不重要,只需从find_ *方法转向范围界定并编写可读代码

答案 2 :(得分:2)

命名范围不应对性能产生影响

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

然后你可以拥有Account.not_admin.count

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

答案 3 :(得分:2)

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

Contact.count

解析为:

SELECT COUNT(*) AS count_id FROM "contacts"

按字段名称查找全部将解析为:

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')

答案 4 :(得分:0)

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

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

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

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

答案 5 :(得分:0)

您应该在控制器中创建一个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 %>