Alex Antonov
Alex Antonov

Reputation: 15156

rails 4 double has_many includes

I have difficulties with double has_many & includes

There is a twitter-style app (with Users, Tweets, and Likes)

class User
  has_many :tweets # direct tweets
  has_many :likes # liked tweets
end

class Tweet
  belongs_to :user 
  has_many :likes

class Like
  belongs_to :like
  belongs_to :user
end

Here is spreads query:

@tweets = Tweet.first(20).includes(:likes) # I need to do includes or joins et.c.

I have a partial which rendering one tweet and saying to current_user about his like status to particular tweet (something like that):

(tweet.likes & current_user.likes).any? # I can't do efficient query here

And I get classic n+1 query. What should I do to prevent it?

Upvotes: 0

Views: 261

Answers (2)

evanbikes
evanbikes

Reputation: 4171

In your partial, I presume you want the current_user's likes for that tweet.

In that case, I would do this in the view:

current_user_likes_for_tweet = current_user.likes.select { |a| a.tweet_id == tweet.id }
(tweet.likes & current_user_likes_for_tweet).any?

This way, current_user.likes will be cached by Rails and you're just doing a filter on an array in memory.

You could also do this:

Controller

@current_user_likes = current_user.likes.group_by(&:tweet_id)

View

(tweet.likes & @current_user_likes[tweet.id].to_a).any? # to_a because it might be nil

Upvotes: 0

itzmurd4
itzmurd4

Reputation: 663

Try this:

class User
  has_many :tweets # direct tweets
  has_many :likes # liked tweets
end

class Tweet
  belongs_to :user 
  has_many :likes, through: :users

class Like
  belongs_to :like
  belongs_to :user
end

Upvotes: 1

Related Questions