<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Bruno P. Simão on Medium]]></title>
        <description><![CDATA[Stories by Bruno P. Simão on Medium]]></description>
        <link>https://medium.com/@bpsimao?source=rss-e78349dbd1ed------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*SjwPz6RiyUHLp1yOzsKj6g.png</url>
            <title>Stories by Bruno P. Simão on Medium</title>
            <link>https://medium.com/@bpsimao?source=rss-e78349dbd1ed------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 10:07:41 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@bpsimao/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Limitando o uso de memória RAM no docker-compose]]></title>
            <link>https://medium.com/atelie-de-software/limitando-o-uso-de-mem%C3%B3ria-ram-no-docker-compose-31d81a10a80d?source=rss-e78349dbd1ed------2</link>
            <guid isPermaLink="false">https://medium.com/p/31d81a10a80d</guid>
            <category><![CDATA[docker]]></category>
            <category><![CDATA[desenvolvimento-software]]></category>
            <category><![CDATA[docker-compose]]></category>
            <category><![CDATA[linux]]></category>
            <category><![CDATA[v3]]></category>
            <dc:creator><![CDATA[Bruno P. Simão]]></dc:creator>
            <pubDate>Tue, 12 Nov 2019 14:41:39 GMT</pubDate>
            <atom:updated>2019-11-12T14:41:39.370Z</atom:updated>
            <content:encoded><![CDATA[<h4>Essa dica serve para docker-compose 3.7, utilizando Linux</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/0*HBcX-N2JlfWIaetj.png" /></figure><p>Aloha amigos, tudo na paz?</p><p>O post de hoje será útil para quem deseja limitar o uso de memória RAM da nossa aplicação rodando com <a href="https://www.docker.com/"><strong>Docker</strong></a>.</p><h3>Por que limitar o uso de memória RAM?</h3><p>Ao utilizar o <a href="https://www.docker.com/"><strong>Docker</strong></a><strong> </strong>no Linux,<strong> </strong>percebi que o mesmo utiliza uma quantidade considerável de memória RAM.</p><p>O mesmo já não acontece nos computadores da Apple, pois como ele utiliza o <a href="https://docs.docker.com/docker-for-mac/"><strong>Docker for Mac</strong></a>, é possível limitar a quantidade de memória RAM à ser utilizada.</p><p>Para verificar quanto de memória RAM o seu serviço está utilizando, basta subir o contêiner, e em seguida, executar no terminal o seguinte comando:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/fce89d56f98966c3c5f934897a0083a2/href">https://medium.com/media/fce89d56f98966c3c5f934897a0083a2/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ILIO7peJV_Tj0wrjnMilSg.png" /><figcaption>docker stats</figcaption></figure><p>Por essa tela podemos observar a quantidade de memória RAM que o nosso serviço está utilizando, através da coluna <strong>MEM USAGE</strong>, e qual o limite que ele poderá utilizar (coluna <strong>LIMIT</strong>).</p><p>O meu notebook possui 16GB de RAM, e a coluna <strong>LIMIT</strong> mostra que o serviço pode utilizar praticamente 16GB. Ou seja, ele pode utilizar toda a memória RAM, ocasionando assim num eventual travamento da máquina (o que já aconteceu algumas vezes).</p><h3>Limites/Reservas de memória</h3><p>Para entender limites de memória e reservas de memória de uma maneira bem resumida:</p><ul><li><strong>Limite de memória:</strong> um limite superior estrito à quantidade de memória disponibilizada para um contêiner.</li><li><strong>Reserva de memória:</strong> deve ser definida como a quantidade mínima de memória necessária para que um aplicativo seja executado corretamente. Portanto, não falha ou se comporta mal quando o sistema está tentando recuperar parte da memória.</li></ul><h3>Especificando limites/reserva de memória na versão 3.7</h3><p>Se você utiliza a versão 3.7 do <a href="https://docs.docker.com/compose/"><strong>docker-compose</strong></a>, deve-se inserir a seguinte configuração no arquivo <em>docker-compose.yml</em>:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/eb9133f6a2e1d43584bc61b85c6b284b/href">https://medium.com/media/eb9133f6a2e1d43584bc61b85c6b284b/href</a></iframe><p>Com isso, estamos dizendo ao <a href="https://www.docker.com/"><strong>docker</strong></a><strong> </strong>que ele pode utilizar no máximo 4GB de RAM, com uma reserva mínima de 2GB.</p><p>Feito isso, basta salvar e subir nossa aplicação novamente, com o comando:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7efcc7eeeb788d87f688644f519e2403/href">https://medium.com/media/7efcc7eeeb788d87f688644f519e2403/href</a></iframe><p>Ao subir a aplicação, nos deparamos com a seguinte mensagem de alerta:</p><blockquote><strong>WARNING:</strong> Some services (web) use the ‘deploy’ key, which will be ignored. Compose does not support ‘deploy’ configuration — use `docker stack deploy` to deploy to a swarm.</blockquote><p>Essa mensagem é exibida porquê o <em>docker-compose</em> na versão 3.x não suporta a chave de <em>deploy</em>. Para que isso funcione corretamente, deve-se executar o <a href="https://www.docker.com/"><strong>docker</strong></a> no modo <a href="https://docs.docker.com/engine/swarm/"><strong>swarm</strong></a>.</p><h3>- - Compatibility</h3><p>Porém, uma maneira mais simples que encontrei de resolver essa questão, foi subir a aplicação <a href="https://www.docker.com/"><strong>docker</strong></a> com a flag <em>compatibility</em>:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7a38b273cfec20aa90699865aadfd6be/href">https://medium.com/media/7a38b273cfec20aa90699865aadfd6be/href</a></iframe><p>Segundo a documentação:</p><blockquote>If set, Compose will attempt to convert deploy keys in v3 files to their non-Swarm equivalent</blockquote><p>Ou seja, o docker-compose tentará converter as chaves de <em>deploy</em> nos arquivos v3 em seus equivalentes não Swarm.</p><p>Após isso, basta executar o seguinte comando no terminal para ver se a configuração funcionou:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/fce89d56f98966c3c5f934897a0083a2/href">https://medium.com/media/fce89d56f98966c3c5f934897a0083a2/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-JwjJr6XTmq2sgWu6I0wjw.png" /><figcaption>docker stats após subir a aplicação com o comando docker-compose — compatibility up</figcaption></figure><p>Com isso, podemos observar agora que o limite de memória RAM do nosso serviço é 4GB.</p><h3>Conclusão</h3><p>Por hoje é isso, pessoal! Espero que tenham gostado. Qualquer dúvida, sugestão ou feedback em geral, deixem um comentário, pois estamos sempre monitorando. Mahalo!</p><p>Quer fazer sugestões ou tirar dúvidas? Entre em contato com a gente \o/ Obrigada por ler!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/30/0*u0L8aNIJ6JvDzivO" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/0*0W4KEdPdN96OPwqB.png" /></figure><p><a href="http://marketing.atelie.software/form-para-assinar-news-blog-share"><strong>ASSINE NOSSA NEWSLETTER!</strong></a><strong> <br></strong>E fique por dentro de tudo o que acontece no Ateliê.</p><p>Dê um alô pra gente! E nos acompanhe nas redes sociais:<br>→ <a href="http://atelie.software/"><strong>Nosso site</strong></a><strong><br></strong>→ <a href="https://goo.gl/IJJPd4"><strong>Facebook</strong></a><br>→ <a href="https://goo.gl/1147hb"><strong>Instagram</strong></a><br>→ <a href="https://goo.gl/afIL5i"><strong>Twitter</strong></a><br>→ <a href="https://goo.gl/nmbVb6"><strong>Youtube</strong></a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=31d81a10a80d" width="1" height="1" alt=""><hr><p><a href="https://medium.com/atelie-de-software/limitando-o-uso-de-mem%C3%B3ria-ram-no-docker-compose-31d81a10a80d">Limitando o uso de memória RAM no docker-compose</a> was originally published in <a href="https://medium.com/atelie-de-software">Share! por Ateliê de Software</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Alertando o usuário sobre alterações não salvas no formulário]]></title>
            <link>https://medium.com/atelie-de-software/alertando-o-usu%C3%A1rio-sobre-altera%C3%A7%C3%B5es-n%C3%A3o-salvas-no-formul%C3%A1rio-db7b150dcc27?source=rss-e78349dbd1ed------2</link>
            <guid isPermaLink="false">https://medium.com/p/db7b150dcc27</guid>
            <category><![CDATA[forms]]></category>
            <category><![CDATA[desenvolvimento-software]]></category>
            <category><![CDATA[ruby-on-rails]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[Bruno P. Simão]]></dc:creator>
            <pubDate>Tue, 17 Sep 2019 20:16:27 GMT</pubDate>
            <atom:updated>2019-09-17T20:16:27.803Z</atom:updated>
            <content:encoded><![CDATA[<h4>Essa dica serve para Ruby on Rails, utilizando jQuery</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*OKneTjXBmQGEvZGa" /></figure><p>Aloha amigos, tudo na paz?</p><p>Vocês alguma vez já estiveram em um website, preencheram aquele formulário gigantesco, e por algum motivo atualizaram a página acidentalmente ou saíram sem salvar, perdendo todo o trabalho realizado?</p><p>Pensando na experiência do usuário (<a href="https://share.atelie.software/ux-n%C3%A3o-%C3%A9-s%C3%B3-prot%C3%B3tipo-c41fb82de051"><strong>UX</strong></a>), isso é terrível, podendo fazer com que ele nunca mais retorne ao seu website.</p><p>Para amenizar esse problema, podemos criar de forma simples, um <a href="https://www.javascript.com/"><strong>JavaScript</strong></a> que alerte o nosso usuário caso o mesmo tente sair do formulário sem salvar as alterações realizadas.</p><h3>Formulário</h3><p>Para começar, iremos utilizar como exemplo um formulário simples para cadastrar <strong>usuários</strong>:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ef827719ce721ebb4ba4c4c63c8c7610/href">https://medium.com/media/ef827719ce721ebb4ba4c4c63c8c7610/href</a></iframe><h3>JavaScript (jQuery)</h3><p>Para verificarmos as alterações não salvas no formulário, deve-se utilizar um pouco de <a href="https://www.javascript.com/"><strong>JavaScript</strong></a>. Vamos criar um arquivo chamado <strong><em>form_check_modified.js</em></strong>, com o<strong> </strong>seguinte trecho de código:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/22bdea2b5595f556c96f8756a64d89f5/href">https://medium.com/media/22bdea2b5595f556c96f8756a64d89f5/href</a></iframe><p>Estamos selecionando o formulário por meio de uma role (<strong><em>[role=“check-modified”]</em></strong>), o que significa que precisaremos modificar o formulário de usuário para incluir essa função.</p><p>Essa é uma boa prática utilizada para prevenir alertas indesejados na aplicação, como formulários de pesquisa ou outros que serão salvos automaticamente quando os campos forem alterados.</p><p>Então, no formulário de usuário, vamos adicionar a role <strong><em>“check-modified”</em></strong>, para que o <a href="https://www.javascript.com/"><strong>JavaScript</strong></a> possa verificar nosso formulário quanto às alterações não salvas:</p><blockquote>&lt;%= simple_form_for(@user, <strong><em>html: { role: ‘check-modified’ }</em></strong>) do |f| %&gt;</blockquote><h3>Resultado</h3><p>Agora, quando atualizamos nossa página, sempre que modificamos o formulário e tentamos sair sem salvar, recebemos o seguinte alerta:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/501/1*nZGbpOaCICfUmB1nK6eESw.png" /></figure><h3>Conclusão</h3><p>Por hoje é isso, pessoal! Espero que tenham gostado. Qualquer dúvida, sugestão ou feedback em geral, deixem um comentário, pois estamos sempre monitorando. Mahalo!</p><p>Quer fazer sugestões ou tirar dúvidas? Entre em contato com a gente \o/ Obrigada por ler!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*hpdil_RdUvuBtUDbgJ8olw.png" /></figure><p><a href="http://marketing.atelie.software/form-para-assinar-news-blog-share"><strong>ASSINE NOSSA NEWSLETTER!</strong></a><strong> <br></strong>E fique por dentro de tudo o que acontece no Ateliê.</p><p>Dê um alô pra gente! E nos acompanhe nas redes sociais:<br>→ <a href="http://atelie.software/"><strong>Nosso site</strong></a><strong><br></strong>→ <a href="https://goo.gl/IJJPd4"><strong>Facebook</strong></a><br>→ <a href="https://goo.gl/1147hb"><strong>Instagram</strong></a><br>→ <a href="https://goo.gl/afIL5i"><strong>Twitter</strong></a><br>→ <a href="https://goo.gl/nmbVb6"><strong>Youtube</strong></a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=db7b150dcc27" width="1" height="1" alt=""><hr><p><a href="https://medium.com/atelie-de-software/alertando-o-usu%C3%A1rio-sobre-altera%C3%A7%C3%B5es-n%C3%A3o-salvas-no-formul%C3%A1rio-db7b150dcc27">Alertando o usuário sobre alterações não salvas no formulário</a> was originally published in <a href="https://medium.com/atelie-de-software">Share! por Ateliê de Software</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Ajuste do BetterErrors (ip dinâmico) para Docker]]></title>
            <link>https://medium.com/atelie-de-software/ajuste-do-bettererrors-ip-din%C3%A2mico-para-docker-1502a5a5e935?source=rss-e78349dbd1ed------2</link>
            <guid isPermaLink="false">https://medium.com/p/1502a5a5e935</guid>
            <category><![CDATA[ruby-on-rails]]></category>
            <category><![CDATA[docker]]></category>
            <category><![CDATA[better-error]]></category>
            <category><![CDATA[desenvolvimento-software]]></category>
            <dc:creator><![CDATA[Bruno P. Simão]]></dc:creator>
            <pubDate>Mon, 26 Nov 2018 12:19:11 GMT</pubDate>
            <atom:updated>2018-11-26T12:21:22.770Z</atom:updated>
            <content:encoded><![CDATA[<h3>Ajuste do BetterErrors (IP dinâmico) para Docker</h3><h4>Essa dica serve para Ruby on Rails, utilizando Docker e a gem BetterErrors</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Fc3k0vj_TJhm1CMz" /></figure><p>Aloha amigos, tudo na paz?</p><p>Podemos utilizar a gem <a href="https://github.com/BetterErrors/better_errors"><strong>BetterErrors</strong></a> para exibirmos uma página de erro mais amigável no Rails. Em conjunto, utilizamos ainda outra gem, a <a href="https://github.com/banister/binding_of_caller"><strong>binding_of_caller</strong></a><strong>, </strong>permitindo debugar nossa aplicação pelo próprio navegador.</p><p>Para que isso funcione corretamente, precisamos informar ao <a href="https://github.com/BetterErrors/better_errors"><strong>BetterErrors</strong></a> qual o ip da nossa aplicação, através da configuração. Segue abaixo um exemplo:</p><blockquote>BetterErrors::Middleware.allow_ip! <strong>“172.18.0.1”</strong></blockquote><p>Com isso, teremos uma tela de erro exibida dessa forma:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Tkdk_FPxY8LSLRyL" /><figcaption>Tela de erro do Rails utilizando o BetterErrors. Fonte: <a href="https://github.com/BetterErrors/better_errors">https://github.com/BetterErrors/better_errors</a></figcaption></figure><h3>Docker</h3><p>Utilizamos o <a href="https://www.docker.com/"><strong>docker</strong></a> para subir nossas aplicações. Porém, o que ocorre em muitas das vezes é que o <a href="https://www.docker.com/"><strong>docker</strong></a> utiliza ip diferente ao subir um servidor, e com isso, nossa configuração do <a href="https://github.com/BetterErrors/better_errors"><strong>BetterErrors</strong></a> deixa de funcionar.</p><h3>Configurando o BetterErrors</h3><p>Para corrigirmos isso, vamos criar um arquivo <strong><em>better_errors.rb </em></strong>na pasta <em>config/initializers. </em>Nesse arquivo, iremos inserir a seguinte configuração:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/163b641f9526d4fab9a926361cafda1c/href">https://medium.com/media/163b641f9526d4fab9a926361cafda1c/href</a></iframe><p>Feito isso, basta subir o servidor novamente.</p><h3>Conclusão</h3><p>Por hoje é isso, pessoal! Espero que tenham gostado. Qualquer dúvida, sugestão ou feedback em geral, deixem um comentário, pois estamos sempre monitorando. Mahalo!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*hpdil_RdUvuBtUDbgJ8olw.png" /></figure><p><a href="http://marketing.atelie.software/form-para-assinar-news-blog-share"><strong>ASSINE NOSSA NEWSLETTER!</strong></a><strong> </strong>E dê um alô pra gente, nos acompanhe nas redes sociais: → <a href="http://atelie.software/"><strong>Site</strong></a><strong> </strong>→ <a href="https://goo.gl/IJJPd4"><strong>Facebook</strong></a><strong> </strong>→ <a href="https://goo.gl/1147hb"><strong>Instagram</strong></a><strong> </strong>→ <a href="https://goo.gl/afIL5i"><strong>Twitter</strong></a><strong> </strong>→ <a href="https://goo.gl/nmbVb6"><strong>Youtub</strong></a><strong>e</strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1502a5a5e935" width="1" height="1" alt=""><hr><p><a href="https://medium.com/atelie-de-software/ajuste-do-bettererrors-ip-din%C3%A2mico-para-docker-1502a5a5e935">Ajuste do BetterErrors (ip dinâmico) para Docker</a> was originally published in <a href="https://medium.com/atelie-de-software">Share! por Ateliê de Software</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Evitando erros de duplicidade com Factory Bot]]></title>
            <link>https://medium.com/atelie-de-software/evitando-erros-de-duplicidade-com-factory-bot-e0b94c9ed171?source=rss-e78349dbd1ed------2</link>
            <guid isPermaLink="false">https://medium.com/p/e0b94c9ed171</guid>
            <category><![CDATA[ffaker]]></category>
            <category><![CDATA[desenvolvimento-software]]></category>
            <category><![CDATA[rspec]]></category>
            <category><![CDATA[factory-girl]]></category>
            <category><![CDATA[ruby-on-rails]]></category>
            <dc:creator><![CDATA[Bruno P. Simão]]></dc:creator>
            <pubDate>Mon, 27 Aug 2018 16:51:34 GMT</pubDate>
            <atom:updated>2018-08-27T16:51:34.343Z</atom:updated>
            <content:encoded><![CDATA[<h4>Essa dica serve para Ruby on Rails, utilizando Factory Bot, FFaker e RSpec</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*BH6IaCwNOn2D8zUg" /></figure><p>Aloha amigos, tudo na paz?</p><p>Aqui no Ateliê de Software utilizamos o <a href="http://tdd.caelum.com.br/"><strong>TDD</strong> <strong>(Test Driven Development)</strong></a>, ou <a href="http://tdd.caelum.com.br/"><strong>Desenvolvimento Orientado por Testes</strong></a>, que consiste basicamente em:</p><blockquote>Escreva seus testes antes mesmo de escrever o código de produção</blockquote><p>Essa prática ajuda a prevenir erros que poderiam surgir com a introdução de novos requisitos, além de manter a qualidade do nosso código.</p><p>Para desenvolver nossos testes, utilizamos <a href="https://github.com/rspec/rspec-rails"><strong>RSpec</strong></a>, <a href="https://github.com/thoughtbot/factory_bot"><strong>Factory Bot</strong></a> e <a href="https://github.com/ffaker/ffaker"><strong>FFaker</strong></a>.</p><h3>Duplicidade na geração de dados das factories (FFaker)</h3><p>Utilizamos o <a href="https://github.com/rspec/rspec-rails"><strong>RSpec</strong></a><strong> </strong>para escrever nossos testes, aliado ao <a href="https://github.com/thoughtbot/factory_bot"><strong>Factory Bot</strong></a><strong> </strong>para geração das <em>factories</em>, além do <a href="https://github.com/ffaker/ffaker"><strong>FFaker</strong></a>, para geração de dados aleatórios.</p><p>Acontece que, se nossa aplicação possuir muitos testes, o <a href="https://github.com/ffaker/ffaker"><strong>FFaker</strong></a><strong> </strong>pode começar a gerar dados repetidos (o que não deveria, já que os mesmos são aleatórios).</p><p>Para isso, podemos utilizar uma configuração que resolve essa questão.</p><h3>Configurando nosso projeto</h3><p>Devemos configurar a nossa estrutura para que os testes sejam executados em transações. No arquivo <em>spec/rails_helper.rb</em>, insira a seguinte linha de código:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/89ebfe6fac52bb80c1ebca609f3a6950/href">https://medium.com/media/89ebfe6fac52bb80c1ebca609f3a6950/href</a></iframe><p>Vamos agora realizar a configuração das <em>factories</em>. Temos como exemplo uma <em>factory</em> de <strong><em>usuário</em></strong>:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1722876d5660ef4db273e0bc46d6e553/href">https://medium.com/media/1722876d5660ef4db273e0bc46d6e553/href</a></iframe><p>Vamos envolver os atributos em blocos. Isso ajuda o <a href="https://github.com/ffaker/ffaker"><strong>FFaker</strong></a> a manter a singularidade do dados. Segue abaixo como nossa <em>factory</em> ficará:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2db729748830ade2d1a66211299112f3/href">https://medium.com/media/2db729748830ade2d1a66211299112f3/href</a></iframe><p>E por fim, pode-se acrescentar ao <a href="https://github.com/ffaker/ffaker"><strong>FFaker</strong></a> o método<strong> <em>unique</em></strong>, garantindo que o dado gerado seja único. A versão final de nossa <em>factory</em> ficará assim:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4180224dacb9d77ab9ec48c693333455/href">https://medium.com/media/4180224dacb9d77ab9ec48c693333455/href</a></iframe><h3>Conclusão</h3><p>Por hoje é isso, pessoal! Espero que tenham gostado. Qualquer dúvida, sugestão ou feedback em geral, deixem um comentário, pois estamos sempre monitorando. Mahalo!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*hpdil_RdUvuBtUDbgJ8olw.png" /></figure><p><a href="http://marketing.atelie.software/form-para-assinar-news-blog-share"><strong>ASSINE NOSSA NEWSLETTER!</strong></a><strong> <br></strong>E fique por dentro de tudo o que acontece no Ateliê.</p><p>Dê um alô pra gente! E nos acompanhe nas redes sociais:<br>→ <a href="http://atelie.software/"><strong>Nosso site</strong></a><strong><br></strong>→ <a href="https://goo.gl/IJJPd4"><strong>Facebook</strong></a><br>→ <a href="https://goo.gl/1147hb"><strong>Instagram</strong></a><br>→ <a href="https://goo.gl/afIL5i"><strong>Twitter</strong></a><br>→ <a href="https://goo.gl/nmbVb6"><strong>Youtube</strong></a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e0b94c9ed171" width="1" height="1" alt=""><hr><p><a href="https://medium.com/atelie-de-software/evitando-erros-de-duplicidade-com-factory-bot-e0b94c9ed171">Evitando erros de duplicidade com Factory Bot</a> was originally published in <a href="https://medium.com/atelie-de-software">Share! por Ateliê de Software</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Criando um Toggle Switch Button com Sass]]></title>
            <link>https://medium.com/atelie-de-software/criando-um-toggle-switch-button-com-sass-da7d4b2faa45?source=rss-e78349dbd1ed------2</link>
            <guid isPermaLink="false">https://medium.com/p/da7d4b2faa45</guid>
            <category><![CDATA[sass]]></category>
            <category><![CDATA[html]]></category>
            <category><![CDATA[switch]]></category>
            <category><![CDATA[desenvolvimento-software]]></category>
            <category><![CDATA[ux]]></category>
            <dc:creator><![CDATA[Bruno P. Simão]]></dc:creator>
            <pubDate>Thu, 23 Aug 2018 18:01:31 GMT</pubDate>
            <atom:updated>2018-08-23T18:01:31.868Z</atom:updated>
            <content:encoded><![CDATA[<h4>Nessa dica iremos utilizar HTML e Sass</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*QZWNr09Zg3BKvcI8" /></figure><p>Aloha amigos, tudo na paz?</p><p>O post de hoje será útil para quem deseja criar, em poucos passos, um <strong>Toggle Switch Button </strong>(ou botão de<strong> On/Off</strong>).</p><p>Em formulários nos quais o usuário precisa responder com <strong>Sim</strong> ou <strong>Não,</strong> geralmente fazemos uso dos famosos <strong>checkboxes </strong>ou<strong> radios buttons</strong>. Porém a <a href="https://pt.wikipedia.org/wiki/Experi%C3%AAncia_do_usu%C3%A1rio"><strong>UX</strong></a> não fica tão legal, já que esses recursos não possuem uma usabilidade tão intuitiva.</p><p>Com base nisso, podemos utilizar um <strong>Toggle Switch</strong>, que são amplamente utilizados em smartphones, além de possuírem um visual legal e serem bem mais indicativos. Então mãos à obra!</p><h3>HTML</h3><p>Para criar um <em>checkbox</em> em <strong>HTML</strong>, podemos utilizar a seguinte instrução:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4e2db49ef45738241a99e246a02d265e/href">https://medium.com/media/4e2db49ef45738241a99e246a02d265e/href</a></iframe><p>E o resultado gerado será este:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/292/1*Lvlq5B1iYA5S0GlhtGqC1A.jpeg" /><figcaption>Após a criação do <strong>HTML</strong>, o checkbox será exibido conforme imagem acima</figcaption></figure><h3>CSS</h3><p>Para conseguirmos atingir o nosso objetivo, foi necessário criar um arquivo <a href="https://sass-lang.com/"><strong>Sass</strong></a> para customizar o nosso <em>checkbox</em>. Segue o código:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9d56f937d08d4eb1d26ac0341bf6278f/href">https://medium.com/media/9d56f937d08d4eb1d26ac0341bf6278f/href</a></iframe><p>Após criar o <strong>CSS</strong> acima, devemos alterar nosso <strong>HTML</strong>, inserindo uma classe <em>switch</em> no nosso <em>checkbox</em>. O código ficará assim:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6614b1f9678e026df6b1e3dd8bf42e4c/href">https://medium.com/media/6614b1f9678e026df6b1e3dd8bf42e4c/href</a></iframe><p>Com isso, obtemos o seguinte resultado:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/356/1*k89Yl7xN0N3UoXXNljzJ5g.jpeg" /><figcaption>Após a criação do <strong>scss</strong>, o checkbox será exibido conforme imagem acima…</figcaption></figure><h3>Conclusão</h3><p>Por hoje é isso, pessoal! Espero que tenham gostado. Qualquer dúvida, sugestão ou feedback em geral, deixem um comentário, pois estamos sempre monitorando. Mahalo!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*hpdil_RdUvuBtUDbgJ8olw.png" /></figure><p><a href="http://marketing.atelie.software/form-para-assinar-news-blog-share"><strong>ASSINE NOSSA NEWSLETTER!</strong></a><strong> <br></strong>E fique por dentro de tudo o que acontece no Ateliê.</p><p>Dê um alô pra gente! E nos acompanhe nas redes sociais:<br>→ <a href="http://atelie.software/"><strong>Nosso site</strong></a><strong><br></strong>→ <a href="https://goo.gl/IJJPd4"><strong>Facebook</strong></a><br>→ <a href="https://goo.gl/1147hb"><strong>Instagram</strong></a><br>→ <a href="https://goo.gl/afIL5i"><strong>Twitter</strong></a><br>→ <a href="https://goo.gl/nmbVb6"><strong>Youtube</strong></a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=da7d4b2faa45" width="1" height="1" alt=""><hr><p><a href="https://medium.com/atelie-de-software/criando-um-toggle-switch-button-com-sass-da7d4b2faa45">Criando um Toggle Switch Button com Sass</a> was originally published in <a href="https://medium.com/atelie-de-software">Share! por Ateliê de Software</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Creating an OAuth Provider]]></title>
            <link>https://medium.com/atelie-de-software/creating-an-oauth-provider-16109c6229dd?source=rss-e78349dbd1ed------2</link>
            <guid isPermaLink="false">https://medium.com/p/16109c6229dd</guid>
            <category><![CDATA[ruby-on-rails]]></category>
            <category><![CDATA[doorkeeper]]></category>
            <category><![CDATA[devise]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[oauth]]></category>
            <dc:creator><![CDATA[Bruno P. Simão]]></dc:creator>
            <pubDate>Mon, 04 Jun 2018 12:44:17 GMT</pubDate>
            <atom:updated>2018-06-04T12:44:17.040Z</atom:updated>
            <content:encoded><![CDATA[<h4>This tip is for Ruby on Rails 5.2.0, using Doorkeeper and Devise</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*MeWsQy0TkR-KUAjA." /></figure><p>Aloha friends, everything’s fine?<br>In today’s post we’ll create an OAuth provider, which aims to act as an <em>authorization server</em>, allowing multiple applications <em>(clients)</em> to log in to a single location. And for that we’ll use the <a href="https://github.com/doorkeeper-gem/doorkeeper"><strong>Doorkeeper</strong></a><strong> </strong>and <a href="https://github.com/plataformatec/devise"><strong>Devise</strong></a><strong> </strong>libraries.</p><p>First of all, I’d like to thank the help of my co-workers <a href="https://medium.com/u/5b52054701e2">Jorge David</a> and <a href="https://medium.com/u/1b1d1eb7b27e">Altieres Ribeiro Lopes</a> in the preparation of this project, and <a href="https://medium.com/u/6749ab54e66f">Gustavo Canedo</a> who has helped with various issues concerning Docker.</p><h3>OAuth</h3><p>First we need to know what OAuth is.</p><blockquote>OAuth is a widely used authorization protocol for scalable web applications. The current version is 2.0, which makes use of tokens to access data on another system, and probably in another database.</blockquote><p>Have you ever stopped to think about how access is made to your Facebook account in mobile games? It’s with OAuth!</p><p>This protocol enables other systems to access some data without you always having to log in, returning authorization tokens.</p><p>For more information, access the official documentation through this <a href="https://oauth.net/2/"><strong>link</strong></a>.</p><h3>The app</h3><p>Let’s now explain how our application will work. It’ll be divided into two parts: the <em>authorization server</em>, which we’ll call <strong>Accounts</strong>, and the <em>client</em>, which will be our <strong>Client</strong>.</p><p>Both <strong>Accounts </strong>and <strong>Client </strong>will have <em>authentication (with email and password)</em>, which will be created by <a href="https://github.com/plataformatec/devise"><strong>Devise</strong></a>. The access data will be these:</p><blockquote><strong>Accounts</strong></blockquote><blockquote><strong>E-mail:</strong> accounts@ateliedesoftware.com.br<br><strong>Password:</strong> 123456</blockquote><blockquote><strong>Client:</strong></blockquote><blockquote><strong>E-mail:</strong> client@ateliedesoftware.com.br<br><strong>Password:</strong> 123456</blockquote><p>Let’s go to the business rules:</p><blockquote><strong>Scenario 1:</strong> Accounts unlogged and Client unlogged</blockquote><blockquote>When the Client tries to log into Accounts, the Accounts login screen will appear, and after entering the access data, the user will be redirected to the Client.</blockquote><blockquote><strong>Result:</strong> Accounts logged in and Client logged in</blockquote><blockquote><strong>Scenario 2:</strong> Accounts logged in and Client unlogged</blockquote><blockquote>When the Client attempts to log into Accounts, the user will be redirected to the Client, without having to enter the access data.</blockquote><blockquote><strong>Result:</strong> Accounts logged in and Client logged in</blockquote><blockquote><strong>Scenario 3:</strong> Accounts unlogged and Client unlogged</blockquote><blockquote>When the Client attempts to log in locally, the Client login screen will be displayed, and after entering the access data, the user will be redirected to the Client itself.</blockquote><blockquote><strong>Result:</strong> Accounts unlogged and Client logged in</blockquote><h3>Creating the authorization server (Accounts)</h3><p>For the <em>authorization server</em>, we’ll create an application in Ruby on Rails and use the following <strong><em>gems</em></strong>:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a85cc31a3e5dc860b902623f845d6645/href">https://medium.com/media/a85cc31a3e5dc860b902623f845d6645/href</a></iframe><p>Run the installation with the following command on the terminal:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1fc7e1a366652dec6ab09e821005743e/href">https://medium.com/media/1fc7e1a366652dec6ab09e821005743e/href</a></iframe><blockquote>This will generate the <a href="https://github.com/doorkeeper-gem/doorkeeper"><strong>Doorkeeper</strong></a> initializer in config/initializers/doorkeeper.rb</blockquote><p>After that, we should generate the <a href="https://github.com/doorkeeper-gem/doorkeeper"><strong>Doorkeeper</strong></a><strong> </strong>migration, using the following command:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f06c7ce9e1e39d1e1b0a8bea1c979ea7/href">https://medium.com/media/f06c7ce9e1e39d1e1b0a8bea1c979ea7/href</a></iframe><p>And finally, we added foreign keys to our <strong><em>migration</em></strong>. Our file will look like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c8bf02f9eb7f84246360821b0ca96ec6/href">https://medium.com/media/c8bf02f9eb7f84246360821b0ca96ec6/href</a></iframe><h4>Configuration</h4><p>After running the migration, with the<em> rails db:migrate</em> command, we’ll leave our user <strong><em>model </em></strong>as follows:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2227466efc9cade7ce41af26c5acaa84/href">https://medium.com/media/2227466efc9cade7ce41af26c5acaa84/href</a></iframe><h4>Routes</h4><p>Our routes will look like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/551326b0433cefd75dbd21d1fd8df7a1/href">https://medium.com/media/551326b0433cefd75dbd21d1fd8df7a1/href</a></iframe><h4>Authentication</h4><p>We now need to configure our <em>doorkeeper.rb</em> file. In this step we will perform 3 configurations:</p><ul><li><strong><em>resource_owner_authenticator:</em></strong> configuration to perform <a href="https://github.com/doorkeeper-gem/doorkeeper"><strong>Doorkeeper</strong></a><strong> </strong>integration with <a href="https://github.com/plataformatec/devise"><strong>Devise</strong></a>. It’ll be responsible for redirecting the user to your application after login <em>(see scenario 1 of our business rules)</em>.</li><li><strong><em>force_ssl_in_redirect_uri:</em></strong> configuration to determine if we will use <em>https </em>or <em>http</em>. In our case, it will be <em>false</em>.</li><li><strong><em>skip_authorization:</em></strong> A setting that defines whether the authorization form is displayed to the user. In our application, the authentication must be transparent to the user, that is, an authorization confirmation screen should not appear. This will be set to <em>true</em>.</li></ul><p>Following the settings above, our <em>doorkeeper.rb</em> file should look like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b2446eb3b35e9b96bfe96aa0bcacfa75/href">https://medium.com/media/b2446eb3b35e9b96bfe96aa0bcacfa75/href</a></iframe><p>And to finish the configuration of the <em>authorization server</em>, we’ll create the following <strong><em>controllers </em></strong>that should be in the path <em>controllers/api/v1</em>:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/92c38390668bb82a8aa3f16ba562da27/href">https://medium.com/media/92c38390668bb82a8aa3f16ba562da27/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3354a950cb15f180d8d993f1f6e174c9/href">https://medium.com/media/3354a950cb15f180d8d993f1f6e174c9/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2307aab1139c9b08638e0deb40a42653/href">https://medium.com/media/2307aab1139c9b08638e0deb40a42653/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d6b40896a49a4366fdc2d41257cc4cee/href">https://medium.com/media/d6b40896a49a4366fdc2d41257cc4cee/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/76bd8fdab6db8804db242cbad9a3eb6d/href">https://medium.com/media/76bd8fdab6db8804db242cbad9a3eb6d/href</a></iframe><h3>Creating the access provider (Client)</h3><p>For the <em>access provider</em>, we’ll create an application in Ruby on Rails and use the following <strong><em>gems</em></strong>:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/96ea9200f626de997f631830b7aed430/href">https://medium.com/media/96ea9200f626de997f631830b7aed430/href</a></iframe><p>We should now create a <strong><em>migration </em></strong>to add the <em>provider </em>and <em>uid </em>fields to the users <strong><em>model</em></strong>. Our file will look like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5b73b52e858d8b4a107dc36c84b7670e/href">https://medium.com/media/5b73b52e858d8b4a107dc36c84b7670e/href</a></iframe><h3>OmniAuth</h3><p><strong>OmniAuth </strong>assumes that the authorization process has two main phases: <strong><em>request </em></strong>and <strong><em>call-back</em></strong>:</p><ul><li><strong><em>Request </em></strong>is the step where the <em>provider </em>is called. This provider authenticates the user and requests the user’s permission to share the data in the application.</li><li>The provider then performs the <strong><em>callback </em></strong>with the required information.</li></ul><h4>OmniAuth Strategy</h4><p><strong>OmniAuth </strong>lets you add custom providers. For this, we must create a login scheme for our provider through a strategy. Our strategy will be called <strong><em>Webgoal </em></strong>and will be located in <em>lib/strategies/webgoal.rb</em>. The following settings will be performed:</p><ul><li><strong><em>option :name</em></strong> will contain the name of our strategy.</li><li><strong><em>option :client_options, { :site =&gt; … }</em></strong> will contain the URL of our <em>authorization server (the one we created above)</em>.</li></ul><p>With this, our <em>webgoal.rb</em> file will look like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7887a19c6b52719c6504e4aac8dbdaf0/href">https://medium.com/media/7887a19c6b52719c6504e4aac8dbdaf0/href</a></iframe><h4>Devise</h4><p>Once the <strong><em>Webgoal </em></strong>strategy is created, we must inform it in our <em>devise.rb</em> file. With this, our file will conform to the code snippet below <strong><em>(detail for line 36):</em></strong></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d765ecfaf4dc2534564a264fc01e3aa5/href">https://medium.com/media/d765ecfaf4dc2534564a264fc01e3aa5/href</a></iframe><p>When registering a strategy, we must inform the <strong><em>id (DOORKEEPER_APP_ID)</em></strong> and <strong><em>secret (DOORKEEPER_APP_SECRET)</em></strong> generated by <a href="https://github.com/doorkeeper-gem/doorkeeper"><strong>Doorkeeper</strong></a>. To generate these fields, we must register our application in the <a href="https://github.com/doorkeeper-gem/doorkeeper"><strong>Doorkeeper</strong></a>.</p><p>With the authorization server running, we will access the following address:</p><blockquote><a href="http://accounts:3001/oauth/applications">http://accounts:3001/oauth/applications</a></blockquote><p>Click the <strong><em>New Application</em></strong> button and enter the following data:</p><blockquote><strong>Name:</strong> Client<br><strong>Redirect URI:</strong> <a href="http://client:3002/users/auth/webgoal/callback">http://client:3002/users/auth/webgoal/callback</a><br><strong>Scopes:</strong> leave blank</blockquote><p>With this, the following screen will be displayed:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*BYjw5wkX1h6a7rLYeh9d_A.png" /></figure><ul><li>The <em>Application UID</em> must be used in the <strong><em>Webgoal </em></strong>strategy instead of the <strong><em>DOORKEEPER_APP_ID.</em></strong></li><li>The <em>Secret </em>should be used in the <strong><em>Webgoal </em></strong>strategy instead of the <strong><em>DOORKEEPER_APP_SECRET.</em></strong></li></ul><p>After this step, we must create a <strong><em>controller </em></strong>in the <em>users </em>folder, called <strong><em>omniauth_callbacks_controller</em></strong>, which will be responsible for executing the callback triggered by the request of the provider:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6a8fef9225c1aa73abb972b598267954/href">https://medium.com/media/6a8fef9225c1aa73abb972b598267954/href</a></iframe><p>And to finish, we must create a <em>logout </em><strong><em>action</em></strong>, which will be responsible for performing the local and server logout. The code looks like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ae590bb611dc4a612dbc6e91b6e97fbe/href">https://medium.com/media/ae590bb611dc4a612dbc6e91b6e97fbe/href</a></iframe><h3>Project source code</h3><p>This project is hosted on <em>GitHub </em>by <a href="https://github.com/webgoal"><strong>Webgoal</strong></a>. To access it, just use the following links:</p><ul><li><a href="https://github.com/webgoal/spike-oauth-rails52"><strong>Complete project</strong></a></li><li><a href="https://github.com/webgoal/spike-oauth-rails52/tree/master/accounts-app"><strong>Accounts</strong></a></li><li><a href="https://github.com/webgoal/spike-oauth-rails52/tree/master/client-app"><strong>Client</strong></a></li></ul><h3>Project Images</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*y9SwUeqYi3M0vIUNRLDllg.png" /><figcaption>Authorization server main screen (Accounts)</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8QmwgcJZWwoPjKVrLYwHXg.png" /><figcaption>Client main screen</figcaption></figure><h3>Conclusion</h3><p>That’s it for today, folks! I hope you enjoyed. Any questions, suggestions or feedback in general leave a comment, as we are always monitoring. Mahalo!</p><p>Want to make suggestions or ask questions? Contact us \o/<br>Thanks for reading!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*hpdil_RdUvuBtUDbgJ8olw.png" /></figure><p><a href="http://marketing.atelie.software/form-para-assinar-news-blog-share"><strong>SIGN UP FOR OUR NEWSLETTER!</strong></a><strong><br></strong>And stay inside everything that happens in Ateliê.</p><p>Say hello to us! And join us on social networks:<br>→ <a href="http://atelie.software/"><strong>Our site</strong></a><strong><br></strong>→ <a href="https://goo.gl/IJJPd4"><strong>Facebook</strong></a><br>→ <a href="https://goo.gl/1147hb"><strong>Instagram</strong></a><br>→ <a href="https://goo.gl/afIL5i"><strong>Twitter</strong></a><br>→ <a href="https://goo.gl/nmbVb6"><strong>Youtube</strong></a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=16109c6229dd" width="1" height="1" alt=""><hr><p><a href="https://medium.com/atelie-de-software/creating-an-oauth-provider-16109c6229dd">Creating an OAuth Provider</a> was originally published in <a href="https://medium.com/atelie-de-software">Share! por Ateliê de Software</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Criando um provedor OAuth]]></title>
            <link>https://medium.com/atelie-de-software/criando-um-provedor-oauth-9c02ff19faf8?source=rss-e78349dbd1ed------2</link>
            <guid isPermaLink="false">https://medium.com/p/9c02ff19faf8</guid>
            <category><![CDATA[doorkeeper]]></category>
            <category><![CDATA[devise]]></category>
            <category><![CDATA[oauth]]></category>
            <category><![CDATA[desenvolvimento-software]]></category>
            <category><![CDATA[ruby-on-rails]]></category>
            <dc:creator><![CDATA[Bruno P. Simão]]></dc:creator>
            <pubDate>Wed, 30 May 2018 19:11:42 GMT</pubDate>
            <atom:updated>2018-05-30T19:11:42.470Z</atom:updated>
            <content:encoded><![CDATA[<h4>Essa dica serve para Ruby on Rails 5.2.0, utilizando Doorkeeper e Devise</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*MeWsQy0TkR-KUAjA." /></figure><p>Aloha amigos, tudo na paz? <br>No post de hoje vamos criar um provedor OAuth, tendo por objetivo atuar como um <em>servidor de autorização</em>, possibilitando que múltiplas aplicações <em>(clientes)</em> possam realizar o login em um único local. E para isso vamos utilizar as bibliotecas <a href="https://github.com/doorkeeper-gem/doorkeeper"><strong>Doorkeeper</strong></a> e <a href="https://github.com/plataformatec/devise"><strong>Devise</strong></a>.</p><p>Antes de tudo, gostaria de agradecer a ajuda dos colegas de trabalho <a href="https://medium.com/u/5b52054701e2">Jorge David</a> e <a href="https://medium.com/u/1b1d1eb7b27e">Altieres Ribeiro Lopes</a> na elaboração deste projeto e do <a href="https://medium.com/u/6749ab54e66f">Gustavo Canedo</a> que ajudou em diversas questões referentes ao Docker.</p><h3>OAuth</h3><p>Primeiramente precisamos saber o que é o OAuth.</p><blockquote>O OAuth é um protocolo de autorização muito utilizado em aplicações web escaláveis. A versão atual é a 2.0, que faz uso de tokens para acessar dados em outro sistema, e provavelmente em outro banco de dados.</blockquote><p>Você já parou para pensar como é feito o acesso à sua conta Facebook em jogos para celular? É utilizando OAuth!</p><p>Esse protocolo possibilita que outros sistemas acessem alguns dados sem que você precise fazer login sempre, retornando tokens de autorização.</p><p>Para mais informações, acesse a documentação oficial através desse <a href="https://oauth.net/2/"><strong>link</strong></a>.</p><h3>A aplicação</h3><p>Vamos explicar agora como nossa aplicação irá funcionar. Ela será dividida em duas partes: o <em>servidor de autorização</em>, que chamaremos de <strong>Accounts</strong>, e o <em>cliente</em>, que será nosso <strong>Client</strong>.</p><p>Tanto o <strong>Accounts</strong> quanto o <strong>Client</strong> irão possuir <em>autenticação</em> <em>(com e-mail e senha)</em>, que serão criados pela <a href="https://github.com/plataformatec/devise"><strong>Devise</strong></a>. Os dados de acesso serão esses<strong>:</strong></p><blockquote><strong>Accounts</strong></blockquote><blockquote><strong>E-mail:</strong> accounts@ateliedesoftware.com.br<br><strong>Senha:</strong> 123456</blockquote><blockquote><strong>Client:</strong></blockquote><blockquote><strong>E-mail:</strong> client@ateliedesoftware.com.br<br><strong>Senha:</strong> 123456</blockquote><p>Vamos para as regras de negócio:</p><blockquote><strong>Cenário 1:</strong> Accounts deslogado e Client deslogado</blockquote><blockquote>Quando o Client tentar logar no Accounts, será exibida a tela de login do Accounts e após a inserção dos dados de acesso, o usuário será redirecionado para o Client.</blockquote><blockquote><strong>Resultado:</strong> Accounts logado e Client logado</blockquote><blockquote><strong>Cenário 2:</strong> Accounts logado e Client deslogado</blockquote><blockquote>Quando o Client tentar logar no Accounts, o usuário será redirecionado para o Client, sem a necessidade de informar os dados de acesso.</blockquote><blockquote><strong>Resultado:</strong> Accounts logado e Client logado</blockquote><blockquote><strong>Cenário 3:</strong> Accounts deslogado e Client deslogado</blockquote><blockquote>Quando o Client tentar logar localmente, será exibida a tela de login do Client e após a inserção dos dados de acesso, o usuário será redirecionado para o próprio Client.</blockquote><blockquote><strong>Resultado:</strong> Accounts deslogado e Client logado</blockquote><h3>Criando o servidor de autorização (Accounts)</h3><p>Para o <em>servidor de autorização</em>, criaremos uma aplicação em Ruby on Rails e utilizaremos as seguintes <strong><em>gems</em></strong>:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a85cc31a3e5dc860b902623f845d6645/href">https://medium.com/media/a85cc31a3e5dc860b902623f845d6645/href</a></iframe><p>Execute a instalação com o seguinte comando no terminal:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1fc7e1a366652dec6ab09e821005743e/href">https://medium.com/media/1fc7e1a366652dec6ab09e821005743e/href</a></iframe><blockquote>Isso irá gerar o inicializador do <a href="https://github.com/doorkeeper-gem/doorkeeper"><strong>Doorkeeper</strong></a> em config/initializers/doorkeeper.rb</blockquote><p>Após isso, deveremos gerar a migração do <a href="https://github.com/doorkeeper-gem/doorkeeper"><strong>Doorkeeper</strong></a>, utilizando o seguinte comando:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f06c7ce9e1e39d1e1b0a8bea1c979ea7/href">https://medium.com/media/f06c7ce9e1e39d1e1b0a8bea1c979ea7/href</a></iframe><p>E por fim, adicionamos chaves estrangeiras à nossa <strong><em>migração</em></strong>. O nosso arquivo ficará assim:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c8bf02f9eb7f84246360821b0ca96ec6/href">https://medium.com/media/c8bf02f9eb7f84246360821b0ca96ec6/href</a></iframe><h4>Configuração</h4><p>Após executar a migração, com o comando <em>rails db:migrate</em>, iremos deixar a nossa <strong><em>model</em></strong> de usuário da seguinte forma:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2227466efc9cade7ce41af26c5acaa84/href">https://medium.com/media/2227466efc9cade7ce41af26c5acaa84/href</a></iframe><h4>Rotas</h4><p>As nossas rotas ficarão assim:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/551326b0433cefd75dbd21d1fd8df7a1/href">https://medium.com/media/551326b0433cefd75dbd21d1fd8df7a1/href</a></iframe><h4>Autenticação</h4><p>Precisamos agora configurar o nosso arquivo <em>doorkeeper.rb. </em>Nessa etapa iremos realizar 3 configurações:</p><ul><li><strong><em>resource_owner_authenticator</em>:</strong> configuração para realizar a integração do <a href="https://github.com/doorkeeper-gem/doorkeeper"><strong>Doorkeeper</strong></a> com a <a href="https://github.com/plataformatec/devise"><strong>Devise</strong></a>. Será responsável por fazer o redirecionamento do usuário para sua aplicação após o login <em>(vide cenário 1 das nossas regras de negócio).</em></li><li><strong>force_ssl_in_redirect_uri:</strong> configuração para determinar se iremos utilizar <em>https</em> ou <em>http</em>. No nosso caso, será <em>false</em>.</li><li><strong>skip_authorization:</strong> configuração que define se a tela de autorização será exibida para o usuário. Na nossa aplicação, a autenticação deve ser transparente para o usuário, ou seja, não deverá aparecer uma tela de confirmação de autorização. Com isso, será definida como <em>true</em>.</li></ul><p>Realizada as configurações acima, o nosso arquivo <em>doorkeeper.rb</em> deverá ficar assim:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b2446eb3b35e9b96bfe96aa0bcacfa75/href">https://medium.com/media/b2446eb3b35e9b96bfe96aa0bcacfa75/href</a></iframe><p>E para finalizar a configuração do <em>servidor de autorização</em>, iremos criar as seguintes <strong><em>controllers </em></strong>que deverão ficar no caminho <em>controllers/api/v1</em>:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/92c38390668bb82a8aa3f16ba562da27/href">https://medium.com/media/92c38390668bb82a8aa3f16ba562da27/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3354a950cb15f180d8d993f1f6e174c9/href">https://medium.com/media/3354a950cb15f180d8d993f1f6e174c9/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2307aab1139c9b08638e0deb40a42653/href">https://medium.com/media/2307aab1139c9b08638e0deb40a42653/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d6b40896a49a4366fdc2d41257cc4cee/href">https://medium.com/media/d6b40896a49a4366fdc2d41257cc4cee/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/76bd8fdab6db8804db242cbad9a3eb6d/href">https://medium.com/media/76bd8fdab6db8804db242cbad9a3eb6d/href</a></iframe><h3>Criando o provedor de acesso (Client)</h3><p>Para o <em>provedor de acesso</em>, criaremos uma aplicação em Ruby on Rails e utilizaremos as seguintes <strong><em>gems</em></strong>:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/96ea9200f626de997f631830b7aed430/href">https://medium.com/media/96ea9200f626de997f631830b7aed430/href</a></iframe><p>Devemos agora criar uma <strong><em>migração</em></strong> para adicionar os campos <em>provider</em> e <em>uid</em> para a <strong><em>model</em></strong> de usuários. O nosso arquivo ficará assim:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5b73b52e858d8b4a107dc36c84b7670e/href">https://medium.com/media/5b73b52e858d8b4a107dc36c84b7670e/href</a></iframe><h3>OmniAuth</h3><p>O <strong>OmniAuth</strong> assume que o processo de autorização possui duas fases principais: <strong><em>request</em></strong> e <strong><em>callback:</em></strong></p><ul><li><strong><em>Request</em></strong> é a etapa onde o provedor <em>(provider)</em> é chamado. Esse provedor autentica o usuário e pede a permissão do usuário para compartilhar os dados na aplicação.</li><li>O provedor então executa o <strong><em>callback</em></strong> com as informações necessárias.</li></ul><h4>Estratégia OmniAuth</h4><p>O <strong>OmniAuth</strong> permite adicionar provedores customizados. Para isso, devemos criar um esquema de login para o nosso provedor através de uma estratégia. A nossa estratégia vai se chamar <strong><em>Webgoal </em></strong>e ficará localizada em <em>lib/strategies/webgoal.rb. </em>As seguintes configurações serão realizadas:</p><ul><li><strong><em>option :name</em></strong> irá conter o nome da nossa estratégia.</li><li><strong><em>option :client_options, { :site =&gt; … }</em></strong> irá conter a URL do nosso <em>servidor de autorização (que criamos acima).</em></li></ul><p>Com isso, o nosso arquivo <em>webgoal.rb</em> ficará assim:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7887a19c6b52719c6504e4aac8dbdaf0/href">https://medium.com/media/7887a19c6b52719c6504e4aac8dbdaf0/href</a></iframe><h4>Devise</h4><p>Uma vez criada a estratégia <strong><em>Webgoal</em></strong>, devemos informá-la no nosso arquivo <em>devise.rb</em>. Com isso, nosso arquivo ficará conforme o trecho de código abaixo <strong><em>(detalhe para a linha 36)</em></strong>:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d765ecfaf4dc2534564a264fc01e3aa5/href">https://medium.com/media/d765ecfaf4dc2534564a264fc01e3aa5/href</a></iframe><p>Ao registrar uma estratégia, devemos informar os <strong><em>id (DOORKEEPER_APP_ID) </em></strong>e <strong><em>secret (DOORKEEPER_APP_SECRET) </em></strong>gerados pelo <a href="https://github.com/doorkeeper-gem/doorkeeper"><strong>Doorkeeper</strong></a>. Para gerarmos esses campos, devemos registrar nossa aplicação no <a href="https://github.com/doorkeeper-gem/doorkeeper"><strong>Doorkeeper</strong></a><strong>.</strong></p><p>Com o servidor de autorização rodando, vamos acessar o seguinte endereço:</p><blockquote><a href="http://accounts:3001/oauth/applications">http://accounts:3001/oauth/applications</a></blockquote><p>Clicar no botão <strong><em>Nova Aplicação </em></strong>e inserir os seguintes dados:</p><blockquote><strong>Nome:</strong> Client<br><strong>URI de redirecionamento:</strong> <a href="http://client:3002/users/auth/webgoal/callback">http://client:3002/users/auth/webgoal/callback</a><br><strong>Scopes:</strong> deixar em branco</blockquote><p>Com isso, a seguinte tela será exibida:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*BYjw5wkX1h6a7rLYeh9d_A.png" /></figure><ul><li>O <em>Id da Aplicação (Application UID)</em> deve ser utilizado na estratégia <strong><em>Webgoal</em></strong> no lugar do <strong><em>DOORKEEPER_APP_ID.</em></strong></li><li>O <em>Segredo (Secret)</em> deve ser utilizado na estratégia <strong><em>Webgoal</em></strong> no lugar do <strong><em>DOORKEEPER_APP_SECRET.</em></strong></li></ul><p>Realizada essa etapa, devemos criar uma <strong><em>controller</em></strong> na pasta <em>users</em>, chamada <strong><em>omniauth_callbacks_controller</em></strong>, que será responsável por executar o callback disparado pela request do provedor:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6a8fef9225c1aa73abb972b598267954/href">https://medium.com/media/6a8fef9225c1aa73abb972b598267954/href</a></iframe><p>E para encerrar, devemos criar uma <strong><em>action</em></strong> de <em>logout</em>, que será responsável por realizar o logout local e do servidor. O código fica assim:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ae590bb611dc4a612dbc6e91b6e97fbe/href">https://medium.com/media/ae590bb611dc4a612dbc6e91b6e97fbe/href</a></iframe><h3>Código-fonte do projeto</h3><p>Este projeto está hospedado no <em>GitHub</em> da <a href="https://github.com/webgoal"><strong>Webgoal</strong></a>. Para acessá-lo, basta utilizar os seguintes links:</p><ul><li><a href="https://github.com/webgoal/spike-oauth-rails52"><strong>Projeto completo</strong></a></li><li><a href="https://github.com/webgoal/spike-oauth-rails52/tree/master/accounts-app"><strong>Accounts</strong></a></li><li><a href="https://github.com/webgoal/spike-oauth-rails52/tree/master/client-app"><strong>Client</strong></a></li></ul><h3>Imagens do projeto</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*y9SwUeqYi3M0vIUNRLDllg.png" /><figcaption>Tela principal do servidor de autorização (Accounts)</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8QmwgcJZWwoPjKVrLYwHXg.png" /><figcaption>Tela principal do cliente (Client)</figcaption></figure><h3>Conclusão</h3><p>Por hoje é isso, pessoal! Espero que tenham gostado. Qualquer dúvida, sugestão ou feedback em geral deixem um comentário, pois estamos sempre monitorando. Mahalo!</p><p>Quer fazer sugestões ou tirar dúvidas? Entre em contato com a gente \o/ Obrigado por ler!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*hpdil_RdUvuBtUDbgJ8olw.png" /></figure><p><a href="http://marketing.atelie.software/form-para-assinar-news-blog-share"><strong>ASSINE NOSSA NEWSLETTER!</strong></a><strong> <br></strong>E fique por dentro de tudo o que acontece no Ateliê.</p><p>Dê um alô pra gente! E nos acompanhe nas redes sociais:<br>→ <a href="http://atelie.software/"><strong>Nosso site</strong></a><strong><br></strong>→ <a href="https://goo.gl/IJJPd4"><strong>Facebook</strong></a><br>→ <a href="https://goo.gl/1147hb"><strong>Instagram</strong></a><br>→ <a href="https://goo.gl/afIL5i"><strong>Twitter</strong></a><br>→ <a href="https://goo.gl/nmbVb6"><strong>Youtube</strong></a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9c02ff19faf8" width="1" height="1" alt=""><hr><p><a href="https://medium.com/atelie-de-software/criando-um-provedor-oauth-9c02ff19faf8">Criando um provedor OAuth</a> was originally published in <a href="https://medium.com/atelie-de-software">Share! por Ateliê de Software</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Exibindo Radio Buttons como Button Group]]></title>
            <link>https://medium.com/atelie-de-software/exibindo-radio-buttons-como-button-group-f74edc63fece?source=rss-e78349dbd1ed------2</link>
            <guid isPermaLink="false">https://medium.com/p/f74edc63fece</guid>
            <category><![CDATA[ruby-on-rails]]></category>
            <category><![CDATA[desenvolvimento-software]]></category>
            <category><![CDATA[bootstrap]]></category>
            <category><![CDATA[radiobutton]]></category>
            <category><![CDATA[button-group]]></category>
            <dc:creator><![CDATA[Bruno P. Simão]]></dc:creator>
            <pubDate>Fri, 06 Apr 2018 13:43:28 GMT</pubDate>
            <atom:updated>2018-04-06T13:48:32.809Z</atom:updated>
            <content:encoded><![CDATA[<h4>Essa dica serve para Ruby on Rails, utilizando Simple Form, Bootstrap 4 e um pouco de JavaScript</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*YKNTPvKCFlWFUnwb." /></figure><p>Trabalhar no Ateliê de Software é muito empolgante! Pois a cada dia que passa, estamos diante de novos desafios. E para essa semana, surgiu a seguinte necessidade: exibir uma coleção de <em>radio buttons </em>do <a href="https://github.com/plataformatec/simple_form"><strong>Simple Form</strong></a>, como <em>button group</em> do <a href="https://v4-alpha.getbootstrap.com/components/button-group/"><strong>Bootstrap 4</strong></a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*VW0FPl6LPSnEIyEnhJk5fQ.png" /><figcaption>Coleção sendo exibida como radio buttons</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZraiCfOSTe3olHDcmfaMtQ.png" /><figcaption><strong>DESAFIO:</strong> Coleção sendo exibida como button group</figcaption></figure><blockquote>Após uma pesquisa pela internet, descobri que o <strong>Simple Form</strong> não suporta alguns componentes do <strong>Bootstrap</strong> (dentre deles, o button group).</blockquote><p>Neste post irei mostrar qual solução foi adotada para realizar essa integração, solucionar a nossa necessidade e possivelmente a de outras pessoas.</p><h3>Simple Form</h3><p>Para exibir um <em>radio button</em> com o <strong>Simple Form</strong>, podemos utilizar a seguinte instrução:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7fc2b2d66f5bfd151360d51225547b14/href">https://medium.com/media/7fc2b2d66f5bfd151360d51225547b14/href</a></iframe><p>Se quisermos utilizar um <em>button group</em>, devemos criar um <strong>wrapper customizado</strong>. Na seção abaixo irei demonstrar como fazer isso.</p><p>Adicione o seguinte trecho de código ao arquivo <em>config/initializers/simple_form_bootstrap.rb:</em></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f238131d98b65bd4efc545ec2338109d/href">https://medium.com/media/f238131d98b65bd4efc545ec2338109d/href</a></iframe><p>O método <strong>wrapper</strong> gera uma instância do <strong>SimpleForm::Wrappers::Builder</strong>. Com isso, podemos utilizar a seguinte instrução:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/944eb11d5cc3ac3d554c11b4fad4b869/href">https://medium.com/media/944eb11d5cc3ac3d554c11b4fad4b869/href</a></iframe><p>E o resultado gerado será este:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*YzNrc0GZJXmdz5oss_zK8Q.png" /><figcaption>Após a criação do <strong>wrapper</strong>, os radio buttons serão exibidos conforme imagem acima</figcaption></figure><h3>CSS</h3><p>Para conseguirmos atingir o nosso objetivo, foi necessário criar um arquivo <strong>CSS</strong> para customizar o nosso <em>button group</em>. Segue o código abaixo:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8587609c870e51be9c8fc3e49129b15f/href">https://medium.com/media/8587609c870e51be9c8fc3e49129b15f/href</a></iframe><p>Com isso, obtemos o seguinte resultado:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZraiCfOSTe3olHDcmfaMtQ.png" /><figcaption>Após a criação do <strong>css</strong>, o button group será exibido conforme imagem acima…</figcaption></figure><h3>JavaScript</h3><p>Ao abrir o formulário em modo de edição, o <em>button group</em> não estava exibindo o valor que havia sido selecionado. Isso ocorre devido ao fato do <em>button group</em> utilizar a class <strong>active</strong>, enquanto o <em>radio button</em> trabalha com o parâmetro <strong>checked</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*d4pBK17LrATooBRKtBGgWA.png" /><figcaption>Formulário em modo de exibição, não exibe o button group selecionado</figcaption></figure><blockquote>Para corrigir isso, podemos criar um <strong>JavaScript</strong> que verifica qual <em>radio button </em>está selecionado <strong>(checked)</strong>, e<strong> </strong>com isso, adicionar a classe <strong>active</strong> ao botão correspondente.</blockquote><p>O seguinte trecho de código foi utilizado nesta etapa:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/71d05e49673e3f2f40d28aac20d6762e/href">https://medium.com/media/71d05e49673e3f2f40d28aac20d6762e/href</a></iframe><h3>Conclusão</h3><p>Por hoje é isso, pessoal! Espero que tenham gostado. Qualquer dúvida, sugestão ou feedback em geral, deixem um comentário, pois estamos sempre monitorando. Mahalo!</p><p>Quer fazer sugestões ou tirar dúvidas? Entre em contato com a gente \o/ Obrigada por ler!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*hpdil_RdUvuBtUDbgJ8olw.png" /></figure><p><a href="http://marketing.atelie.software/form-para-assinar-news-blog-share"><strong>ASSINE NOSSA NEWSLETTER!</strong></a><strong> <br></strong>E fique por dentro de tudo o que acontece no Ateliê.</p><p>Dê um alô pra gente! E nos acompanhe nas redes sociais:<br>→ <a href="http://atelie.software/"><strong>Nosso site</strong></a><strong><br></strong>→ <a href="https://goo.gl/IJJPd4"><strong>Facebook</strong></a><br>→ <a href="https://goo.gl/1147hb"><strong>Instagram</strong></a><br>→ <a href="https://goo.gl/afIL5i"><strong>Twitter</strong></a><br>→ <a href="https://goo.gl/nmbVb6"><strong>Youtube</strong></a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f74edc63fece" width="1" height="1" alt=""><hr><p><a href="https://medium.com/atelie-de-software/exibindo-radio-buttons-como-button-group-f74edc63fece">Exibindo Radio Buttons como Button Group</a> was originally published in <a href="https://medium.com/atelie-de-software">Share! por Ateliê de Software</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>