3

我正在使用 ROAR 为 Rails 应用程序实现 API。此应用程序处理可以具有主题描述等属性的票证,但也具有用户定义的属性。为简单起见,我们假设一张票看起来像:

class Ticket
  attr_accessor :subject, :description

  def custom_attributes
    # in reality these attributes depend on the current ticket instance
    # they are not hard-coded into the class
    [['priority', 'high'], ['Operating System', 'Ubuntu']]
  end
end

此类票证所需的 JSON 输出如下所示:

{
  "subject": "Foo",
  "description": "Bar",
  "customField1": "high",
  "customField2": "Ubuntu"
}

现在您可能已经看到了问题所在。所有属性都是根对象的直接子对象,这意味着我不能将其写为代表:

class TicketRepresenter
  property :subject
  property :description

  # Need to iterate over instance members on the class level here...
end

ROAR 是否提供了一些机制来实现这一目标?例如,在实际实例的上下文中执行的回调,例如

def call_me_on_write
  represented.custom_attributes.each do |attribute|
    add_property('customField1', attribute[1])
  end
end

在 ROAR 中是否有类似的东西我忽略了实现这一点?

我查看了ROAR的文档和可表示的文档,但找不到任何东西。

免责声明

我试图简化实际情况以使问题更具可读性。如果您认为缺少重要信息,请告诉我。谢天谢地,我会提供更多细节。

超出范围

请不要讨论选择的 JSON 格式是好还是坏,我想评估 ROAR 是否支持它。

4

2 回答 2

1

我相信解决这个问题的最佳方法是使用 Roar 的writer:. 它通过将少数调用选项的值传递给提供的 lambda 来完全控制输出。

例如:

property :desired_property_name, writer: -> (represented:, doc:, **) do
  doc[:desired_key] = represented.desired_value
end

github 自述文件未涵盖许多用途,但 Trailblazer 网站上记录了这些用途。这一个特别是可以在http://trailblazer.to/gems/representable/3.0/function-api.html#writer找到。

干杯!

于 2018-04-10T15:44:58.663 回答
0

我最终从我的基本代表动态创建类:

class TicketRepresenter
  property :subject
  property :description

  def self.create(ticket, context = {})
    klass = Class.new(TicketRepresenter) # create a subclass of my representer
    ticket.custom_attributes.each do |attribute|
      # for each custom attribute in the actual instance insert a property into the created class
      property "customField#{attribute.id}".to_sym
               getter: -> (*) { attribute.value }
    end

    # return an instance of the class created above
    klass.new(ticket, context)
  end
end

基本上,这意味着用于创建 JSON 的实际表示器类对于每个Ticket.

如果您想Ticket从 JSON 中读取回信息,则必须正确初始化表示器,以便创建的表示器类知道您的自定义字段并定义设置器。

您现在需要按惯例调用新create方法而不是new. 如果您需要通过 ROAR 创建您的表示器(例如,对于一个集合),您可以使用 ROAR 的多态对象创建机制。

注意:上面的代码不完全适合我的问题中发布的自定义属性的示例,但您应该明白(在示例中,属性没有像idand之类的成员value,而是由键和值组成的列表)。

于 2015-02-13T12:47:49.433 回答