Внесите «Добавить в избранное» в Rails 3 & 4
Я создаю приложение, в котором пользователи могут создавать рецепты, видеть все созданные рецепты, просматривать свои собственные рецепты в области участников, и, наконец, я бы хотел, чтобы пользователи добавили «избранные» в свою учетную запись.
Я новичок в Rails, но прочитал документы, и это мое понимание того, как оно должно выглядеть в бэкэнд. Мог ли кто-нибудь подтвердить, что это выглядит правильно или сообщить о любых ошибках, пожалуйста, с объяснениями, если я сделал что-то неправильно (что, вероятно, так)?
Итак, это мой код:
Модель пользователя
has_many :recipes has_many_favorites, :through => :recipes
Модель рецепта
belongs_to :user has_many :ingredients #created seperate db for ingredients has_many :prepererations #created seperate db for prep steps
Любимая модель
belongs_to :user has_many :recipes, :through => :user #this model has one column for the FK, :user_id
Избранное
def create @favrecipes =current_user.favorites.create(params[:user_id]) end
Затем я хотел иметь кнопку для публикации в db, поэтому у меня есть следующее:
"create", :controller => "favorites" %>
Я думаю, что, вероятно, что-то не хватает на своих маршрутах, но я не уверен.
Конкретная настройка, которую вы описываете, смешивает несколько типов ассоциаций.
A) Пользователь и рецепт
Сначала у нас есть модель User и вторая модель рецепта. Каждый рецепт принадлежит одному пользователю, поэтому у нас есть рецепт 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 - со столбцами: 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's favorites @recipe = Recipe.find(1) current_user.favorites << @recipe # Remove a recipe from current_user's favorites @recipe = Recipe.find(1) current_user.favorites.delete(@recipe) # (Validate)
D) Действия controllerа
Может быть несколько подходов к тому, как реализовать действия controllerа и маршрутизацию. Мне очень нравится Райан Бейтс, показанный в Railscast # 364 в системе репутации ActiveRecord. Часть решения, описанного ниже, структурирована вдоль линий движения вверх и вниз по голосованию.
В нашем файле маршрутов мы добавляем маршрут участника по рецептам, называемым фаворитом. Он должен отвечать на запросы по почте. Это добавит вспомогательный URL-адрес favorite_recipe_path (@recipe) для нашего представления.
# config/routes.rb resources :recipes do put :favorite, on: :member end
В нашем RecipesController мы можем теперь добавить соответствующее любимое действие. Там нам нужно определить, что пользователь хочет делать, выгодно или неприглядно. Для этого может быть введен параметр запроса, называемый, например, type, который нам также нужно будет передать в наш помощник связи позже.
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 по ассоциациям довольно сложны и помогут вам при запуске.
Спасибо за руководство, Томас! Он отлично работает.
Просто хотелось добавить, что для того, чтобы ваш любимый метод работал правильно, вам нужно обернуть текст в двойные кавычки, а не одинарные кавычки для функции интерполяции строк.
redirect_to :back, notice: 'You favorited #{@recipe.name}'
->
redirect_to :back, notice: "You favorited #{@recipe.name}"
https://rubymonk.com/learning/books/1-ruby-primer/chapters/5-strings/lessons/31-string-basics
Эта тема была очень полезна !!
Спасибо!
Не забудьте включить в tags формы tags =.
<% 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 %>
Выбранный ответ действительно хорош, но я не могу опубликовать комментарий, и у меня действительно есть вопрос о том, что выше. Как вы можете ограничить пользователя одним любимым рецептом? С приведенным выше ответом пользователь может продолжить нажатие на фаворит, и в базе данных будет создано много записей …