Reputation: 282
The DB relation in rails models:
Class User < ActiveRecord::Base
has_many :user_messages
has_many :messages
end
Class UserMessage < ActiveRecord::Base
belongs_to :user
belongs_to :message
end
Class Message < ActiveRecord::Base
belongs_to :user
has_many :user_messages
end
I want to optimize the following code:
ids.each do |id|
user = User.find_by_id(id)
unread_count = user.user_messages.where(:folder => user.inbox_id, :read => false).count
puts "UserID #{id} ---- Unread Message count #{unread_count}"
end
Can some tell me how can I optimize the above code using Active record or SQL Query. I basically want to reduce DB queries and time the above code take to complete the loop.
Thanks in advance.
Upvotes: 0
Views: 298
Reputation: 1923
You can do something like this:
users = User.where(id: ids).includes(:user_messages)
users.each do |user|
unread_count = user.user_messages.where(:folder => user.inbox_id, :read => false).count
puts "UserID #{user.id} ---- Unread Message count #{unread_count}"
end
Since you are eager loading user_messages
, it won't fire any other DB query inside the loop. Only 1 query to fetch user and it's user_messages.
Or you can do something like:
user_messages = UserMessage.joins(:user).where('folder = users.inbox_id AND read = false').group(:user_id).count
# user_messages = {1=>10, 2=>19}
# Here keys are user ids and values are no of user_messages for that user
user_messages.each do |user_id,unread_msg_count|
puts "UserID #{user_id} ---- Unread Message count #{unread_msg_count}"
end
PS: I have not tested any code, please comment any error if you have any. And I assumed here puts "UserID #{ids}
you want to put a single user id and modified my code according to it, since in your code it will print all the ids ids
.
Upvotes: 1