I am in charge of the back end of the system currently under development, and implemented something like "returning some API responses in form format". I thought that the design used at this time was versatile, so I decided to write an article.
The essential meaning is different, but depending on the point of view, I think it looks like an adapter in the design pattern. I'm not sure if it's correct. ..
The language is ruby and the framework is rails.
column | Mold |
---|---|
id | int8 |
first | varchar(255) |
second | varchar(255) |
Suppose you have a table like the one above and you want to return one record in the JSON response format below.
{
"form_items" : [
{
"item_name" : "first",
"value" : "hoge" #value in first column
},
{
"item_name" : "second",
"value" : "fuga" #second column value
}
]
}
In the actual system, not only item_name and value but also metadata etc. are included and it has a complicated structure, but this time it is a simple design for convenience. Assuming that the number of columns will increase in the future and the elements of the array of form_items will be proportional to each column.
We have prepared 5 classes.
The third is the class that defines the Field. I am creating a FieldBase class as an abstract class.
At first glance you may be wondering why you designed it this way, but given the increased amount of columns and metadata that accompanies them, I thought it was safe.
class FirstField < FieldBase
COLUMN_NAME = 'first'
end
class SecondField < FieldBase
COLUMN_NAME = 'second'
end
class Base
def initialize(record)
@record = record
end
def value
@record.send(self.class::COLUMN_NAME)
end
end
The 4th and 5th will be explained as a set
First, the FormItem class is created to hold a set of item_name and value as an instance. Specifically, you can see it by looking at the fifth class.
class FormItem
attr_reader :item_name, :value
def initialize(field_instance)
@item_name = field_instance.class::COLUMN_NAME
@value = field_instance.value
end
end
The fifth is a class that creates an array of form_item
class FormItemList
attr_reader :form_items
def initialize(record)
@form_items = []
#Below form_The order of items is directly linked to the order of forms sent as a response
form_item(FirstField.new(record))
form_item(SecondField.new(record))
end
private
def form_item(field_instance)
@form_items += [FormItem.new(field_instance)]
end
end
After that, if you call it with controller as follows, you can get an array whose elements are objects made into form format.
record = Test.first
form_items = FormItemList.new(record).form_items
pp form_items
# => [FormItem instance created from FirstField instance, FormItem instance created from FirstField instance]
At this point, just serialize the objects in the array to json.
There are various serialize methods, so I won't explain them.
I don't think I'm getting much benefit from a small number of columns or metadata, but I think it's good that it's easier to customize as it grows!
I recently started Twitter, so please follow me!
Recommended Posts