I am using ROAR to implement an API for a rails application. This application deals with tickets that can have attributes like a subject and a description, but also have user defined attributes. For simplicity lets assume a ticket looks like:
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
The desired JSON output for such a ticket looks as follows:
{
"subject": "Foo",
"description": "Bar",
"customField1": "high",
"customField2": "Ubuntu"
}
Now you might already see the problem. All properties are immediate children of the root object, this means I can't write that up as representer:
class TicketRepresenter
property :subject
property :description
# Need to iterate over instance members on the class level here...
end
Is there some mechanic that ROAR offers to accomplish that? E.g. a callback that is executed in the context of an actual instance, e.g.
def call_me_on_write
represented.custom_attributes.each do |attribute|
add_property('customField1', attribute[1])
end
end
Is there something like this in ROAR that I have overlooked to accomplish this?
I looked in both the docs for ROAR and the docs for representable, but could not find anything.
Disclaimer
I tried to simplify the actual circumstances to make the question more readable. If you think that important information are missing, please tell me. I will thankfully provide more details.
Out of scope
Please do not discuss whether the chosen JSON format is a good/bad idea, I want to evaluate whether ROAR would support it.
I ended up dynamically creating classes from my basic representer:
Basically that means the actual representer class used to create the JSON is a different one for each
Ticket
.If you wanted to read a
Ticket
back from JSON, it is neccessary to correctly initialize the representer so that the created representer class knows about your custom fields and also define setters.You will now need to conventionally call the new
create
method instead ofnew
. If you need your representer to be created by ROAR (e.g. for a collection), you can use the Polymorphic Object Creation mechanism of ROAR.Note: The code above does not exactly fit the example of custom attributes posted in my question, but you should get the idea (in the example an attribute did not have members like
id
andvalue
, but was list consisting of key and value).