Ответ 1
Конкретная настройка, которую вы описываете, смешивает несколько типов ассоциаций.
A) Пользователь и рецепт
Сначала у нас есть модель пользователя и вторая модель рецепта. Каждый рецепт принадлежит одному пользователю, поэтому у нас есть рецепт User: has_many, Recipe принадлежит_to: user association. Эта взаимосвязь сохраняется в поле user_id рецепта.
$ rails g model Recipe user_id:integer ...
$ rails g model User ...
class Recipe < ActiveRecord::Base
belongs_to :user
end
class User < ActiveRecord::Base
has_many :recipes
end
B) FavoriteRecipe
Далее нам нужно решить, как реализовать рассказ о том, что пользователь должен иметь возможность отмечать избранные рецепты.
Это можно сделать, используя модель объединения - позвольте ей FavoriteRecipe - со столбцами: user_id и: recipe_id. Здесь мы создаем ассоциацию has_many: через.
A User
- has_many :favorite_recipes
- has_many :favorites, through: :favorite_recipes, source: :recipe
A Recipe
- has_many :favorite_recipes
- has_many :favorited_by, through: :favorite_recipes, source: :user
# returns the users that favorite a recipe
Добавление этого фаворита has_many: через ассоциацию с моделями, мы получаем наши окончательные результаты.
$ rails g model FavoriteRecipe recipe_id:integer user_id:integer
# Join model connecting user and favorites
class FavoriteRecipe < ActiveRecord::Base
belongs_to :recipe
belongs_to :user
end
---
class User < ActiveRecord::Base
has_many :recipes
# Favorite recipes of user
has_many :favorite_recipes # just the 'relationships'
has_many :favorites, through: :favorite_recipes, source: :recipe # the actual recipes a user favorites
end
class Recipe < ActiveRecord::Base
belongs_to :user
# Favorited by users
has_many :favorite_recipes # just the 'relationships'
has_many :favorited_by, through: :favorite_recipes, source: :user # the actual users favoriting a recipe
end
C) Взаимодействие с ассоциациями
##
# Association "A"
# Find recipes the current_user created
current_user.recipes
# Create recipe for current_user
current_user.recipes.create!(...)
# Load user that created a recipe
@recipe = Recipe.find(1)
@recipe.user
##
# Association "B"
# Find favorites for current_user
current_user.favorites
# Find which users favorite @recipe
@recipe = Recipe.find(1)
@recipe.favorited_by # Retrieves users that have favorited this recipe
# Add an existing recipe to current_user favorites
@recipe = Recipe.find(1)
current_user.favorites << @recipe
# Remove a recipe from current_user favorites
@recipe = Recipe.find(1)
current_user.favorites.delete(@recipe) # (Validate)
D) Действия контроллера
Может быть несколько подходов к тому, как реализовать действия контроллера и маршрутизацию. Мне очень нравится Ryan Bates, показанный в Railscast # 364 в системе репутации ActiveRecord. Часть решения, описанного ниже, структурирована вдоль линий движения вверх и вниз.
В нашем файле маршрутов мы добавляем маршрут участника по рецептам, называемым фаворитами. Он должен отвечать на запросы по почте. Это добавит вспомогательный URL-адрес favorite_recipe_path (@recipe) для нашего представления.
# config/routes.rb
resources :recipes do
put :favorite, on: :member
end
В нашем RecipesController теперь мы можем добавить соответствующее любимое действие. Там нам нужно определить, что пользователь хочет делать, выгодно или неприглядно. Для этого параметр запроса, называемый, например, тип может быть введен, что нам также нужно будет передать в наш помощник по ссылке позже.
class RecipesController < ...
# Add and remove favorite recipes
# for current_user
def favorite
type = params[:type]
if type == "favorite"
current_user.favorites << @recipe
redirect_to :back, notice: 'You favorited #{@recipe.name}'
elsif type == "unfavorite"
current_user.favorites.delete(@recipe)
redirect_to :back, notice: 'Unfavorited #{@recipe.name}'
else
# Type missing, nothing happens
redirect_to :back, notice: 'Nothing happened.'
end
end
end
По вашему мнению, вы можете добавить соответствующие ссылки на благоприятные и непривлекательные рецепты.
<% if current_user %>
<%= link_to "favorite", favorite_recipe_path(@recipe, type: "favorite"), method: :put %>
<%= link_to "unfavorite", favorite_recipe_path(@recipe, type: "unfavorite"), method: :put %>
<% end %>
Что это. Если пользователь нажимает ссылку "Избранное" рядом с рецептом, этот рецепт добавляется к избранным current_user.
Я надеюсь, что это поможет, и, пожалуйста, задавайте любые вопросы, которые вам нравятся.
Руководства по Rails для ассоциаций являются довольно подробными и помогут вам при запуске.