How to move nested hash up one level in a 2-level deep association with ActiveModel::Serializer?

huangapple go评论173阅读模式
英文:

(Ruby on Rails active_model_serializers) How to move nested hash up one level in a 2-level deep association with ActiveModel::Serializer?

问题

在Ruby on Rails中,我有以下的ActiveRecord关联关系:

  1. class Driver
  2. has_one :car
  3. delegate :tires, to: :car
  4. end
  5. class Car
  6. belongs_to :driver
  7. has_many :tires
  8. end
  9. class Tire
  10. belongs_to :car
  11. end

我有以下的序列化器:

  1. class DriverSerializer < ActiveModel::Serializer
  2. attributes :id, :name
  3. has_one :car
  4. class CarSerializer < ActiveModel::Serializer
  5. attributes :id
  6. has_many :tires
  7. class TireSerializer < ActiveModel::Serializer
  8. attributes :id
  9. end
  10. end
  11. end

生成的JSON如下所示:

  1. {
  2. "id": 1,
  3. "name": "Bob",
  4. "car": {
  5. "id": 1,
  6. "tires": [
  7. {
  8. "id": 1
  9. },
  10. {
  11. "id": 2
  12. }
  13. // 其他数据
  14. ]
  15. }
  16. }

但我希望将tires移到上一级,直接嵌套在driver下面。我想要利用现有的序列化器,而不使用Ruby的map方法。我知道可以这样做:

  1. class DriverSerializer < ActiveModel::Serializer
  2. attribute :tires
  3. def tires
  4. object.tires.map{|t| TireSerializer.new(t)}
  5. end
  6. end

但是否有一种更简单的方法将哈希表移到上一级?

英文:

I have the following ActiveRecord associations in Ruby on Rails:

  1. class Driver
  2. has_one :car
  3. delegate :tires, to: :car
  4. end
  1. class Car
  2. belongs_to :driver
  3. has_many :tires
  4. end
  1. class Tire
  2. belongs_to :car
  3. end

I have the following Serializer:

  1. class DriverSerializer < ActiveModel::Serializer
  2. attributes :id, :name
  3. has_one :car
  4. class CarSerializer < ActiveModel::Serializer
  5. attributes :id
  6. has_many :tires
  7. class TireSerializer < ActiveModel::Serializer
  8. attributes :id
  9. end
  10. end
  11. end

The resulting JSON looks like this:

  1. {
  2. "id": 1,
  3. "name": "Bob",
  4. "car": {
  5. "id": 1,
  6. "tires": [
  7. {
  8. "id": 1
  9. },
  10. {
  11. "id": 2
  12. }
  13. ...
  14. ]
  15. }
  16. }

But I want the tires to move up one level so that they're nested directly under driver. I want to leverage the serializers as-is, without using Ruby's map method. I know I can do this:

  1. class DriverSerializer < ActiveModel::Serializer
  2. attribute :tires
  3. def tires
  4. object.tires.map{|t| TireSerializer.new(t)}
  5. end
  6. end

But is there a simpler way to just move the hash up one level?

答案1

得分: 3

我认为在您的 Driver 模型中,对于 tires 属性,最好使用 has_one :tires, through: :car 关联,而不是将其委托给 :car。然后,您可以在 DriverSerializer 中为此属性使用 has_many 选项,并使用 TireSerializer 作为其序列化器。

  1. class Driver
  2. has_one :car
  3. has_many :tires, through: :car
  4. end

以及在您的 Driver 序列化器中:

  1. class DriverSerializer < ActiveModel::Serializer
  2. has_many :tires, serializer: TireSerializer
  3. end

参考链接

英文:

I think it's better to use has_one :tires, through: :car association for the tires attribute in you Driver model instead of delegating it to :car. You can then use the has_many option in your DriverSerializer for this attribute and use TireSerializer for its serializer.

  1. class Driver
  2. has_one :car
  3. has_many :tires, through: :car
  4. end

and in your Driver serializer

  1. class DriverSerializer &lt; ActiveModel::Serializer
  2. has_many :tires, serializer: TireSerializer
  3. end

huangapple
  • 本文由 发表于 2023年5月29日 19:17:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/76356871.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定