1

我正在使用'葡萄实体','〜> 0.7.1'

我有一个哈希格式:

temp_data = [{sheet_index: 0, other_names: []},{'sheet_index' => 1, 'other_names': ['a']}]

我有以下实体

 class Sheet < Grape::Entity
   expose :sheet_index, documentation: {type: Integer, desc: "Sheet index"}
   expose :other_names, documentation: {type: Array, desc: "Other names"}
 end

 class Sheets < Grape::Entity
  present_collection true

  expose :items, as: 'sheet_history', using Entities::Sheet
 end


# response from the entities
present temp_data, with: Entities::Sheets

现在我需要确保无论我的 Hash 中的键类型如何,它仍然应该为我提供上述情况的正确输出

expected_response = {"sheet_history" => [{"sheet_index"=>0, "other_names"=>[]}, {"sheet_index"=>1, "other_names"=>["a"]}]}

但我得到的响应格式如下

actual_response = {"sheet_history" => [{"sheet_index"=>0, "other_names"=>[]}, {"sheet_index"=>nil, "other_names"=>nil}]}

所以在实际响应sheet_indexother_names,第二个元素的值为 nil,因为它们的键是字符串,而不是符号。(请参阅temp_data。)

我已经参考了https://github.com/ruby-grape/grape-entity/pull/85来获得上述实现,但如果不使用 HashWithIndifferentAccess 或 OpenStructs 仍然无法使其工作

4

1 回答 1

0

您在 之后缺少一个冒号using,但我不会设置多个这样的实体,因为它可能会导致不稳定的行为。尝试这个:

# Dummy definition of your class
class Item
  include ActiveModel::Serialization

  attr_accessor :sheet_index
  attr_accessor :other_names

  def initialize(index, names)
    @sheet_index = index
    @other_names = names
  end
end
items = []
items << Item.new(0, [])
items << Item.new(1, ['a'])
=> [
  #<Item:0x00007f860f740e40 @other_names=[], @sheet_index=0>, 
  #<Item:0x00007f860f513618 @other_names=["a"], @sheet_index=1>
]
# Entity Definition
class Sheet < Grape::Entity
  # The first arg here is the key to use for a collection, 
  # the second is the key to use for a single object
  root 'sheet_history', 'sheet_history'

  expose :sheet_index, documentation: {
    type: Integer, 
    desc: "Sheet index" # Plz use locales
  }

  expose :other_names, documentation: {
    type: Array, 
    desc: "Other names" # Plz use locales
  }
end
# Test it
representation = Sheet.represent(items)
=> {
  "sheet_history"=>[
    #<Sheet:70106854276160 sheet_index=0 other_names=[]>, 
    #<Sheet:70106854275680 sheet_index=1 other_names=["a"]>
  ]
}
# This is just more a more readable, but as you can see it's 
# both mapping all the attributes correctly and 
# setting the root key that you wanted:
representation['sheet_history'].map do |r| r.serializable_hash end
=> [
  {
    :sheet_index=>0, 
    :other_names=>[]
  }, 
  {
    :sheet_index=>1, 
    :other_names=>["a"]
  }
]

# Endpoint
get do
  items = current_user.items # or whatever
  present items, with: Entities::Sheet
end

您可以将哈希数组发送到该represent方法,但它不喜欢字符串化的键。理想情况下,您应该将 DB 对象而不是哈希传递给您的实体,但是,如果由于某种原因不能,我会temp_data.map(&:symbolize_keys)作为您的参数传递给实体,以确保它解析的哈希中的顶级键是符号。

于 2020-09-04T07:36:39.170 回答