walta
walta

Reputation: 3466

Loop through 2 model objects at once rails

I have a users object that I'm exposing through the simple call:

@users = User.all

I also have some more expensive queries I'm doing where I'm using custom SQL to generate the results.

@comment_counts = User.received_comment_counts

This call and others like it will return objects with one element per user in my list ordered by id.

In my view I'd like to loop through the users and the comment_counts object at the same time. Eg:

for user, comment_count in @users, @comment_counts do
end

I can't figure out how to do this. I also can't seem to figure out how to get an individual record from the @comment_counts result without running it through @comment_counts.each

Isn't there some way to build an iterator for each of these lits objects, dump them into a while loop and step the iterator individually on each pass of the loop? Also, if you can answer this where can I go to learn about stepping through lists in rails.

Upvotes: 4

Views: 3369

Answers (3)

D-side
D-side

Reputation: 9495

It's not obvious because your data requires a bit of restructuring. comment_count clearly belongs to instances of User and this should be reflected so that only loop on one collection (of Users) is necessary. I can think of two possible ways to achieve this:

  1. Eager loading. Only works for associated models, not the case here probably. Say, each of your users has comments, so writing User.includes(:comments).all would return all users with their comments and only do 2 queries to fetch the data.

  2. For counting each user's comments you could just use counter_cache (clickable). Then you'll have one more field in the users table for caching how many comments a user has. Again, works for associated Comments only.

Upvotes: 0

Wizard of Ogz
Wizard of Ogz

Reputation: 12643

Something like this should work for you:

@users.zip(@comment_counts).each do |user, comments_count|
  # Do something
end

I've never come across manual manipulation of iterators in Ruby, not to say that it can't be done. Code like that would likely be messy and so I would likely favor more elegant solutions.

Upvotes: 7

Sam 山
Sam 山

Reputation: 42863

Assuming the arrays have equal values:

In your controller:

@users = User.all
@comments = Comment.all

In your view.

<% @users.each_with_index do |user, i |%>
    <% debug user %>
    <% debug @comments[i] %>
<% end %>

Then you can just check if the values exists on @comments if you don't know if the arrays have the same number of objects.

Upvotes: 3

Related Questions