BrainLikeADullPencil
BrainLikeADullPencil

Reputation: 11673

accessing association of an association

I have a Rails app with a user model that sets up friend relationships like this

User.rb

has_many :friendships
has_many :friends, :through => :friendships

Each user has a has_many association with the Recipe.rb model

In my app, I want to post recipes on a user's show page by the friends of that user. i.e. go through the friends association to get the recipes of the friends. Therefore, I do this in the users_controller.rb

def show 
  @friend_recipes = []
  @user.friendships.each do |friendship|
    @friend_recipes << User.recipes_by_friends(friendship.friend_id)
  end 
end

which calls the class method recipes_by_friends on the user model

User.rb

scope :recipes_by_friends, lambda { |friend_id|
  joins(:recipes).
  where(recipes: {user_id: friend_id})     
}

In the user show page, I try to show each of the recipes. However, in the code below, the recipe local variable is actually an active record relation for the friend, not the recipes for the friend.

/views/users/show.html.erb

<% @friend_recipes.each do |recipe| %></li> 
  <%= recipe.inspect %>  ## this is the relation for the user, not the recipe 
<% end %> 
  1. How should I change the scope method (or change something else?) in the User model to get the recipes?

  2. Is this the best way to loop through friends and add their recipes to an array?

    @user.friendships.each do |friend|
      @friend_recipes << User.recipes_by_friends(friend.friend_id)
    end
    

Upvotes: 2

Views: 79

Answers (1)

Marcelo De Polli
Marcelo De Polli

Reputation: 29301

I believe you can let ActiveRecord do the grunt work for you in this case.

user.rb

has_many :friend_recipes, :through => :friends, :source => :recipes

users_controller.rb

def show 
  @friend_recipes = @user.friend_recipes 
end

The actual SQL query generated by that would be:

2.0.0p247 :001 > user = User.first
2.0.0p247 :002 > user.friend_recipes
  Recipe Load (1.7ms)  SELECT "recipes".* FROM "recipes" INNER JOIN "friends" ON "recipes"."friend_id" = "friends"."id" INNER JOIN "friendships" ON "friends"."id" = "friendships"."friend_id" WHERE "friendships"."user_id" = ?  [["user_id", 1]]

Upvotes: 2

Related Questions