Obed Lorisson
Obed Lorisson

Reputation: 449

return the count for element in a has_many relationships

i have 2 models one is listing and user user has_many listings listing belongs_to user

i have a view setup , i want to display for each user their own listings count ,i try this code :

<% User.all.each do |user| %>
<%= user.listings.count %>
<% end %>

i want to grab the listing count for each user . i found a bunch of solution here , all return the loop .other solutions i tried is to create a class method .

def count_listings
  Listing.where(:user_id => user.id).count
end 

try to call this way <%= User.count_listings%> it doesn't work . for some reason there something i'm missing ,can't quite figure it out .

Upvotes: 0

Views: 748

Answers (2)

jaspreet21anand
jaspreet21anand

Reputation: 779

The :counter_cache option can be used to make finding the number of belonging objects more efficient. Consider these models:

class Order < ActiveRecord::Base
  belongs_to :customer
end
class Customer < ActiveRecord::Base
  has_many :orders
end

With these declarations, asking for the value of @customer.orders.size requires making a call to the database to perform a COUNT(*) query. To avoid this call, you can add a counter cache to the belonging model:

class Order < ActiveRecord::Base
  belongs_to :customer, counter_cache: true
end
class Customer < ActiveRecord::Base
  has_many :orders
end

With this declaration, Rails will keep the cache value up to date, and then return that value in response to the size method.

Although the :counter_cache option is specified on the model that includes the belongs_to declaration, the actual column must be added to the associated model. In the case above, you would need to add a column named orders_count to the Customer model. You can override the default column name if you need to:

class Order < ActiveRecord::Base
  belongs_to :customer, counter_cache: :count_of_orders
end
class Customer < ActiveRecord::Base
  has_many :orders
end

Counter cache columns are added to the containing model's list of read-only attributes through attr_readonly.

source: Rails guide on associations ..scroll down to options of belongs_to

Upvotes: 1

xlembouras
xlembouras

Reputation: 8295

If all you need is what you show in the example you can do it better as follows

<% Listing.group(:user_id).count.each do |user, count| %>
  <%= "user: #{user} has #{count} listings" %>
<% end %>

This does a single query to the database and fetches only what you need.

SELECT COUNT(*) AS count_all, user_id AS user_id FROM `listings` GROUP BY user_id

and returns a hash like:

{
  1: 123,
  2: 231
}

#{ user_id: count }

Upvotes: 1

Related Questions