如何覆盖 Grape API 响应负载中的根密钥?

How do I override the root key in a Grape API response payload?

module Entities
  class StuffEntity < Grape::Entity
    root 'stuffs', 'stuff'
    ...

如何通过重用该实体来干燥我的代码,同时仍然可以灵活地重命名实体中定义的根键('stuffs' 和 'stuff')?

在公开由现有实体表示的集合的子集或公开可由现有实体表示的关联集合的情况下,我可能需要执行此操作。

在公开关联对象或集合时隐藏根键

假设我有一个具有 name 属性的对象和一些 scoped_stuff 的集合,我想将其公开为 some_stuffs。我可以用这样的实体来做到这一点:

module Entities
  class CoolStuffEntity < Grape::Entity
    root 'cool_stuffs', 'cool_stuff'
    
    expose :some_stuffs, documentation: {
      type: Entities::StuffEntity
    } do |object, _options|
      Entities::StuffEntity.represent(
        object.class.scoped_stuff,
        root: false
      )
    end
    
    expose :name, documentation: { type: 'string' }
  end
end

root: false 传递给 represent 方法可确保嵌套关联在没有根键的情况下表示。以下是使用和不使用该参数时的表示形式:

# Without root: false
cool_stuff: {
  some_stuffs: { 
    stuffs:    [ /* collection represented by StuffEntity */ ] 
  },
  name: 'Something'
}

# With root: false
cool_stuff: { 
  some_stuffs: [ /* collection represented by StuffEntity */ ],
  name:        'Something'
}

在这种情况下,传递 root: false 可确保嵌套实体的根键不包含在我们的表示中。

在呈现没有定义根的实体时设置根键名称

假设我们有一个没有指定根的实体:

module Entities
  class StuffEntity < Grape::Entity
    expose :name, documentation: { type: 'string' }
  end
end

用此实体表示的对象的可序列化散列将如下所示:{ name: 'Object name' }

在我们的 API 中,我们可以像这样指定响应键:

get do
  stuff_object = Stuff.find_by(user_id: current_user)

  present stuff_object, 
    with: Entities::StuffEntity,
    root: :stuff
end

因此我们的响应将如下所示:{ stuff: { name: 'Object name' } }

注意 'root' 在这里接受字符串和符号参数。

如果您想在 API 响应中重命名根键

那么,如果我有一个实体,我在其中指定了一个根密钥 并且 我希望我的响应中的密钥不同(例如,公开集合的一个子集)?我可以再次使用 represent,而不是使用 present。除了这一次,我可以给它一个键名,而不是通过传递 'false' 来禁用根键:

get do
  my_stuff = Stuff.find_by(user_id: current_user)

  Entities::StuffEntity.represent(
    my_stuff,
    root: :my_stuff
  )
end