Implementa “Aggiungi ai preferiti” in Rails 3 e 4

Sto costruendo un’app in cui gli utenti possono creare ricette, vedere tutte le ricette create, visualizzare le proprie ricette in un’area membro e infine vorrei che gli utenti aggiungessero “preferiti” al proprio account.

Sono nuovo di Rails ma ho letto i documenti e questa è la mia comprensione di come dovrebbe apparire nel backend. Qualcuno potrebbe confermare che questo sembra corretto o avvisare di eventuali errori per favore, con spiegazioni se ho fatto qualcosa di sbagliato (che è probabilmente il caso)?

Quindi questo è il mio codice:

Modello utente

has_many :recipes has_many_favorites, :through => :recipes 

Modello di ricetta

 belongs_to :user has_many :ingredients #created seperate db for ingredients has_many :prepererations #created seperate db for prep steps 

Modello preferito

 belongs_to :user has_many :recipes, :through => :user #this model has one column for the FK, :user_id 

Controller preferiti

 def create @favrecipes =current_user.favorites.create(params[:user_id]) end 

Allora volevo avere un pulsante per postare sul db, quindi ho questo:

  "create", :controller => "favorites" %> 

Penso che probabilmente manchi qualcosa nei miei percorsi ma non sono sicuro.

La particolare configurazione che descrivi combina diversi tipi di associazioni.

A) Utente e ricetta

Per prima cosa abbiamo un modello utente e un secondo modello ricetta. Ogni ricetta appartiene a un utente, quindi abbiamo un utente: has_many recipes, Recipe belongs_to: user association. Questa relazione è memorizzata nel campo user_id della ricetta.

 $ 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

Quindi dobbiamo decidere come implementare la storia che un utente dovrebbe essere in grado di contrassegnare le ricette preferite.

Questo può essere fatto usando un modello di join - chiamiamolo FavoriteRecipe - con le colonne: user_id e: recipe_id. L'associazione che stiamo costruendo qui è una has_many: attraverso l' associazione.

 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 

L'aggiunta di questi preferiti has_many: attraverso l'associazione ai modelli, otteniamo i nostri risultati finali.

 $ 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) Interagire con le associazioni

 ## # 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) Azioni del controllore

Ci possono essere diversi approcci su come implementare le azioni e il routing del Controller. Mi piace proprio quello di Ryan Bates mostrato in Railscast # 364 sul sistema di reputazione ActiveRecord. La parte di una soluzione descritta di seguito è strutturata lungo le linee del meccanismo di voto su e giù lì.

Nel nostro file Routes aggiungiamo un percorso membro alle ricette chiamate preferite. Dovrebbe rispondere alle richieste di posta. Questo aggiungerà un helper URL preferito_recipe_path (@recipe) per la nostra vista.

 # config/routes.rb resources :recipes do put :favorite, on: :member end 

Nel nostro RecipesController possiamo ora aggiungere l'azione preferita corrispondente. Qui dobbiamo determinare cosa l'utente vuole fare, favorire o sfavorire. Per questo è ansible introdurre un parametro di richiesta chiamato ad esempio type, che dovremo passare anche nel nostro helper link più tardi.

 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 

Dal tuo punto di vista puoi quindi aggiungere i rispettivi collegamenti alle ricette favorevoli e sfavorevoli.

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

Questo è tutto. Se un utente fa clic sul link "preferito" accanto a una ricetta, questa ricetta viene aggiunta ai preferiti di current_user.

Spero che ti sia d'aiuto, e per favore fai tutte le domande che ti piacciono.

Le guide di Rails sulle associazioni sono piuttosto comprensibili e ti aiuteranno molto quando inizi.

Grazie per la guida, Thomas! Funziona alla grande.

Volevo solo aggiungere che, affinché il tuo metodo preferito funzioni correttamente, devi racchiudere il testo tra virgolette anziché virgolette singole per far funzionare l’interpolazione della stringa.

 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

Questa discussione è stata super utile !!

Grazie!

Non dimenticare di includere il = nei tag del modulo.

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

La risposta selezionata è davvero buona, tuttavia non posso pubblicare un commento e ho davvero una domanda sopra. Come puoi limitare un utente ad avere una ricetta preferita? Con la risposta di cui sopra un utente può continuare a premere i preferiti e molte voci verranno create nel database …