Reputation: 11673
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 %>
How should I change the scope method (or change something else?) in the User model to get the recipes?
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
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