Serializer JSONs com Sinatra
Leia em: 4 minutosSerializar objetos em JSONs nunca foi tão fácil depois que a gem ActiveModel::Serializers
passou a existir.
A gem facilita a manipulação dos objetos Ruby para objetos JSONs.
Com isso podemos dedicar um lugar para personalizar totalmente a saída desses objetos. Para cada objeto que queremos serializar devemos criar um arquivo que contenha uma classe que estenda de ActiveModel::Serializer
.
Imagine que o controller
receba um objeto com a seguinte estrutura:
#<Foo id: 1, foo: "foo", bar: "bar", baz: "baz">
Mas você eu não estou satisfeito em devolver todos atributos na resposta. Qual seria a solução para isto?
A solução é manipular este objeto usando uma classe serializer. Desejo que ele tenha apenas o atributo bar
. Para que isto seja possível dexei o serializer da seguinte maneira:
class FooSerializer < ActiveModel::Serializer
attributes :bar
end
Se estiver utilizando o framework Rails basta fazer um render
do tipo json
:
def show
render json: Foo.find(params[:id])
end
e teremos este retorno:
{
"foo": {
"bar": "bar"
}
}
Perfeito, tudo funcionou como desejavamos.
Conhecendo um pouco mais a Gem
Você deve ter achado esquisito (automatico) em fazer apenas um render
e ele trazer um objeto serializado sem precisar especificar nada de onde pegar.
Pois bem esta magia acontece dentro da gem
, como podemos ver aqui, ele intercepta todos os renders
do tipo json
, depois procura pelo serializer que tenha o mesmo nome do objeto e finaliza devolvendo a instância desta classe no formato JSON.
Genial, não?
Se sua resposta foi sim, concordo plenamente contigo. Mas pena que isto só funciona para o Rails.
Solução para o Sinatra
Meses atras passei por esta dificuldade. Precisei utilizar o ActiveModel::Serializers
em uma APP feita em Sinatra e tive problemas em deixar as resposta em JSONs
serializadas de forma automatica, como ocorre no Rails.
O problema é que no Sinatra não oferece suporte para a classe ActionController
, sendo assim a gem lança o seguinte erro cannot load such file -- action_controller (LoadError)
ao tentar carregar, mas este erro é tratado para que nossa aplicação não pare de funcionar.
Sendo assim que fazer esse trabalho manualmente, ficando da seguinte forma:
get '/foo/:id' do
foo = Foo.find(params[:id])
json FooSerializer.new(foo).to_json
end
Não podemos dizer que isto não seja uma solução válida, mas se você achou que da pra melhorar, eu concordo contigo.
Vendo essa necessidade, criei esta gem sinatra-active-model-serializers
para deixar tudo isso automatico no Sinatra também, assim como é no Rails.
E o resultado disto ficou:
get '/foo/:id' do
json Foo.find(params[:id])
end
Para que estas adaptações funcione como no exemplo acima você deverá instalar a gem: gem install sinatra-active-model-serializers
ou adicionar em seu Gemfile: gem 'sinatra-active-model-serializers'
.
Essa gem
basicamente aplica toda a lógica de controller feita para o Rails no módulo JSON
do Sinatra com algumas opções caso queira personalizar mais ainda suas respostas.
Maiores detalhes você encontrará aqui nas espeficicações da gem.
Comentários:
Deixe sua dúvida, sugestão ou crítica, estou ansioso para saber tudo o que você achou sobre este post: