0

Я пытаюсь сохранить объект, в котором есть рецепт и несколько ингредиентов. Данные поступают из моего углового 2 приложения, которое передает объект как JSON. Приложение rails 5 api получит объект рецепта и сохранит его непосредственно в моей БД с использованием сильных параметров. Сейчас я могу сохранить объект рецепта в базе данных, но по какой-то причине ингредиенты внутри него не сохраняются. Я проверил документацию по рельсам, и я не нашел проблем с моим текущим кодом. Любые мысли были бы оценены.Рельсы 5 сильных параметров с вложенными множественными атрибутами

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 

мой журнал консоли

 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

Разве не о сильных параметрах? Вот хороший пост [как разрешить массив в сильных параметрах] (http://jaketrent.com/post/permit-array-rails-strong-parameters/) – matiss

+0

Я уже пробовал, он просто игнорирует ингредиенты внутри объекта рецепта. – Johji

ответ

1

В Rails 5, всякий раз, когда мы определяем ассоциацию belongs_to, необходимо, чтобы соответствующая запись присутствовала по умолчанию после этого https://github.com/rails/rails/pull/18937change. Если вы показываете @ recipe.errors.messages, вы найдете

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

Просто добавьте «необязательными: истинно» к вашей belong_to линии в модели ингредиента.

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

Извините, я не понимаю, что вы имели в виду. Я пытаюсь сохранить рецепт и ингредиент внутри него в моем контроллере рецептов. – Johji

+0

Он не будет сохранен, если у вас есть ошибка проверки. Тот факт, что Rails 5 требует, чтобы родительская ассоциация существовала до того, как вы сохранили запись, создаст ошибку проверки и не позволит вашему контроллеру работать. Если вы попробуете свой код в Rails 4, он будет работать, но не Rails 5. Используя опцию: true, вы разрешаете сохранять ребенка без наличия родительского идентификатора. – JamesAspinwall

0

Ваш журнал консоли показывает, что параметры включают ключ ingredients. Для вложенных атрибутов вместо этого вы должны использовать ingredients_attributes. Поэтому убедитесь, что ваш PARAMS выглядеть следующим образом:

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

Почему мы не можем просто использовать ingredients здесь? Ну, это привело бы в следующий код выполняется внутри:

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

Но recipe.ingredients= является атрибутом писатель отношения, и он принимает только массив Ingredient экземпляров. Таким образом, вы должны были бы использовать его как это:

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

Под капотом, используя recipe.ingredients_attributes= по существу делает это преобразование из простых хэшей в случаях Ingredient.