0

Ich versuche ein Objekt zu speichern, das ein Rezept und mehrere Zutaten enthält. Die Daten stammen von meiner App angular 2, die das Objekt als JSON übergibt. Meine Anwendung rails 5 api erhält das Rezeptobjekt und speichert es mit den starken Parametern direkt in meiner Datenbank. Momentan kann ich das Rezeptobjekt in der Datenbank speichern, aber aus irgendeinem Grund werden die Zutaten nicht gespeichert. Ich habe die Rails-Dokumentation überprüft und festgestellt, dass mein aktueller Code kein Problem darstellt. Irgendwelche Gedanken würden geschätzt werden.Rails 5 starke Parameter mit geschachtelten multiplen Attributen

recipe.rb

class Recipe < ApplicationRecord 
has_many :ingredients 
accepts_nested_attributes_for :ingredients 
end 

ingredient.rb

class Ingredient < ApplicationRecord 
belongs_to :recipe 
end 

recipe_controller.rb

def create 
    @recipe = Recipe.new(recipe_params) 
    if @recipe.save                                     
    render json: @recipe, status: :created, location: @recipe 
    else 
    render json: @recipe.errors, status: :unprocessable_entity 
    end 
end 

def recipe_params 
    params.require(:recipe).permit(:name , :description, :imagePath, ingredients_attributes: [ :id, :name, :amount]) 
end 

meine Konsolenprotokoll

 Started POST "/recipes" for ::1 at 2017-01-09 11:40:44 +0900 
     ActiveRecord::SchemaMigrationLoad(0.3ms)SELECT`schema_migrations`.* FROM `schema_migrations` 

     Processing by RecipesController#create as HTML Parameters: {"name"=>"Spaghetti", "imagePath"=>"http://cdn2.tmbi.com/TOH/Images/Photos/37/300x300/exps36749_SD143203D10__25_1b.jpg", "description"=>"Delicious spaghetti", "ingredients"=>[{"name"=>"Tomato", "amount"=>1}, {"name"=>"Pasta", "amount"=>1}], "recipe"=>{"name"=>"Spaghetti", "description"=>"Delicious spaghetti", "imagePath"=>"http://cdn2.tmbi.com/TOH/Images/Photos/37/300x300/exps36749_SD143203D10__25_1b.jpg"}} 


    (0.1ms) BEGIN 
     SQL (0.2ms) INSERT INTO `recipes` (`name`, `description`, `imagePath`, `created_at`, `updated_at`) VALUES ('Spaghetti', 'Delicious spaghetti', 'http://cdn2.tmbi.com/TOH/Images/Photos/37/300x300/exps36749_SD143203D10__25_1b.jpg', '2017-01-09 02:40:44', '2017-01-09 02:40:44') 
    (0.7ms) COMMIT 
    Completed 201 Created in 9ms (Views: 1.0ms | ActiveRecord: 2.1ms) 
+0

Geht es nicht um starke params? Hier ist ein guter Beitrag [wie Array in starken Params erlauben] (http://jaketrent.com/post/permit-array-rails-strong-parameters/) – matiss

+0

Ich habe es schon versucht, es ignoriert nur die Zutaten in der Rezept-Objekt. – Johji

Antwort

1

Wenn wir in Rails 5 eine assignes_to-Assoziation definieren, muss der zugehörige Datensatz standardmäßig nach diesem https://github.com/rails/rails/pull/18937change vorhanden sein. ': True optional', um Ihre BELONG_TO Linie in der Zutaten Modell Wenn Sie die @ recipe.errors.messages angezeigt werden, werden Sie

{:"ingredient.recipe"=>["must exist"]} 

Fügen Sie einfach finden.

class Ingredient < ApplicationRecord 
belongs_to :recipe, optional: true 
end 
+0

Entschuldigung, ich verstehe nicht, was du damit meintest. Ich versuche, das Rezept und die Zutat darin in meinem Rezept-Controller zu speichern. – Johji

+0

Es wird nicht gespeichert, wenn Sie einen Validierungsfehler haben. Die Tatsache, dass Rails 5 erfordert, dass die übergeordnete Zuordnung vorhanden ist, bevor Sie den Datensatz speichern können, generiert den Überprüfungsfehler und lässt Ihren Controller nicht arbeiten. Wenn Sie Ihren Code in Rails 4 versuchen, wird es funktionieren, aber nicht Rails 5. Wenn Sie optional: true verwenden, können Sie das Kind speichern, ohne dass bereits eine Eltern-ID festgelegt wurde. – JamesAspinwall

0

Ihr Konsolenprotokoll zeigt, dass die Parameter den Schlüssel ingredients enthalten. Für verschachtelte Attribute müssen Sie stattdessen ingredients_attributes verwenden. So stellen Sie sicher, dass Ihre params wie folgt aussehen:

{ 
    "name" => "Spaghetti", 
    "description" => "Delicious spaghetti", 
    "ingredient_attributes" => [ 
    {"name" => "Tomato", "amount" => 1}, 
    {"name" => "Pasta", "amount" => 1} 
    ] 
} 

Warum können wir nicht einfach ingredients hier benutzen? Nun, dies würde dazu führen, in dem folgenden Code intern ausgeführt wird:

recipe.ingredients = [{"name" => "Tomato", … }] 

Aber recipe.ingredients= ist das Attribut Verfasser der Beziehung, und es nimmt nur eine Reihe von Ingredient Instanzen. So würden Sie es wie folgt verwenden müssen:

recipe.ingredients = [Ingredient.new("name" => "tomato", …)] 

Unter der Haube mit recipe.ingredients_attributes= im Wesentlichen erledigt diese Umwandlung von einfachen Hashes in Fällen von Ingredient.

Verwandte Themen