- 更新 - Rails API 应用程序使用来自控制器的 POST 请求一次创建不同模型的多个嵌套记录
- UPDATED - Rails API app create multiple nested records of a different models at once using POST request from the controller
我正在 API Ruby rails 6.1 应用程序上工作,所以我的所有回复都在 JSON 中。我正在尝试创建一个 3 级嵌套记录,这意味着我想创建一个计划记录,其中包含许多天的记录,其中包含每天的许多餐点。
Plan.rb
class Plan < ApplicationRecord
has_and_belongs_to_many :days
has_and_belongs_to_many :meals
has_one_attached :image, dependent: :destroy
accepts_nested_attributes_for :meals, reject_if: ->(object) { object[:name].blank? }
accepts_nested_attributes_for :days, reject_if: ->(object) { object[:number].blank? }
end
Day.rb
class Day < ApplicationRecord
has_and_belongs_to_many :plans
has_and_belongs_to_many :meals
validates_presence_of :number, on: [:create, :update], message: "can't be blank"
validates_uniqueness_of :number, on: [:create, :update], message: "You can't use same day number twice"
accepts_nested_attributes_for :meals, reject_if: ->(object) { object[:name].blank? }
end
Meal.rb
class Meal < ApplicationRecord
has_and_belongs_to_many :days
has_and_belongs_to_many :plans
end
我还添加了 2 个连接表
create_table "days_meals", id: false, force: :cascade do |t|
t.bigint "day_id", null: false
t.bigint "meal_id", null: false
end
create_table "days_plans", id: false, force: :cascade do |t|
t.bigint "day_id", null: false
t.bigint "plan_id", null: false
end
这是plans_controller.rb
中的UPDATED方法
# POST /create_custon_plan
def create_custon_plan
@plan = Plan.new(plan_params)
if @plan.save
render json: {
messages: "Plan was successfully created.",
is_success: true,
status: :created,
data: { plan: @plan, days_attributes: @plan.days, meals_attributes: @plan.meals },
}
else
render json: @plan.errors, status: :unprocessable_entity
end
end
这就是我允许我的参数的方式
def plan_params
params.require(:plan).permit(:name, :monthly_price, :image_url, days_attributes: [:number, meals_attributes: [:name, :calories, :protein, :fat, :carbohydrates, :categorie]])
end
这是我的 POST 请求正文 http://localhost:3000/api/create_custon_plan
{
"name": "Test Plan",
"monthly_price": 0,
"image_url": "55555",
"days_attributes": [
{
"number": 500,
"meals_attributes": [
{
"name": "azerazer Salad",
"calories": 55,
"protein": 55,
"fat": 55,
"carbohydrates": 55,
"image_url": "55555",
"categorie": "snack-1"
},
{
"name": "Fit Burger",
"calories": 55,
"protein": 55,
"fat": 55,
"carbohydrates": 55,
"image_url": "55555",
"categorie": "meal-1"
},
{
"name": "Vegan Rataouille",
"calories": 55,
"protein": 55,
"fat": 55,
"carbohydrates": 55,
"image_url": "55555",
"categorie": "snack-2"
},
{
"name": "Chicken BBQ",
"calories": 55,
"protein": 55,
"fat": 55,
"carbohydrates": 55,
"image_url": "55555",
"categorie": "meal-3"
}
]
},
{
"number": 502,
"meals_attributes":
[
{
"name": "Woldrof Salad",
"calories": 55,
"protein": 55,
"fat": 55,
"carbohydrates": 55,
"image_url": "55555",
"categorie": "snack-1"
},
{
"name": "Baked Beef",
"calories": 55,
"protein": 55,
"fat": 55,
"carbohydrates": 55,
"image_url": "55555",
"categorie": "meal-1"
}
]
}
]
}
到目前为止,嵌套日工作正常,但嵌套日内的嵌套膳食不知道如何解决?甚至终端内的日志也完全忽略它
您无需循环访问它们并单独创建它们。 Plan.new(plan_params)
应该可以完成工作,您只需正确指定嵌套属性即可。
变化:
days
到 day_attributes
- 不需要传递 ID。
例如:
{
"name": "Test Plan",
"monthly_price": 0,
"image_url": null,
"day_attributes": [
{
"number": 1,
"meal_attributes": [
{
"name": "Kale Salad",
"calories": null,
"protein": null,
"fat": null,
"carbohydrates": null,
"image_url": null,
"categorie": "snack-1"
},
{
"name": "Fit Burger",
"calories": null,
"protein": null,
"fat": null,
"carbohydrates": null,
"image_url": null,
"categorie": "meal-1"
},
{
"name": "Vegan Rataouille",
"calories": null,
"protein": null,
"fat": null,
"carbohydrates": null,
"image_url": null,
"categorie": "snack-2"
},
{
"name": "Chicken BBQ",
"calories": null,
"protein": null,
"fat": null,
"carbohydrates": null,
"image_url": null,
"categorie": "meal-3"
}
]
},
{
"number": 2,
"meal_attributes":
[
{
"name": "Woldrof Salad",
"calories": null,
"protein": null,
"fat": null,
"carbohydrates": null,
"image_url": null,
"categorie": "snack-1"
},
{
"name": "Baked Beef",
"calories": null,
"protein": null,
"fat": null,
"carbohydrates": null,
"image_url": null,
"categorie": "meal-1"
}
]
}
]
}
此外,您还应该在许可参数中适当提及它们,例如:
params.permit(:name, :monthly_price, :image_url, day_attributes: [:number, meal_attributes: [:name, :calories, :protein, :fat, :carbohydrates, :image_url, :categorie]])
更多信息可以参考:
我正在 API Ruby rails 6.1 应用程序上工作,所以我的所有回复都在 JSON 中。我正在尝试创建一个 3 级嵌套记录,这意味着我想创建一个计划记录,其中包含许多天的记录,其中包含每天的许多餐点。
Plan.rb
class Plan < ApplicationRecord
has_and_belongs_to_many :days
has_and_belongs_to_many :meals
has_one_attached :image, dependent: :destroy
accepts_nested_attributes_for :meals, reject_if: ->(object) { object[:name].blank? }
accepts_nested_attributes_for :days, reject_if: ->(object) { object[:number].blank? }
end
Day.rb
class Day < ApplicationRecord
has_and_belongs_to_many :plans
has_and_belongs_to_many :meals
validates_presence_of :number, on: [:create, :update], message: "can't be blank"
validates_uniqueness_of :number, on: [:create, :update], message: "You can't use same day number twice"
accepts_nested_attributes_for :meals, reject_if: ->(object) { object[:name].blank? }
end
Meal.rb
class Meal < ApplicationRecord
has_and_belongs_to_many :days
has_and_belongs_to_many :plans
end
我还添加了 2 个连接表
create_table "days_meals", id: false, force: :cascade do |t|
t.bigint "day_id", null: false
t.bigint "meal_id", null: false
end
create_table "days_plans", id: false, force: :cascade do |t|
t.bigint "day_id", null: false
t.bigint "plan_id", null: false
end
这是plans_controller.rb
中的UPDATED方法# POST /create_custon_plan
def create_custon_plan
@plan = Plan.new(plan_params)
if @plan.save
render json: {
messages: "Plan was successfully created.",
is_success: true,
status: :created,
data: { plan: @plan, days_attributes: @plan.days, meals_attributes: @plan.meals },
}
else
render json: @plan.errors, status: :unprocessable_entity
end
end
这就是我允许我的参数的方式
def plan_params
params.require(:plan).permit(:name, :monthly_price, :image_url, days_attributes: [:number, meals_attributes: [:name, :calories, :protein, :fat, :carbohydrates, :categorie]])
end
这是我的 POST 请求正文 http://localhost:3000/api/create_custon_plan
{
"name": "Test Plan",
"monthly_price": 0,
"image_url": "55555",
"days_attributes": [
{
"number": 500,
"meals_attributes": [
{
"name": "azerazer Salad",
"calories": 55,
"protein": 55,
"fat": 55,
"carbohydrates": 55,
"image_url": "55555",
"categorie": "snack-1"
},
{
"name": "Fit Burger",
"calories": 55,
"protein": 55,
"fat": 55,
"carbohydrates": 55,
"image_url": "55555",
"categorie": "meal-1"
},
{
"name": "Vegan Rataouille",
"calories": 55,
"protein": 55,
"fat": 55,
"carbohydrates": 55,
"image_url": "55555",
"categorie": "snack-2"
},
{
"name": "Chicken BBQ",
"calories": 55,
"protein": 55,
"fat": 55,
"carbohydrates": 55,
"image_url": "55555",
"categorie": "meal-3"
}
]
},
{
"number": 502,
"meals_attributes":
[
{
"name": "Woldrof Salad",
"calories": 55,
"protein": 55,
"fat": 55,
"carbohydrates": 55,
"image_url": "55555",
"categorie": "snack-1"
},
{
"name": "Baked Beef",
"calories": 55,
"protein": 55,
"fat": 55,
"carbohydrates": 55,
"image_url": "55555",
"categorie": "meal-1"
}
]
}
]
}
到目前为止,嵌套日工作正常,但嵌套日内的嵌套膳食不知道如何解决?甚至终端内的日志也完全忽略它
您无需循环访问它们并单独创建它们。 Plan.new(plan_params)
应该可以完成工作,您只需正确指定嵌套属性即可。
变化:
days
到day_attributes
- 不需要传递 ID。
例如:
{
"name": "Test Plan",
"monthly_price": 0,
"image_url": null,
"day_attributes": [
{
"number": 1,
"meal_attributes": [
{
"name": "Kale Salad",
"calories": null,
"protein": null,
"fat": null,
"carbohydrates": null,
"image_url": null,
"categorie": "snack-1"
},
{
"name": "Fit Burger",
"calories": null,
"protein": null,
"fat": null,
"carbohydrates": null,
"image_url": null,
"categorie": "meal-1"
},
{
"name": "Vegan Rataouille",
"calories": null,
"protein": null,
"fat": null,
"carbohydrates": null,
"image_url": null,
"categorie": "snack-2"
},
{
"name": "Chicken BBQ",
"calories": null,
"protein": null,
"fat": null,
"carbohydrates": null,
"image_url": null,
"categorie": "meal-3"
}
]
},
{
"number": 2,
"meal_attributes":
[
{
"name": "Woldrof Salad",
"calories": null,
"protein": null,
"fat": null,
"carbohydrates": null,
"image_url": null,
"categorie": "snack-1"
},
{
"name": "Baked Beef",
"calories": null,
"protein": null,
"fat": null,
"carbohydrates": null,
"image_url": null,
"categorie": "meal-1"
}
]
}
]
}
此外,您还应该在许可参数中适当提及它们,例如:
params.permit(:name, :monthly_price, :image_url, day_attributes: [:number, meal_attributes: [:name, :calories, :protein, :fat, :carbohydrates, :image_url, :categorie]])
更多信息可以参考: