Подтвердить что ты не робот

Внесите "Добавить в избранное" в 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, поэтому у меня есть это:

<%= button_to("Add to Favorites" :action => "create", :controller => "favorites" %>

Я думаю, что, вероятно, что-то не хватает на своих маршрутах, но я не уверен.

4b9b3361

Ответ 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 для ассоциаций являются довольно подробными и помогут вам при запуске.

Ответ 2

Спасибо за руководство, Томас! Он отлично работает.

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

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

Ответ 3

Эта тема была очень полезна!!

Спасибо!

Не забудьте включить = в теги формы.

<% 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 %>

Ответ 4

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