0

J'ai une table d'ingrédients. Lorsqu'un utilisateur entre un ingrédient, il enregistre dans le tableau. Maintenant, ce que je remarque, c'est que de nombreux enregistrements se répètent, et je ne le veux pas, ce que je veux c'est que chacun de ces enregistrements soit référencé s'il existe déjà. Par exemple, j'ai de la farine sauvée environ 20 fois dans la base de données (DB). Je veux qu'il soit sauvegardé une fois, et pour chaque recette, quand un utilisateur entre de la farine, il devrait simplement faire référence à cet ingrédient dans la base de données. Comment puis-je y parvenir?Comment stocker un enregistrement une fois et le référencer plusieurs fois dans d'autres tables?

J'ai déjà un modèle d'entrée (recette), et un modèle EntryIngredient de jointure. Donc, chaque fois qu'une entrée enregistre un ingrédient qui existe déjà, je veux qu'il se réfère simplement à celui de la table EntryIngredient (en tant que clé étrangère) au lieu d'en créer un nouveau.

class Ingredient < ActiveRecord::Base 
    has_many :entry_ingredients 
    has_many :entries, :through => :entry_ingredients 

end 

class EntryIngredient < ActiveRecord::Base 
    belongs_to :entry 
    belongs_to :ingredient 

    accepts_nested_attributes_for :ingredient, :reject_if => lambda { |a| a[:name].blank? }, :allow_destroy => true 

end 

class Entry < ActiveRecord::Base 
    belongs_to :user 
    has_many :entry_ingredients 
    has_many :ingredients, :through => :entry_ingredients 
    has_many :steps 

    accepts_nested_attributes_for :entry_ingredients, :allow_destroy => true 
    accepts_nested_attributes_for :steps, :reject_if => lambda { |s| s[:description].blank? }, :allow_destroy => true 

end 

MISE À JOUR:

trouveurs dynamiques sonores comme ils le font ce que je veux, en particulier find_or_create ou first_or_create mais je ne suis pas en mesure de comprendre comment les utiliser dans ma configuration. Quelqu'un peut-il me pousser dans la bonne direction ici? Voilà ce que j'ai essayé, mais je me rends compte que cela est tout simplement de créer un nouvel ingrédient à chaque fois que les entrées # nouvelles est appelé ... pas ce que je veux arriver

#entries_controller.rb 
    def new 
    @entry = Entry.new 
    @entry.entry_ingredients.build.build_ingredient 
    @entry.steps.build 

    @ingredient = Ingredient.where(params[:ingredient]).first_or_create() 

    respond_to do |format| 
     format.html # new.html.erb 
     format.xml { render :xml => @entry } 
    end 
    end 

#_entry_ingredient_fields.html.erb 
<%= f.fields_for :ingredient do |builder| %> 
    <%= builder.label :name %> 
    <%= builder.text_field :name, :class => "ingredient_field" %> 
<% end %> 
+0

Examinez une solution de saisie semi-automatique lors de l'ajout d'ingrédients. ajouter également une validation de l'unicité au nom des ingrédients pour au moins éviter la duplication basée sur les noms. – jvnill

+0

mais si j'ajoute la validation de l'unicité, un utilisateur obtiendrait une erreur lors de la sauvegarde d'un ingrédient qui existe déjà ... peut-être que je suis supposé en utiliser un au lieu d'en avoir plusieurs? Je vais poster mes modèles maintenant. – GiH

+1

avec une solution de saisie semi-automatique en place, vous n'avez pas à vous soucier d'échouer à la validation de l'unicité. c'est juste là, donc vous n'aurez pas de doublons dans le db. si elle existe déjà dans la base de données, la fonctionnalité de saisie semi-automatique doit être utilisée. Si ce n'est pas le cas, un champ de texte libre peut être ajouté pour créer un nouvel ingrédient. – jvnill

Répondre

1

Il est difficile de savoir exactement ce que vous avez besoin sans voir du code, mais si je comprends bien, vous voulez créer un ingrédient seulement s'il n'existe pas encore.

Vérifiez les rails 'dynamic finders. Si vous utilisez un nom de méthode comme

@ingredient = Ingredient.find_or_create_by_name("flour") 

, il crée un nouvel objet s'il n'y avait pas d'entrée avec le nom de « farine » avant ou retourner un ingrédient existant appelé « farine ». Dans les deux cas, @ingredient contiendra l'entrée désirée renvoyée par l'instruction ci-dessus. Rails le créera pour vous seulement s'il n'existe pas encore.

+0

alors comment l'utiliser avec des données de la vue? Les utilisateurs passeront dans l'argument, params [: nom]? – GiH

+0

C'est vrai. Passez simplement ce que vous voulez comme nom d'ingrédient. Vérifiez votre hachage params pour obtenir la clé exacte, mais ce sera quelque chose comme 'params [: nom]' ou plutôt 'params [: ingrédient] [: nom]'. – weltschmerz

+0

@GiH Est-ce que ça a marché pour vous? Le problème persiste-t-il? – weltschmerz

Questions connexes