Reputation: 888
If i have a model method like:
def favoured_users
self.followers.limit(5).order("created_at")
end
with a view block like:
<% 5.times do |i| %>
<li><%= @user.favoured_users[i].name %></li>
<% end %>
...would I be calling the favoured_user method five times and each time asking for the 5 users, ending up with like 25 users being called?
I'm just wondering if I should put the result of favoured_users in a variable in my controller instead:
@favoured_users = @user.followers.limit(5).order("created_at")
Would that be less calls to the server?
** EDIT **
I'm not sure if this means the value is coming from the cache, it appears it is (bcos of the CACHE, but I dont know thats what it means), but I haven't explicitly told it to, do I have to do anything to make sure it does come fro the cache:
User Load (0.6ms) SELECT `users`.* FROM `users` INNER JOIN `relationships` ON `users`.`id` = `relationships`.`followed_id` WHERE `relationships`.`follower_id` = 1 ORDER BY full_name, created_at LIMIT 5
CACHE (0.0ms) SELECT `users`.* FROM `users` INNER JOIN `relationships` ON `users`.`id` = `relationships`.`followed_id` WHERE `relationships`.`follower_id` = 1 ORDER BY full_name, created_at LIMIT 5
CACHE (0.0ms) SELECT `users`.* FROM `users` INNER JOIN `relationships` ON `users`.`id` = `relationships`.`followed_id` WHERE `relationships`.`follower_id` = 1 ORDER BY full_name, created_at LIMIT 5
CACHE (0.0ms) SELECT `users`.* FROM `users` INNER JOIN `relationships` ON `users`.`id` = `relationships`.`followed_id` WHERE `relationships`.`follower_id` = 1 ORDER BY full_name, created_at LIMIT 5
CACHE (0.0ms) SELECT COUNT(*) FROM `users` INNER JOIN `relationships` ON `users`.`id` = `relationships`.`follower_id` WHERE `relationships`.`followed_id` = 1
User Load (0.5ms) SELECT `users`.* FROM `users` INNER JOIN `relationships` ON `users`.`id` = `relationships`.`follower_id` WHERE `relationships`.`followed_id` = 1 ORDER BY full_name, created_at LIMIT 5
CACHE (0.0ms) SELECT `users`.* FROM `users` INNER JOIN `relationships` ON `users`.`id` = `relationships`.`follower_id` WHERE `relationships`.`followed_id` = 1 ORDER BY full_name, created_at LIMIT 5
CACHE (0.0ms) SELECT `users`.* FROM `users` INNER JOIN `relationships` ON `users`.`id` = `relationships`.`follower_id` WHERE `relationships`.`followed_id` = 1 ORDER BY full_name, created_at LIMIT 5
CACHE (0.0ms) SELECT `users`.* FROM `users` INNER JOIN `relationships` ON `users`.`id` = `relationships`.`follower_id` WHERE `relationships`.`followed_id` = 1 ORDER BY full_name, created_at LIMIT 5
Is the value returning from the cache?
EDIT I'm not sure how to access the variable from my view, I have the method as per Sebi's edit and in my view I am trying to:
<% @user.favoured_followers do %>
<li><%= @favoured.first.username unless @favoured.first.blank? %></li>
<li><%= @favoured.second.username unless @favoured.second.blank? %></li>
<li><%= @favoured.third.username unless @favoured.third.blank? %></li>
<li><%= @favoured.fourth.username unless @favoured.fourth.blank? %></li>
<li><%= @favoured.fifth.username unless @favoured.fifth.blank? %></li>
<% end %>
Nothing is being returned?
Upvotes: 0
Views: 1563
Reputation: 669
If you look in your log you'd be able to verify whether it's hitting the cache or not for each call to the function. This doesn't appear to be hitting the cache so the query to load the followers will be repeated 5 times for each user. i.e for each @user you will fire the query 5 times. So caching the value in a variable is definitely a better idea.
Edit : You could change your model method like this :
def favoured_users
@favoured ||= self.followers.limit(5).order("created_at")
end
The @favoured variable will be created the first time this is called and then for any subsequent calls it will be returned without the query being fired.
Your view code should remain the same without any change. i.e :
<% 5.times do |i| %>
<li><%= @user.favoured_users[i].name %></li>
<% end %>
Upvotes: 3
Reputation: 7733
If i have to do .. i will do below way
Inside controller
@favoured_users = @user.followers.limit(5).order(:created_at)
inside view
<% @favoured_users do |user| %>
<li><%= user.name %></li>
<% end %>
<% (5 - @favoured_users.count).times do%>
<li> </li>
<% end %>
Upvotes: 0