mazing
mazing

Reputation: 743

Understanding rails size vs count, and why .size doesn't work in view?

When I use the method .count, it works just fine and accurately shows the number of posts. When I try .size, it throws an error. Why is this?

My static_controller.rb code (with COUNT as a method)

class StaticController < ApplicationController

def index
@post_count = Post.count
@user_count = User.count
end

index.html.erb (with COUNT as a method)

<div>
      <p> <%= @post_count %> </p>
</div>

When I change the instances of .count to size, I get this error in the local server:

NoMethodError at / undefined method `size' for #

index - app/controllers/static_controller.rb, line 4

Why is this? Is .size not a built in method for rails? If not, how can I fix this issue?

Also, am I correct in understanding that .size is more performant if a counter_cache is applied to the model that the method is being applied to? For example, if my post.rb model has a section where counter_cache is declared, does that automatically make it more fast/performant?

Upvotes: 6

Views: 2735

Answers (2)

burgund
burgund

Reputation: 402

There are 3 similar methods:

  • count which is using SQL query. That's the fastest way but as you have noticed, not always possible to perform.

  • length will return length of a collection without performing additional queries if collection is already loaded. It may be ineffective because it will load a whole collection into memory.

  • size It's a combination of both count and length. Will perform additional query only if collection is unloaded.

Upvotes: 4

Syl
Syl

Reputation: 3829

count is an AR method, it will use COUNT in the SQL query, and it actually makes AR aware that you are doing a database query, and it return the count value returned by the database.

Size is a method for collections, Post and User are classes, not collections, so AR is never used, and you end up with an error, because you first need to do an AR query to have a collection, even an empty one.

The rails way to do what you try is to use all, that will return a collection.

@post_count = Post.all.size
@user_count = User.all.size

Upvotes: 4

Related Questions