2013-10-08 2 views
2

У меня есть приложение Rails с моделью пользователя, который устанавливает другу отношения, как этотдоступа ассоциация ассоциации

User.rb

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

Каждый пользователь имеет has_many ассоциацию с моделью Recipe.rb

В моем приложении я хочу публиковать рецепты на странице показа пользователей от друзей этого пользователя. то есть пройти через ассоциацию друзей, чтобы получить рецепты друзей. Поэтому, я делаю это в users_controller.rb

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

который вызывает метод класса recipes_by_friends на модели пользователя

User.rb

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

В пользовательском шоу странице, я стараюсь показать каждый из рецептов. Однако в приведенном ниже коде локальная переменная рецепта фактически является активным отношением записи для друга, а не рецептами для друга.

/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. Как следует изменить метод Scope (или изменить что-то еще?) В модели пользователя, чтобы получить рецепты?

  2. Это лучший способ связаться с друзьями и добавить их рецепты в массив?

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

Для # 2, я бы use @ user.friendships.map {| v | блок}. Если бы блок мог возвратить nil, добавьте с .compact – rdmcfee

+0

Спасибо. Вы знаете, как изменить метод области, чтобы он возвращал рецепты, а не друг? – BrainLikeADullPencil

+0

'recipes_by_friends' - это запрос, поэтому он возвращает коллекцию совпадений. В вашем случае, я думаю, вы принимаете один матч? В этом случае вы можете сделать: '<% = recipe.first.inspect%>'. Если есть кратные, вам может понадобиться «внутренний каждый»: '<% recipe.each do | r | %> ... '. – lurker

ответ

2

Я считаю, что вы можете позволить ActiveRecord делать черновую работу за вас в этом случае.

user.rb

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

users_controller.rb

def show 
    @friend_recipes = @user.friend_recipes 
end 

Фактический SQL запрос генерируется, что будет:

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]] 
+1

Существует не модель под названием FriendRecipe, поэтому я не знаю, можете ли вы сделать has_many: friend_recipes. Однако, когда я пытаюсь выполнить свой код, я получаю ошибку «слишком высокий уровень стека». – BrainLikeADullPencil

+0

Пожалуйста, уточните мой обновленный ответ. Я просто сделал тестовое приложение с этими ассоциациями, чтобы убедиться, что они будут работать (они сделали).Не нужно беспокоиться о том, что модель не существует, потому что 'has_many' принимает в качестве аргумента только имя ассоциации, которое может быть любым, что вы хотите, до тех пор, пока вы предоставляете другие параметры, которые помогают Rails выяснить, где найти Информация. В нашем случае это делается опцией ': source'. – depa

+0

Большое спасибо за вашу помощь. – BrainLikeADullPencil

Смежные вопросы