{"action":"created","comment":{"url":"https://api.github.com/repos/moip/blog-devs/pulls/comments/38934490","id":38934490,"diff_hunk":"@@ -0,0 +1,70 @@\n+---\n+layout: post\n+title: \"Utilizando componentes do ActiveModel fora do Rails\"\n+author: carlos\n+category:\n+- Ruby\n+permalink: componentes-active-model-fora-do-rails\n+meta_description: \"Utilizando componentes do ActiveModel fora do Rails\"\n+browser_title: \"Utilizando componentes do ActiveModel fora do Rails\"\n+---\n+\n+Aqui no Moip temos o hábito de escrever apps ruby puras sem qualquer framework como o Rails, Sinatra ou Grape, às vezes por que não temos necessidade das funcionalidades destes frameworks e outras só por que é divertido mesmo :stuck_out_tongue:\n+\n+Num destes projetos, um web worker responsável por gerar relatórios, houve a necessidade de serializarmos hashes retornados por buscas do Elasticsearch em hashes no formato das linhas de um relatório específico. Para solucionar esse problema optamos por utilizar o <a href=\"https://github.com/rails-api/active_model_serializers\" target=\"_blank\">ActiveModel::Serializer</a> o único porém é que nosso app não utiliza Rails então a dúvida era como integrar este componente sem o uso do Rails...\n+\n+Para quem não conhece o ActiveModel::Serializer é uma gem responsável por realizar serialização de objetos em JSON de forma simples e altamente customizável. Geralmente é utilizado em app's Rails ou Rails API, porém nada nos impede de utilizá-lo em app's que não façam uso do Rails sendo que sua integração em uma app não Rails é bem simples de ser feita e neste post darei um breve exemplo de como consegui-lo :smiley:\n+\n+Primeiro, basta adicionar estas gem's ao seu GEMFILE:\n+\n+{% highlight ruby linenos %}\n+gem 'activesupport'\n+gem 'active_model_serializers'\n+{% endhighlight %}\n+\n+Para o exemplo usaremos um model chamado Pessoa, com os seguintes atributos:\n+\n+{% highlight ruby linenos %}\n+class Pessoa\n+  # Torna esse model serializável pelo ActiveModel::Serialization\n+  include ActiveModel::Serialization\n+\n+  attr_accessor :idade, :altura, :peso\n+\n+  # Retorna qual classe é responsável por serializar este model\n+  def active_model_serializer\n+    PessoaSerializer\n+  end\n+end\n+{% endhighlight %}\n+\n+Por fim devemos criar um serializer para este model na mão mesmo:\n+\n+{% highlight ruby linenos %}\n+class PessoaSerializer < ActiveModel::Serializer\n+  attributes :idade, :altura, :peso, :imc\n+\n+  def imc\n+    altura_em_metros = object.altura.to_f / 100\n+    imc = object.peso.to_f / (altura_em_metros * altura_em_metros)\n+    imc.round 2\n+  end\n+end\n+{% endhighlight %}\n+\n+No exemplo acima, através do método attributes realizamos um mapeamento um-para-um, ou seja, o serializer irá procurar por um atributo altura, por exemplo, no model serializado e irá criar um nó com este mesmo nome. Também é possível criar nós customizados, com nomes ou valores que não existem no model serializado, o método imc ilustra esta possibilidade.\n+\n+Feito isso serializar objetos da classe Pessoa é bem simples:","path":"_posts/2015-08-22-componentes-active-model-fora-do-rails.md","position":57,"original_position":57,"commit_id":"5172bff22d15c47eb937a2fe3b60c6b694e6fc6f","original_commit_id":"5172bff22d15c47eb937a2fe3b60c6b694e6fc6f","user":{"login":"caueferreira","id":4876851,"avatar_url":"https://avatars.githubusercontent.com/u/4876851?v=3","gravatar_id":"","url":"https://api.github.com/users/caueferreira","html_url":"https://github.com/caueferreira","followers_url":"https://api.github.com/users/caueferreira/followers","following_url":"https://api.github.com/users/caueferreira/following{/other_user}","gists_url":"https://api.github.com/users/caueferreira/gists{/gist_id}","starred_url":"https://api.github.com/users/caueferreira/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/caueferreira/subscriptions","organizations_url":"https://api.github.com/users/caueferreira/orgs","repos_url":"https://api.github.com/users/caueferreira/repos","events_url":"https://api.github.com/users/caueferreira/events{/privacy}","received_events_url":"https://api.github.com/users/caueferreira/received_events","type":"User","site_admin":false},"body":"Feito isso, serializar (...)\r\nacho que tem uma virgula","created_at":"2015-09-08T14:49:41Z","updated_at":"2015-09-08T14:49:41Z","html_url":"https://github.com/moip/blog-devs/pull/1#discussion_r38934490","pull_request_url":"https://api.github.com/repos/moip/blog-devs/pulls/1","_links":{"self":{"href":"https://api.github.com/repos/moip/blog-devs/pulls/comments/38934490"},"html":{"href":"https://github.com/moip/blog-devs/pull/1#discussion_r38934490"},"pull_request":{"href":"https://api.github.com/repos/moip/blog-devs/pulls/1"}}},"pull_request":{"url":"https://api.github.com/repos/moip/blog-devs/pulls/1","id":43069830,"html_url":"https://github.com/moip/blog-devs/pull/1","diff_url":"https://github.com/moip/blog-devs/pull/1.diff","patch_url":"https://github.com/moip/blog-devs/pull/1.patch","issue_url":"https://api.github.com/repos/moip/blog-devs/issues/1","number":1,"state":"open","locked":false,"title":"Componentes do Active Model fora do rails","user":{"login":"carlosmenezes","id":695118,"avatar_url":"https://avatars.githubusercontent.com/u/695118?v=3","gravatar_id":"","url":"https://api.github.com/users/carlosmenezes","html_url":"https://github.com/carlosmenezes","followers_url":"https://api.github.com/users/carlosmenezes/followers","following_url":"https://api.github.com/users/carlosmenezes/following{/other_user}","gists_url":"https://api.github.com/users/carlosmenezes/gists{/gist_id}","starred_url":"https://api.github.com/users/carlosmenezes/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/carlosmenezes/subscriptions","organizations_url":"https://api.github.com/users/carlosmenezes/orgs","repos_url":"https://api.github.com/users/carlosmenezes/repos","events_url":"https://api.github.com/users/carlosmenezes/events{/privacy}","received_events_url":"https://api.github.com/users/carlosmenezes/received_events","type":"User","site_admin":false},"body":"Este post mostra como utilizar componentes do ActiveModel em aplicações não Rails + suporte à autores nos posts...","created_at":"2015-08-21T19:00:27Z","updated_at":"2015-09-08T14:49:41Z","closed_at":null,"merged_at":null,"merge_commit_sha":"04875d34467acb8c9fa40e1b563b17a977787cb5","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/moip/blog-devs/pulls/1/commits","review_comments_url":"https://api.github.com/repos/moip/blog-devs/pulls/1/comments","review_comment_url":"https://api.github.com/repos/moip/blog-devs/pulls/comments{/number}","comments_url":"https://api.github.com/repos/moip/blog-devs/issues/1/comments","statuses_url":"https://api.github.com/repos/moip/blog-devs/statuses/5172bff22d15c47eb937a2fe3b60c6b694e6fc6f","head":{"label":"moip:post-active-model-components-outside-rails","ref":"post-active-model-components-outside-rails","sha":"5172bff22d15c47eb937a2fe3b60c6b694e6fc6f","user":{"login":"moip","id":5281980,"avatar_url":"https://avatars.githubusercontent.com/u/5281980?v=3","gravatar_id":"","url":"https://api.github.com/users/moip","html_url":"https://github.com/moip","followers_url":"https://api.github.com/users/moip/followers","following_url":"https://api.github.com/users/moip/following{/other_user}","gists_url":"https://api.github.com/users/moip/gists{/gist_id}","starred_url":"https://api.github.com/users/moip/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/moip/subscriptions","organizations_url":"https://api.github.com/users/moip/orgs","repos_url":"https://api.github.com/users/moip/repos","events_url":"https://api.github.com/users/moip/events{/privacy}","received_events_url":"https://api.github.com/users/moip/received_events","type":"Organization","site_admin":false},"repo":{"id":39251454,"name":"blog-devs","full_name":"moip/blog-devs","owner":{"login":"moip","id":5281980,"avatar_url":"https://avatars.githubusercontent.com/u/5281980?v=3","gravatar_id":"","url":"https://api.github.com/users/moip","html_url":"https://github.com/moip","followers_url":"https://api.github.com/users/moip/followers","following_url":"https://api.github.com/users/moip/following{/other_user}","gists_url":"https://api.github.com/users/moip/gists{/gist_id}","starred_url":"https://api.github.com/users/moip/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/moip/subscriptions","organizations_url":"https://api.github.com/users/moip/orgs","repos_url":"https://api.github.com/users/moip/repos","events_url":"https://api.github.com/users/moip/events{/privacy}","received_events_url":"https://api.github.com/users/moip/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/moip/blog-devs","description":"Blog Moip Devs","fork":false,"url":"https://api.github.com/repos/moip/blog-devs","forks_url":"https://api.github.com/repos/moip/blog-devs/forks","keys_url":"https://api.github.com/repos/moip/blog-devs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/moip/blog-devs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/moip/blog-devs/teams","hooks_url":"https://api.github.com/repos/moip/blog-devs/hooks","issue_events_url":"https://api.github.com/repos/moip/blog-devs/issues/events{/number}","events_url":"https://api.github.com/repos/moip/blog-devs/events","assignees_url":"https://api.github.com/repos/moip/blog-devs/assignees{/user}","branches_url":"https://api.github.com/repos/moip/blog-devs/branches{/branch}","tags_url":"https://api.github.com/repos/moip/blog-devs/tags","blobs_url":"https://api.github.com/repos/moip/blog-devs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/moip/blog-devs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/moip/blog-devs/git/refs{/sha}","trees_url":"https://api.github.com/repos/moip/blog-devs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/moip/blog-devs/statuses/{sha}","languages_url":"https://api.github.com/repos/moip/blog-devs/languages","stargazers_url":"https://api.github.com/repos/moip/blog-devs/stargazers","contributors_url":"https://api.github.com/repos/moip/blog-devs/contributors","subscribers_url":"https://api.github.com/repos/moip/blog-devs/subscribers","subscription_url":"https://api.github.com/repos/moip/blog-devs/subscription","commits_url":"https://api.github.com/repos/moip/blog-devs/commits{/sha}","git_commits_url":"https://api.github.com/repos/moip/blog-devs/git/commits{/sha}","comments_url":"https://api.github.com/repos/moip/blog-devs/comments{/number}","issue_comment_url":"https://api.github.com/repos/moip/blog-devs/issues/comments{/number}","contents_url":"https://api.github.com/repos/moip/blog-devs/contents/{+path}","compare_url":"https://api.github.com/repos/moip/blog-devs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/moip/blog-devs/merges","archive_url":"https://api.github.com/repos/moip/blog-devs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/moip/blog-devs/downloads","issues_url":"https://api.github.com/repos/moip/blog-devs/issues{/number}","pulls_url":"https://api.github.com/repos/moip/blog-devs/pulls{/number}","milestones_url":"https://api.github.com/repos/moip/blog-devs/milestones{/number}","notifications_url":"https://api.github.com/repos/moip/blog-devs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/moip/blog-devs/labels{/name}","releases_url":"https://api.github.com/repos/moip/blog-devs/releases{/id}","created_at":"2015-07-17T11:44:53Z","updated_at":"2015-07-17T11:45:31Z","pushed_at":"2015-09-08T13:20:53Z","git_url":"git://github.com/moip/blog-devs.git","ssh_url":"git@github.com:moip/blog-devs.git","clone_url":"https://github.com/moip/blog-devs.git","svn_url":"https://github.com/moip/blog-devs","homepage":null,"size":376,"stargazers_count":0,"watchers_count":0,"language":"CSS","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":0,"mirror_url":null,"open_issues_count":1,"forks":0,"open_issues":1,"watchers":0,"default_branch":"gh-pages"}},"base":{"label":"moip:gh-pages","ref":"gh-pages","sha":"030e3749005dcf3726bbdf8b5131b24b26b6cd8d","user":{"login":"moip","id":5281980,"avatar_url":"https://avatars.githubusercontent.com/u/5281980?v=3","gravatar_id":"","url":"https://api.github.com/users/moip","html_url":"https://github.com/moip","followers_url":"https://api.github.com/users/moip/followers","following_url":"https://api.github.com/users/moip/following{/other_user}","gists_url":"https://api.github.com/users/moip/gists{/gist_id}","starred_url":"https://api.github.com/users/moip/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/moip/subscriptions","organizations_url":"https://api.github.com/users/moip/orgs","repos_url":"https://api.github.com/users/moip/repos","events_url":"https://api.github.com/users/moip/events{/privacy}","received_events_url":"https://api.github.com/users/moip/received_events","type":"Organization","site_admin":false},"repo":{"id":39251454,"name":"blog-devs","full_name":"moip/blog-devs","owner":{"login":"moip","id":5281980,"avatar_url":"https://avatars.githubusercontent.com/u/5281980?v=3","gravatar_id":"","url":"https://api.github.com/users/moip","html_url":"https://github.com/moip","followers_url":"https://api.github.com/users/moip/followers","following_url":"https://api.github.com/users/moip/following{/other_user}","gists_url":"https://api.github.com/users/moip/gists{/gist_id}","starred_url":"https://api.github.com/users/moip/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/moip/subscriptions","organizations_url":"https://api.github.com/users/moip/orgs","repos_url":"https://api.github.com/users/moip/repos","events_url":"https://api.github.com/users/moip/events{/privacy}","received_events_url":"https://api.github.com/users/moip/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/moip/blog-devs","description":"Blog Moip Devs","fork":false,"url":"https://api.github.com/repos/moip/blog-devs","forks_url":"https://api.github.com/repos/moip/blog-devs/forks","keys_url":"https://api.github.com/repos/moip/blog-devs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/moip/blog-devs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/moip/blog-devs/teams","hooks_url":"https://api.github.com/repos/moip/blog-devs/hooks","issue_events_url":"https://api.github.com/repos/moip/blog-devs/issues/events{/number}","events_url":"https://api.github.com/repos/moip/blog-devs/events","assignees_url":"https://api.github.com/repos/moip/blog-devs/assignees{/user}","branches_url":"https://api.github.com/repos/moip/blog-devs/branches{/branch}","tags_url":"https://api.github.com/repos/moip/blog-devs/tags","blobs_url":"https://api.github.com/repos/moip/blog-devs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/moip/blog-devs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/moip/blog-devs/git/refs{/sha}","trees_url":"https://api.github.com/repos/moip/blog-devs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/moip/blog-devs/statuses/{sha}","languages_url":"https://api.github.com/repos/moip/blog-devs/languages","stargazers_url":"https://api.github.com/repos/moip/blog-devs/stargazers","contributors_url":"https://api.github.com/repos/moip/blog-devs/contributors","subscribers_url":"https://api.github.com/repos/moip/blog-devs/subscribers","subscription_url":"https://api.github.com/repos/moip/blog-devs/subscription","commits_url":"https://api.github.com/repos/moip/blog-devs/commits{/sha}","git_commits_url":"https://api.github.com/repos/moip/blog-devs/git/commits{/sha}","comments_url":"https://api.github.com/repos/moip/blog-devs/comments{/number}","issue_comment_url":"https://api.github.com/repos/moip/blog-devs/issues/comments{/number}","contents_url":"https://api.github.com/repos/moip/blog-devs/contents/{+path}","compare_url":"https://api.github.com/repos/moip/blog-devs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/moip/blog-devs/merges","archive_url":"https://api.github.com/repos/moip/blog-devs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/moip/blog-devs/downloads","issues_url":"https://api.github.com/repos/moip/blog-devs/issues{/number}","pulls_url":"https://api.github.com/repos/moip/blog-devs/pulls{/number}","milestones_url":"https://api.github.com/repos/moip/blog-devs/milestones{/number}","notifications_url":"https://api.github.com/repos/moip/blog-devs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/moip/blog-devs/labels{/name}","releases_url":"https://api.github.com/repos/moip/blog-devs/releases{/id}","created_at":"2015-07-17T11:44:53Z","updated_at":"2015-07-17T11:45:31Z","pushed_at":"2015-09-08T13:20:53Z","git_url":"git://github.com/moip/blog-devs.git","ssh_url":"git@github.com:moip/blog-devs.git","clone_url":"https://github.com/moip/blog-devs.git","svn_url":"https://github.com/moip/blog-devs","homepage":null,"size":376,"stargazers_count":0,"watchers_count":0,"language":"CSS","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":0,"mirror_url":null,"open_issues_count":1,"forks":0,"open_issues":1,"watchers":0,"default_branch":"gh-pages"}},"_links":{"self":{"href":"https://api.github.com/repos/moip/blog-devs/pulls/1"},"html":{"href":"https://github.com/moip/blog-devs/pull/1"},"issue":{"href":"https://api.github.com/repos/moip/blog-devs/issues/1"},"comments":{"href":"https://api.github.com/repos/moip/blog-devs/issues/1/comments"},"review_comments":{"href":"https://api.github.com/repos/moip/blog-devs/pulls/1/comments"},"review_comment":{"href":"https://api.github.com/repos/moip/blog-devs/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/moip/blog-devs/pulls/1/commits"},"statuses":{"href":"https://api.github.com/repos/moip/blog-devs/statuses/5172bff22d15c47eb937a2fe3b60c6b694e6fc6f"}}}}