25
1.9.3p194 :002 > u = User.find_by_email("email@mail.ru")
1.9.3p194 :005 > u.addresses.size
 => 1 
1.9.3p194 :006 > u.addresses.length
 => 1 
1.9.3p194 :007 > u.addresses.count 

Rails 3.2.3 中的大小、长度和计数没有区别,不是吗?

4

3 回答 3

50

长度将加载所有对象只是为了计算它们;就像是:

select * from addresses...

然后返回结果计数。你可以想象 - 这是糟糕的表现

计数只会发出

select count(*) from addresses...

哪个更好,因为我们加载所有地址并不是为了计算它们

size更智能 - 它会检查关联是否已加载,如果为 true,则返回长度(不调用数据库)。

如果您的用户模型中有一个名为address_count的字段, size还会检查counter_cache,然后 size 将使用该字段进行计数,因此无需在地址表上发出计数。

如果全部失败,sizeselect count(*)将在数据库上发出

于 2012-09-04T06:04:46.387 回答
4

1) 在 rails count 是一个 ActiveRecord 方法,因此 count 可以直接应用于模型名称:

> User.count
   (1.4ms)  SELECT COUNT(*) FROM "users"
=> 1

但是 size 不是 ActiveRecord 方法,因此它会抛出错误

> User.size
"NoMethodError".

2) Rails 中的大小可以与 ActiveRecord 数组一起使用(即 size 是 Array 方法)

> User.all.size
   (1.2ms)  SELECT COUNT(*) FROM "users"
=> 1 

3) count 将始终触发 ActiveRecord 查询。但 size 不会触发 ActiveRecord 查询,仅当记录或 ActiveRecord 数组已加载(执行)为:

  > d=User.all
  User Load (18.1ms)  SELECT "users".* FROM "users"
 => #<ActiveRecord::Relation [#<User id: 1, email: "fasf@f.df", name: "mano", dob: "2017-02-16", address: "fasfafasf", created_at: "2017-02-12 08:16:12", updated_at: "2017-02-12 09:34:07", online: false>]> 
2.3.3 :009 > 
2.3.3 :010 >   d.count
   (1.3ms)  SELECT COUNT(*) FROM "users"
 => 1 
2.3.3 :011 > d.size
 => 1 
于 2017-03-18T17:17:49.457 回答
2

如果“地址”是一个看起来像的关联,那么它们是不同的,但它们应该返回相同的结果。

#count 由 ActiveRecord 提供,将执行类似“select count(*) from addresses where user_id =”之类的操作。

在其他情况下,#addresses 将构建一个包含实际模型对象的数组,并且 #size 和 #length 由 Array 类或 Enumerable 提供。

所以#count 可能更快,因为计数发生在数据库中。如果您确实需要地址,那就不好了:)

于 2012-09-04T04:49:24.843 回答