2015-02-12 2 views
2

Я использую ROAR для реализации API для приложения rails. Это приложение имеет дело с билетами, которые могут иметь такие атрибуты, как тема и описание, но также имеют определенные пользователем атрибуты. Для простоты предположит, билет выглядит следующим образом:Как динамически добавлять свойства репозитарию ROAR?

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 и документы для representable, но ничего не смог найти.

Отказ

Я попытался упростить фактические обстоятельства, чтобы сделать этот вопрос более читаемым. Если вы считаете, что важная информация отсутствует, сообщите мне. Я с благодарностью расскажу подробнее.

Из объема

Пожалуйста, не обсуждайте выбранный формат JSON, является ли хороший/плохой идеей, я хочу, чтобы оценить, будет ли ROAR поддерживать его.

ответ

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 Polymorphic Object Creation.

Примечание: Код выше точно не соответствует примеру пользовательских атрибутов, размещенных в моем вопросе, но вы должны получить представление (в данном примере атрибут не имеют членов, как id и value, но список, состоящий ключа и стоимости).

Смежные вопросы