Rails 5个具有嵌套多个属性的强参数

时间:2017-01-09 02:54:08

标签: ruby-on-rails angularjs activerecord ruby-on-rails-5 strong-parameters

我正在尝试保存一个包含配方和多种成分的对象。数据来自我的角度2应用程序,它将对象作为JSON传递。我的rails 5 api应用程序将接收配方对象并使用强参数将其直接保存到我的数据库。现在我可以将配方对象保存到数据库中,但由于某种原因,其中的成分未被保存。我检查了rails文档,我发现当前代码没有问题。任何想法都将不胜感激。

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)

2 个答案:

答案 0 :(得分:1)

在Rails 5中,每当我们定义belongs_to关联时,都需要在https://github.com/rails/rails/pull/18937 change之后默认存在关联记录。 如果显示@ recipe.errors.messages,您将找到

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

只需添加&#39;可选:true&#39;到成分模型中的belongs_to行。

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

答案 1 :(得分:0)

您的控制台日志显示参数包含密钥ingredients。对于嵌套属性,您必须使用ingredients_attributes。因此,请确保您的参数看起来像这样:

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

为什么我们不能在这里使用ingredients?好吧,这将导致以下代码在内部执行:

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

但是recipe.ingredients=是关系的属性writer,它只接受Ingredient个实例的数组。所以你必须像这样使用它:

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

在幕后,使用recipe.ingredients_attributes=实际上是从普通哈希转换为Ingredient的实例。