【问题标题】:how to use an instance of a model in another serializer如何在另一个序列化程序中使用模型的实例
【发布时间】:2021-09-05 02:59:55
【问题描述】:

我被困在这里,找不到继续工作的解决方案,

我有 3 个模型:计划、日期和膳食。

这是我的计划控制器我已经设法在控制器中得到正确的答案,我希望它嵌套在序列化程序中,因为我正在使用 URL 帮助程序来检索我的图像 URL,有没有可能的方法来使用@plan.id 在 DaySerializer 内?

  def meals
    @plan = Plan.find(params[:id])
    @days = @plan.days
    @meals = Meal.where("plan_id = ? ", @plan.id)
    render :json => { :plan => @plan, :days => @days,
                      :meals => @meals }
  end

这是我的计划模型

class Plan < ApplicationRecord
  has_many :days
  has_one_attached :image, dependent: :destroy
end

这是我的 Day 模型

class Day < ApplicationRecord
  has_many :meals
  has_many :plans
end

这是我的膳食模型

class Meal < ApplicationRecord
  belongs_to :plan
  belongs_to :day
  has_one_attached :image, dependent: :destroy
end

我想显示特定计划的所有膳食,为此我需要在 daySerializer 中使用一个变量,但我找不到如何操作。

这是我的planSerializer

class PlanSerializer < ActiveModel::Serializer
  attributes :id, :name, :monthly_price, :plan_days

  def plan_days
    object.days.map do |day|
      DaySerializer.new(day, scope: scope, root: false, event: object)
    end
  end
end

这是我的 DaySerializer,我需要使用里面的计划实例

class DaySerializer < ActiveModel::Serializer
  attributes :number, :plan_meals

  def plan_meals
    #how to be able to use this line in Serilizer? !important
    @plan = Plan.find(params[:id])
    object.meals.map do |meal|
      if meal.plan_id == @plan.id
        MealSerializer.new(meal, scope: scope, root: false, event: object)
      end
    end
  end
end

目标原因响应:

{
  id: 8,
  name: "Plan1",
  monthly_price: 88,
  plan_days: [
    {
      number: 5,
      plan_meals: [],
    },
    {
      number: 4,
      plan_meals: [],
    },
    {
      number: 3,
      plan_meals: [],
    },
    {
      number: 2,
      plan_meals: [],
    },
    {
      number: 1,
      plan_meals: [
        {
          id: 11,
          name: "test meal",
          calories: 32,
          protein: 32,
          fat: 32,
          carbohydrates: 32,
          plan_id: 8,
        },
      ],
    },
  ],
}

目前显示属于每一天的所有餐食,

不仅仅是与plan_id = Plan.find(params[:id])一起吃饭

【问题讨论】:

  • 自述文件可能是一个不错的起点。 github.com/rails-api/active_model_serializers/tree/…
  • 你的联想没有意义;是否有隐藏的 JOIN 表?你有Plan has_many :days AND Day has_many :plans??那么什么是外键呢?见:guides.rubyonrails.org/…
  • @TomLord 实际上是这样,并且没有连接表,例如我们有 2 个计划 A 和 B,计划 A 有 6 天,计划 B 有 10 天,这些天中的每一天都有 5膳食,所以要检查计划 1 膳食,我们执行 Plan.find(A).days.meals where foods.plan_id = Plan.find(A),事实上我可以使用控制器得到正确的答案 `def foods @plan = Plan .find(params[:id]) @days = @plan.days @meals = Meal.where("plan_id = ? ", @plan.id) 渲染 :json => { :plan => @plan, :days = > @days, :meals => @meals } 结束 `
  • @MohamedAmineAzaiez 这并没有解决我提出的问题。特别是,我们怎么会有Day has_many :plans?运行Day.last.plans 有意义吗?如果是这样,它是如何工作的?
  • @MohamedAmineAzaiez 第三次,我的问题是不是关于meals。我在谈论daysplans。我知道拥有多对多关联是有意义的,在这种情况下,这些关系应该是has_and_belongs_to_many(或has_many through: ...),而不仅仅是has_many。见:guides.rubyonrails.org/…

标签: ruby-on-rails json ruby serialization


【解决方案1】:

更新: 加餐序列化器怎么样?

class MealSerializer < ActiveModel::Serializer
  attributes :id, :name, :calories, :protein, :fat, # etc
end
class DaySerializer < ActiveModel::Serializer
  attributes :number
  has_many :meals, serializer: MealSerializer
end

原文:

class PlanSerializer < ActiveModel::Serializer
  attributes :id, :name, :monthly_price, :plan_days
  
  has_many :plan_days, serializer: DaySerializer
end

类似的东西。

【讨论】:

  • 感谢您的快速回答,但这不是问题,我只想显示具有 plan_id = @plan.id 的膳食,我需要 daySerializer 中的 plan_meals 方法的帮助
  • @MohamedAmineAzaiez 更新了我的答案。
  • 我已经有一个饭菜序列化器,问题仍然存在于当天序列化器内部我更新了我的问题,请再次检查,谢谢
【解决方案2】:

总的来说,我认为你可以使用这样的东西。

ActiveModel::Serializer::CollectionSerializer.new。它本身实际上允许您将附加信息传递给您的序列化程序。它的作用与您当前的代码相同,只是您能够显式传递新数据。

控制器:

  def meals
    @plan = Plan.find(params[:id])
    @days = @plan.days
    @meals = Meal.where("plan_id = ? ", @plan.id)
    render :json => { 
      :plan => @plan,
      :days => ActiveModel::Serializer::CollectionSerializer.new(@days, serializer: DaySerializer, plan_id: @plan.id),
      :meals => @meals
    }
  end

然后在DaySerializer:

class DaySerializer < ActiveModel::Serializer
  attributes :number, :plan_meals

  def plan_meals
    object.meals.map do |meal|
      if meal.plan_id == instance_options[:plan_id]
        MealSerializer.new(meal, scope: scope, root: false, event: object)
      end
    end
  end
end

简而言之,控制器中的ActiveModel::Serializer::CollectionSerializer.new 和序列化程序中的instance_options 可以访问传递的附加参数。

【讨论】:

    猜你喜欢
    • 2023-03-20
    • 2010-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-18
    • 2017-02-08
    • 1970-01-01
    • 2023-04-01
    相关资源
    最近更新 更多