tag:blogger.com,1999:blog-16661679536019373612024-02-19T14:20:34.981-08:00Coisas da VidaAnonymoushttp://www.blogger.com/profile/05453335211403377349noreply@blogger.comBlogger22125tag:blogger.com,1999:blog-1666167953601937361.post-66380009832413227312016-03-11T03:57:00.002-08:002016-03-11T03:57:31.092-08:00Ruby2.3 Net::Telnet was gemifiedAccording to ruby2.3 changelog, the class "Net::Telnet" was removed from the ruby-core and was "gemified"<br />
<br />
<pre class="code highlight js-syntax-highlight plaintext white" style="background: rgb(248, 250, 252); border-radius: 2px; border: none; box-shadow: none; box-sizing: border-box; color: #5b6169; font-family: Menlo, 'Liberation Mono', Consolas, 'DejaVu Sans Mono', 'Ubuntu Mono', 'Courier New', 'andale mono', 'lucida console', monospace; font-size: 13px !important; line-height: 1.6em !important; margin-bottom: 12px !important; margin-top: 12px !important; overflow: auto; padding: 1em; text-shadow: none; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, 'Liberation Mono', Consolas, 'DejaVu Sans Mono', 'Ubuntu Mono', 'Courier New', 'andale mono', 'lucida console', monospace; font-size: inherit; margin-top: 0px; padding: 0px; word-wrap: normal;">Thu May 21 15:41:45 2015 SHIBATA Hiroshi <hsbt@ruby-lang.org>
* lib/net/telnet.rb: gemify net-telnet.
[Feature #11083]
* gems/bundled_gems: added net-telnet to bundled gems.</code></pre>
<br />
<br />
To use it, just add the gem "net-telnet" to Gemfile!Anonymoushttp://www.blogger.com/profile/05453335211403377349noreply@blogger.com0tag:blogger.com,1999:blog-1666167953601937361.post-75676093990100270702016-02-10T09:44:00.003-08:002016-02-10T09:44:39.603-08:00Helpful tips about debian packagesI have worked with debian packages for a few years, for the company I work at uses this method to deploy the software we do.<br />
<br />
The <a href="https://www.debian.org/distrib/packages" target="_blank">official documentation</a> is very detailed but it is difficult to find the things we want.<br />
<br />
I will give here a few tips that I have learnt in the past years that often helps me a lot.<br />
<br />
<h3>
The folder where the package files (like preinst, postinst, etc) are:</h3>
<div>
<br /></div>
<pre>fabio@perrella:~ $ ll /var/lib/dpkg/info/apache2.*
-rw-r--r-- 1 root root 6065 Jan 14 15:46 /var/lib/dpkg/info/apache2.conffiles
-rw-r--r-- 1 root root 7953 Jan 28 20:52 /var/lib/dpkg/info/apache2.list
-rw-r--r-- 1 root root 1464 Jan 14 15:47 /var/lib/dpkg/info/apache2.md5sums
-rwxr-xr-x 1 root root 13714 Jan 14 15:46 /var/lib/dpkg/info/apache2.postinst*
-rwxr-xr-x 1 root root 3905 Jan 14 15:46 /var/lib/dpkg/info/apache2.postrm*
-rwxr-xr-x 1 root root 4602 Jan 14 15:46 /var/lib/dpkg/info/apache2.preinst*
-rwxr-xr-x 1 root root 229 Jan 14 15:46 /var/lib/dpkg/info/apache2.prerm*
</pre>
<br />
<h3>
The folder where the last installed packages are:</h3>
<div>
<br /></div>
<pre>/var/cache/apt/archives</pre>
<br />
<h3>
How to configure the package to restart the service automatically when it is installed:</h3>
<div>
<br /></div>
<div>
in debian/rules:</div>
<div>
<br /></div>
<pre>dh_installinit --restart-after-upgrade</pre>
<div>
<br /></div>
<div>
This will replace the tag <b>#DEBHELPER#</b> in the file debian/postinst by a code to call the service restart.<br />
<br />
<h3>
Conffiles:</h3>
</div>
<div>
<br /></div>
<div>
Put all configuration files into the file <b>debian/conffiles</b>, this will prevent the package to replace the server configuration files while installing a new version of the package. By doing this, it is not necessary to remove the configuration files from the package or add them as .sample files to the repository.<br />
<br />
Do you have any useful tips? Please add a comment below!</div>
Anonymoushttp://www.blogger.com/profile/05453335211403377349noreply@blogger.com0tag:blogger.com,1999:blog-1666167953601937361.post-50057825416121166662016-02-08T08:40:00.000-08:002016-02-08T08:42:58.739-08:00Chapada Diamantina - Volta ao ParqueRecentemente fizemos o roteiro "Volta ao Parque" na Chapada Diamantina oferecido pela agência <a href="http://venturas.com.br/" target="_blank">Venturas</a>, vou deixar aqui o resumo do que fizemos, o lugar é espetacular!<div>
<br /></div>
<div>
Primeiro, escolhemos como meio de tranporte ir de avião até Salvador e depois de ônibus até Lençois, que é uma das principais cidades na região da chapada com boa infraestrutura para receber turistas. Indo de ônibus pudemos economizar um bom dinheiro (60 reais contra uns 600 do avião na alta temporada), mas só recomendo pra quem tiver paciência e tempo, pois o trajeto é longo, 6h de viagem! Se a escolha for avião, ficar atento que só há viagens Salvador - Lençois às 5ª feiras e domingos.</div>
<div>
<br /></div>
<div>
Em Lençóis, ficamos na pousada <a href="http://www.pousadaraiodesollencois.com.br/index.php?option=com_content&view=article&id=48&Itemid=71" target="_blank">Raio de Sol</a>, apesar de ser bem simples, é confortavel, está bem localizada e tem um bom café da manhã, que é uma tradição das pousadas da região. Pra quem quiser um upgrade nas acomodações, recomendo a pousada <a href="http://www.alcinoestalagem.com/pt/pousada.html" target="_blank">Alcino Estalagem</a> que fica logo ao lado e tem a fama de ter o melhor café da manhã do Brasil!</div>
<div>
<br /></div>
<div>
No 1º dia, chegamos a Lençóis por volta das 14h. Lá fizemos um passeio rápido nos Caldeirões do Serrano passando pelo centro histórico, dá uns 30min a pé da pousada (caminhada tranquila). O lugar é muito legal, com vários caldeirões que formam piscinas naturais e com pequenas quedas d'água.</div>
<div>
<br /></div>
<div>
Há várias agências de turismo pelo pequeno centro da cidade. Elas fazem a mediação entre turistas e guias da região. </div>
<div>
Sempre contrate um guia local! A experiência será 10x mais gostosa com os causos, orientações e atenção prestados por eles. Nós tivemos o grande prazer de conhecer o Tiago (Rasta) - guia local com grande conhecimento do lugar, várias histórias para nos manter motivados e sempre com um sorriso no rosto, mesmo com o cansaço e calor do esforço das caminhadas.</div>
<div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgm4c7nEmaDbEJ0PHXy4UOGn1_Zo14aHVUomA7MW6W0hWSoJBMYgoHWhK46Jm-P5c2cx4_KyO8I9_sjPMwT_Tb95RXZN2rZQvOWLagzJ5Ydd_Qn8SLYBftoCPD5gr3e9gxXPmwPsqT86caU/s1600/GOPR0502.JPG" height="480" width="640" /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
No 2o dia pela manhã, visitamos o Sítio 1 na Serra das Paridas, que é um complexo arqueológico com desenhos e pinturas rupestres, bem legal!</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaLCoCiidCJHQLAvJRjA0xVKUmf6NNj7W_TsAur-cajsfYTbnF1UDaM9fm0_mFN9kQHeAjI0mRcATqI1-XnM0rzV0dsZ34MjvArJaCw0G7JXHBt4W9KblCTxSuC3Hb3sADf8IhZaJXQrgr/s1600/GOPR0556.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaLCoCiidCJHQLAvJRjA0xVKUmf6NNj7W_TsAur-cajsfYTbnF1UDaM9fm0_mFN9kQHeAjI0mRcATqI1-XnM0rzV0dsZ34MjvArJaCw0G7JXHBt4W9KblCTxSuC3Hb3sADf8IhZaJXQrgr/s1600/GOPR0556.JPG" height="480" width="640" /></a></div>
<div>
<br /></div>
<div>
Em seguida fomos para a Cachoeira do Mosquito. O acesso de carro é meio dificil, mas depois a trilha até a cachoeira é relativamente curta e fácil, bem legal tambem!</div>
<div>
Tentamos achar algum diamantinho, mas não foi dessa vez...</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/rKeSrQRxzgY?feature=player_embedded' frameborder='0'></iframe></div>
<div>
<br /></div>
<div>
O legal de pegar o pacote com a agência é que está incluso o traslado para todos os atrativos em um veículo 4x4. A maioria das estradas de terra são bem ruins e longas, eu não me arriscaria com um carro comum. Esse foi nosso carro:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqI9l0mf284oXdZ4-cgxtu__uUQyGCBwvaUeYLDj2YTaml6zXJ0Vhdj4p5uptPBZlgNoOYRZ855-P7zh2ObkYxWpKkET_qEP_HQD-0uPbNKGhEKIm5utGZqpn0Bbs6o4WW-mCuSDYd5k-R/s1600/GOPR1034.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqI9l0mf284oXdZ4-cgxtu__uUQyGCBwvaUeYLDj2YTaml6zXJ0Vhdj4p5uptPBZlgNoOYRZ855-P7zh2ObkYxWpKkET_qEP_HQD-0uPbNKGhEKIm5utGZqpn0Bbs6o4WW-mCuSDYd5k-R/s1600/GOPR1034.JPG" height="300" width="400" /></a></div>
<div>
<br /></div>
<div>
Depois da cachoreira do Mosquito seguimos para o Morro do Pai Inácio (1240m) para vermos o pôr do sol, um belo lugar. A dica é levar um agasalho pois quando o sol vai embora a temperatura cai muito lá em cima!</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggxW_M7mMtIvFc5_c17lZDZBdPZux4xfXSnII7lKg7hkpw1kV_YpkvUgJFmVIJtFNqUS_EzMJ_gvbEpIBrE-_dbYvBZehfmwxjU9q8pItO6MSG1l5yGF3rWzdz0XU-9smY9dTfLbU0ASYJ/s1600/GOPR0749.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggxW_M7mMtIvFc5_c17lZDZBdPZux4xfXSnII7lKg7hkpw1kV_YpkvUgJFmVIJtFNqUS_EzMJ_gvbEpIBrE-_dbYvBZehfmwxjU9q8pItO6MSG1l5yGF3rWzdz0XU-9smY9dTfLbU0ASYJ/s1600/GOPR0749.JPG" height="480" width="640" /></a></div>
<div>
<br /></div>
<div>
No 3o dia, começamos visitando o Poço do Diabo. É um lugar bem legal, de fácil acesso (e por isso um pouco cheio), oferece algumas atrações como tirolesa e rapel.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/xgotbIVeQXo?feature=player_embedded' frameborder='0'></iframe></div>
<div>
<br /></div>
<div>
Em seguida fomos para a gruta da Torrinha. Lá tem os guias especializados que fazem o tour pela gruta. Disseram que uma das trilhas dela tem 13km, nós fizemos uma que tem 1,3km. Eles oferecem capacete e lanterna. O passeio é bem legal, mas nao recomendo pra quem tem dor nas costas ou claustrofobia, pois passamos por alguns lugares bem apertados, mas vale a pena!</div>
<div>
Nessa gruta, existe uma formação muito rara de flor de aragonita dentro da bolha de calcita dentre outras formações.</div>
<div>
A formação que mais me chamou atenção foi essa abaixo, que parece uma miniatura dos arredores do Morro do Pai Inácio!</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQF9xH7x_3d9uYNY5IxKOTrOZzeZrALTJWYvCFAli1_OziCXpH4DRGvc-DCMcQ1zAb0dF2Z1bTFYtqlO7AbI11FmiE_3qtLkh-BjgggkBJjWgV00qWqnqxA7CctJEWPTIi_8SqbQ55143T/s1600/DSC03770.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQF9xH7x_3d9uYNY5IxKOTrOZzeZrALTJWYvCFAli1_OziCXpH4DRGvc-DCMcQ1zAb0dF2Z1bTFYtqlO7AbI11FmiE_3qtLkh-BjgggkBJjWgV00qWqnqxA7CctJEWPTIi_8SqbQ55143T/s1600/DSC03770.JPG" height="480" width="640" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
Em seguida fomos para Pratinha. É um lugar bonito e de fácil acesso, por isso fica bem cheio. Tem várias atrações nesse lugar, a Gruta Azul com águas cristalinas, a flutuação da Pratinha, onde é possível nadar na gruta escura com lanterna e a Prainha, que é como se fosse a praia da Chapada!</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKOrCr9O3sXiaW1kInKdW7UY8twFXrdHvuZ_nr_psUiB048DHVLOAmIOdte871S1VJ8dR_rsbO_pDDruocS-9fIAmW8MOaN9YbMntCYOMWkvGr1t4aO12A_Fu0BK_HgiHx5irDTsqLur3E/s1600/GOPR0927.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKOrCr9O3sXiaW1kInKdW7UY8twFXrdHvuZ_nr_psUiB048DHVLOAmIOdte871S1VJ8dR_rsbO_pDDruocS-9fIAmW8MOaN9YbMntCYOMWkvGr1t4aO12A_Fu0BK_HgiHx5irDTsqLur3E/s1600/GOPR0927.JPG" height="480" width="640" /></a></div>
<div>
<br /></div>
<div>
No final do 3o dia, fomos para o Vale do Capão. É uma cidade bem pequena e afastada. A estrada para chegar lá é bem acidentada, graças ao nosso 4x4 não tivemos problemas. Ficamos na <a href="http://www.pousadadocapao.com.br/" target="_blank">Pousada do Capão</a>, um lugar incrível, com uma bela vista, ótima comida, sauna, piscina natural, etc.</div>
<div>
<br /></div>
<div>
No 4o dia, o destino era a famosa Cachoreira da Fumaça. O trajeto até lá é de 6km de caminhada, sendo que os primeiros 2km são de subida bem forte, uma das mais difíceis da viagem. Mas todo o esforço compensa, pois a visão da cachoeira é de outro mundo, nunca vi nada igual!</div>
<div>
<br /></div>
<div>
Nessas caminhadas mais longas, recomendo usar boné (ou chapeu), camisa de manga comprida de tecido leve (tipo dryfit), calça, pois o sol pode castigar, é um maçarico! (nesse dia eu estava de manga curta, mas no dia seguinte aprendi!). Além disso levar uns 2L de agua por pessoa e lanches pois a caminhada é longa.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzjOwcamb3Fw67Hmb8x81w6PiiRFsi7sqtkt3STEWrWcMJeCXNGG6HtMi742vH2BSGmRrb3MKFqeCane5iV1pVbS3t5mYHT_7CH-9swSNdGWNW0sjSZtPbxN2ABYHdPogUvbDoi3EFGhNc/s1600/GOPR1133.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzjOwcamb3Fw67Hmb8x81w6PiiRFsi7sqtkt3STEWrWcMJeCXNGG6HtMi742vH2BSGmRrb3MKFqeCane5iV1pVbS3t5mYHT_7CH-9swSNdGWNW0sjSZtPbxN2ABYHdPogUvbDoi3EFGhNc/s1600/GOPR1133.JPG" height="480" width="640" /></a></div>
<div>
<br /></div>
<div>
Lá no mirante, tem um senhor que quase sempre esta lá e vende um pastel de palmito de jaca - típico na região - recomendo muito experimentar, é muito bom!</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsc2g2Rcut22y04amaKdRdFrnEAlE-61bjCbZx7-fIVXaO1Cpn1riZOIxUjjjIIm5yr-301uZcjI5Ht9tuK_ZtWouc0YcOeJwvEHLncbRyrW6_fRm3t9oeyyC2HLTTGLdJY3djNw-zTpQb/s1600/DSC03841.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsc2g2Rcut22y04amaKdRdFrnEAlE-61bjCbZx7-fIVXaO1Cpn1riZOIxUjjjIIm5yr-301uZcjI5Ht9tuK_ZtWouc0YcOeJwvEHLncbRyrW6_fRm3t9oeyyC2HLTTGLdJY3djNw-zTpQb/s1600/DSC03841.JPG" height="300" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div>
Depois dessa bela caminhada, paramos no Riachinho para dar uma relaxada. A única coisa a que precisam atentar nesse lugar é que o solo é cheio de pedras e machuca o pé, é um lugar muito bom!</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjESd2BCznwiHfIzKPt30MWCjRlBKnH2EKijFsOXYloc2wpzXsPjIobq0zOwQg_axFenBzCDNL8MazosAjakQQ72RTCHttR-Br_hxIa1om3J0ZQZrApIwl6LNqDnoM8VKvcs0TjgaHObOoR/s1600/GOPR1151.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjESd2BCznwiHfIzKPt30MWCjRlBKnH2EKijFsOXYloc2wpzXsPjIobq0zOwQg_axFenBzCDNL8MazosAjakQQ72RTCHttR-Br_hxIa1om3J0ZQZrApIwl6LNqDnoM8VKvcs0TjgaHObOoR/s1600/GOPR1151.JPG" height="480" width="640" /></a></div>
<div>
<br /></div>
<div>
No próximo post eu comento sobre os outros dias...</div>
Anonymoushttp://www.blogger.com/profile/05453335211403377349noreply@blogger.com0tag:blogger.com,1999:blog-1666167953601937361.post-79644226322272383572015-10-12T13:36:00.003-07:002016-02-08T08:29:17.340-08:00How to investigate errors too many open filesLast week, at my job, we were trying to find the root problem that was killing one of our applications. It is a rails app running on Debian, and we had some clues about the problem:<br />
- looking at New Relic errors, we saw many errors like "getaddrinfo: Name or service not known"<br />
- looking at Unicorn logs, there were a lot of "too many open files" errors<br />
<br />
It seemed the application was being killed by these errors.<br />
<br />
We thought that the server may have some network problems, as this could explain the "Name or service not known" error which is an error that happens when some domain can't be resolved with DNS.<br />
<br />
But after some research, we remembered this kind of "too many open files" error is related with the number of open files in the filesystem. It is possible to list all opened files using the command <b>lsof</b>. We ran this command, but the number was too little. It didn't look like the default limit of 1024 was being reached.<br />
<br />
So we kept searching for some answer to our problem, and we found another way to list the current open files of a process using a command like this:<br />
<br />
<pre>ls -la /proc/3591/fd
</pre>
<br />
This command shows all the file descriptors related to a process (pid).<br />
<br />
We ran this command to our process, and we noticed many file descriptors were not being listed due to permission constraints.<br />
<br />
When we ran the same command with root, all the FDs were there listed. So we thought 'Lets try to run <b>lsof</b> with root to see if the result is different', and it was - a big number had appeared!<br />
<br />
Running <b>lsof</b>, it is possible to filter the output using grep, so we could analyse why there were so many opened files.<br />
<br />
After some analysis, and using a little of bash script, we ended up with this command:<br />
<br />
<pre>lsof | grep -e "^ruby" | awk '{print $9}' | grep imap | wc
</pre>
<br />
This showed us a lot of opened IMAP connections.<br />
<br />
The app uses IMAP to get some information about the mailboxes, and the connections were not being closed after it, so the problem was found!<br />
<br />
So the lesson is, when investigating errors like "too many open files", run <b>lsof</b> with root!<br />
<br />
Here some links I found to understand it better:<br />
<br />
<a href="http://www.commandlinefu.com/commands/view/9893/find-ulimit-values-of-currently-running-process">http://www.commandlinefu.com/commands/view/9893/find-ulimit-values-of-currently-running-process</a><br />
<a href="http://geekswing.com/geek/quickie-tutorial-ulimit-soft-limits-hard-limits-soft-stack-hard-stack/">http://geekswing.com/geek/quickie-tutorial-ulimit-soft-limits-hard-limits-soft-stack-hard-stack/</a>Anonymoushttp://www.blogger.com/profile/05453335211403377349noreply@blogger.com0tag:blogger.com,1999:blog-1666167953601937361.post-25092811171405905802014-10-02T07:13:00.000-07:002014-10-02T07:13:19.679-07:00Como editar configurações de rede Ubuntu 12.04 na mãoVou postar isso aqui pois sempre esqueço qual o arquivo que deve ser alterado:<br />
<br />
sudo vim /etc/NetworkManager/system-connections/Wired\ connection\ 1<br />
<br />
[802-3-ethernet]<br />
duplex=full<br />
mac-address=78:2B:CB:C4:69:52<br />
<br />
[connection]<br />
id=Wired connection 1<br />
uuid=eba66e39-b7d1-4ce8-a79d-60208a94f966<br />
type=802-3-ethernet<br />
timestamp=1394655259<br />
<br />
[ipv6]<br />
method=auto<br />
<br />
[802-1x]<br />
eap=peap;<br />
identity=[USERNAME]<br />
phase2-auth=mschapv2<br />
password=[PASSWORD]<br />
<br />
[ipv4]<br />
method=autoAnonymoushttp://www.blogger.com/profile/05453335211403377349noreply@blogger.com0tag:blogger.com,1999:blog-1666167953601937361.post-16718847645435889432014-09-01T04:54:00.000-07:002014-09-01T07:16:40.029-07:00Testes mais rápidos com Rspec e PostgreSqlUma dica simples e fácil para aumentar a velocidade dos testes no Rspec com PostgreSql é seguir as instruções nesse link:<br />
<div>
<br /></div>
<div>
<a href="http://www.postgresql.org/docs/current/static/non-durability.html">http://www.postgresql.org/docs/current/static/non-durability.html</a><br />
obs: não fiz o 1o item da lista (RAM disk)</div>
<div>
<br /></div>
<div>
No meu caso os testes que rodavam em 4min e 10s cairam para 56s !!</div>
<div>
<br /></div>
<div>
Só não use essas configurações em produção pois o risco perder dados é alto!</div>
Anonymoushttp://www.blogger.com/profile/05453335211403377349noreply@blogger.com2tag:blogger.com,1999:blog-1666167953601937361.post-79464648164764931372014-03-14T06:33:00.000-07:002014-03-14T06:35:08.632-07:00Adicionando o nome do branch em todos os commits do git*obs: testei isso rodando no Ubuntu 12.4, não tenho certeza se funciona no Mac e no Windows<br />
<br />
Com este hook o nome do branch será colocado no começo de todos os commits do git<br />
<br />
Por exemplo se fizer isso no branch [historia_1]<br />
<br />
git commit -am "lala popo"<br />
<br />
A mensagem gravada será "[historia_1] lala popo"<br />
<br />
Segue o passo a passo de como configurar o git para isso:<br />
<br />
- Se estiver usando o git acima da versão 1.7.1, é possível deixar o hook global deste jeito<br />
<br />
<b>git config --global init.templatedir '~/.git_template'</b><br />
<br />
- Depois disso, criar o arquivo abaixo<br />
<br />
<b>~/.git_template/hooks/prepare-commit-msg</b><br />
<br />
- Colocar o conteudo abaixo:<br />
<br />
<b>#!/bin/bash</b><br />
<b><br /></b>
<b>FILE=$1</b><br />
<b><br /></b>
<b>if [[ "$git_status" =~ On\ branch\ ([^[:space:]]+) ]]; then</b><br />
<b> BRANCH_NAME=${BASH_REMATCH[1]}</b><br />
<b> test "$branch" != master || branch=' '</b><br />
<b>else</b><br />
<b> # Detached HEAD. (branch=HEAD is a faster alternative.)</b><br />
<b> BRANCH_NAME="`git describe --all --contains --abbrev=4 HEAD 2> /dev/null ||</b><br />
<b> echo HEAD`"</b><br />
<b>fi</b><br />
<b><br /></b>
<b>echo $1</b><br />
<b><br /></b>
<b>if [ -n "$BRANCH_NAME" ] && [ "$BRANCH_NAME" != "master" ]; then</b><br />
<b> sed -i.bak -e "1s/^/[$BRANCH_NAME] /" $FILE</b><br />
<b>fi</b><br />
<div>
<br /></div>
<div>
- Salvar o arquivo e colocar permissão chmod 755</div>
<div>
<br /></div>
<div>
A partir desse ponto, todos os repositórios clonados e inicializados terão este hook, para os já existentes, precisa rodar o comando <b>git init</b> que carregará o hook global.<br />
<br /></div>
Anonymoushttp://www.blogger.com/profile/05453335211403377349noreply@blogger.com3tag:blogger.com,1999:blog-1666167953601937361.post-33512234212122828612014-01-14T02:38:00.000-08:002014-01-14T02:38:01.354-08:00PostgreSql migrando da versão 9.2 para a 9.3No Debian/Ubuntu existe um jeito simples de fazer um upgrade da versão 9.2 para a versão 9.3 do PostgreSql com os comando <b>pg_upgradecluster </b>(<a href="http://manpages.ubuntu.com/manpages/jaunty/man8/pg_upgradecluster.8.html">http://manpages.ubuntu.com/manpages/jaunty/man8/pg_upgradecluster.8.html</a>).<br />
<br />
Basta seguir o procedimento abaixo:<br />
<br />
sudo apt-get install postgresql-9.3<br />
sudo /etc/init.d/postgresql stop<br />
sudo pg_dropcluster --stop 9.3 main<br />
sudo pg_upgradecluster 9.2 main<br />
<br />
Após isso, é possivel rodar o comando <b>pg_lsclusters</b> para verificar que a versão 9.3 está ok.<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/05453335211403377349noreply@blogger.com2tag:blogger.com,1999:blog-1666167953601937361.post-24127378100291589022013-02-06T15:57:00.000-08:002013-02-06T15:57:24.966-08:00Lumosity - You have the power to improve your brainHoje vou falar do site <a href="http://lumosity.com/">lumosity.com</a><br />
<br />
O Lumosity é um site com vários jogos feitos para treinar o cérebro.<br />
<br />
Segundo eles, os jogos treinam 5 diferentes áreas:<br />
<br />
<ul>
<li>velocidade</li>
<li>memória</li>
<li>atenção</li>
<li>flexibilidade</li>
<li>resolução de problemas</li>
</ul>
<br />
Ao criar uma conta, você escolhe quais áreas deseja melhorar e quais tem preferência no treinamento.<br />
<br />
Todos os dias, são 5 jogos selecionados de acordo com seu perfil. Eles dizem que treinar o cérebro deve ser um costume como escovar os dentes, deve ser feito todos os dias e assim terá resultados no futuro.<br />
<br />
Uma das partes mais legais é acompanhar o gráfico de evolução das suas habilidades e como você se compara com as outras pessoas da sua mesma faixa etária. A seguir coloquei um print dessa tela:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeO52toaBGEYNearAMYv4AE9MVZakgpm0CYVYcce8A83x-jDAwFdw2xTDajJTbBgYHzsZzXRi5OXbJfYlWBbq-axNIMYXlif5GXOQeQ8alFHCtnGURqI1blbdPwH4BTsdzyOmpfdBlMTaH/s1600/lumosity.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="350" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeO52toaBGEYNearAMYv4AE9MVZakgpm0CYVYcce8A83x-jDAwFdw2xTDajJTbBgYHzsZzXRi5OXbJfYlWBbq-axNIMYXlif5GXOQeQ8alFHCtnGURqI1blbdPwH4BTsdzyOmpfdBlMTaH/s640/lumosity.png" width="640" /></a></div>
<br />
Para experimentar é possível criar uma conta trial e jogar por 3 dias.<br />
<br />
Eu não consegui resistir e estou pagando um plano mensal para poder continuar, até minha esposa está treinando e gostando!<br />
<br />
A dica é fazer um plano familiar, fica mais barato por pessoa, inclusive tenho vagas no meu plano, se alguem tiver interesse me avisem!Anonymoushttp://www.blogger.com/profile/05453335211403377349noreply@blogger.com0tag:blogger.com,1999:blog-1666167953601937361.post-50513902041032530612012-04-13T05:03:00.001-07:002012-04-13T05:03:46.525-07:00Importação de dados em massa no MongoDB com MongoimportNo mysql quando precisamos inserir grande quantidade de registros podemos utilizar o comando <a href="http://dev.mysql.com/doc/refman/5.1/en/load-data.html" target="_blank">LOAD DATA</a>, no MongoDB temos o comando <a href="http://www.mongodb.org/display/DOCS/Import+Export+Tools#ImportExportTools-mongoimport" target="_blank">mongoimport</a>, vou falar de algumas coisas que percebemos ao utilizá-lo<br />
obs: Nossa implementação foi feita em Rails + Mongoid<br />
<br />
<h3>
Utilização básica</h3>
<div>
<br /></div>
<div>
Após alguns testes, decidimos utilizar a importação com algumas opções, como abaixo:</div>
<div>
<br /></div>
<div>
<span style="background-color: #b6d7a8;">mongoimport -d [DB_NAME] --upsert --stopOnError -c [COLLECTION] [IMPORT_FILE]</span></div>
<div>
<span style="background-color: white;">onde:</span></div>
<div>
<ul>
<li><span style="background-color: white;">DB_NAME: nome do database</span></li>
<li><span style="background-color: white;">--upsert: atualiza documentos que já existirem (abaixo falarei mais sobre isso);</span></li>
<li><span style="background-color: white;">--stopOnError: interrompe a importação caso ocorra algum erro em alguma linha do arquivo de importação;</span></li>
<li><span style="background-color: white;">COLLECTION: nome da collection;</span></li>
<li><span style="background-color: white;">IMPORT_FILE: arquivo com os os dados a serem importados (falarei mais sobre isso)</span></li>
</ul>
</div>
<div>
<span style="background-color: white;"><br /></span></div>
<h3>
Opção --upsert</h3>
<div>
<br /></div>
<div>
Quando utilizada a opção --upsert, ao importar uma linha, o mongo irá procurar se existe algum documento com esse ID no banco e se existir sobrescreverá esse pelo que está no arquivo de importação, mas atenção, ele não faz e não tem como fazer um MERGE, que é uma <a href="https://jira.mongodb.org/browse/SERVER-1674" target="_blank">feature request</a> no mongodb, ele irá sobrescrever todos atributos desse documento!</div>
<div>
<br /></div>
<div>
Se não utilizada a opção --upsert, as linhas que já existirem no mongo serão ignoradas pela importação</div>
<div>
<br /></div>
<h3>
Arquivo de importação</h3>
<div>
<br /></div>
<div>
Para rodar o mongoimport, é preciso gerar um arquivo de importação seguindo o <a href="http://www.mongodb.org/display/DOCS/Import+Export+Tools#ImportExportTools-Example%3AImportfileformat" target="_blank">exemplo na documentação do mongoimport</a></div>
<div>
<br /></div>
<div>
É preciso tomar cuidado ao gerar esse arquivo, por exemplo alguns campos como <i>created_at</i> e <i>updated_at</i> que são criados automaticamente ao inserir um novo documento, não são criados se não forem colocados nesse arquivo de importação. Também precisamos tomar cuidado com os campos de relacionamento, mesmo que esse documento não esteja relacionado, é preciso colocar no json o campo com o valor vazio.</div>
<div>
<br /></div>
<div>
Na nossa implementação para geração desse arquivo, fizemos um metodo <i>to_mongo_json</i> no modelo a ser importado, para que gerasse o json esperado pelo mongoimport de cada documento.</div>
<div>
<br /></div>
<div>
Para isso utilizamos o método <i>attributes</i> para pegar todos atributos do documento e gerar o json, além disso precisamos converter alguns valores (data, object_ids, etc..) de acordo com <a href="http://www.mongodb.org/display/DOCS/Mongo+Extended+JSON" target="_blank">essa página</a></div>
<div>
<br /></div>
<h3>
Velocidade de importação</h3>
<div>
<br /></div>
<div>
Ao rodar o comando <i>mongoimport</i>, é impresso a taxa de importação. Nos testes que fizemos chegamos a taxas de até 9mil documentos por segundo, muito rapido! Se fizéssemos o <i>create</i> de cada documento individualmente no Rails, demoraria muito mais.</div>
<div>
<br /></div>
<h3>
Atualização de documentos existentes</h3>
<div>
<br /></div>
<div>
Como no mongoimport não existe a opção de <i>merge</i> dos dados, como mencionado acima, a solução seria gerar o json desse documento com todos os dados existentes e rodar o mongoimport com a opção --upsert. Assim poderíamos ter problemas, pois se enquanto a importação estivesse sendo processada, se um documento fosse atualizado pela aplicação, e ele já tivesse seu json gravado no arquivo de importação, ao rodar o mongoimport, os dados atualizados nesse meio tempo seriam perdidos.</div>
<div>
<br /></div>
<div>
O ideal nesse caso seria atualizar somente os novos dados com uma opção de <i>merge</i> que não existe, como falamos acima. Nossa solução foi separar os documentos que já existem no mongo dos que são novos. Para os novos utilizamos o mongoimport normalmente, já para os existentes, não colocamos no arquivo de importação e simplesmente rodamos a query de update direto no mongo, como o exemplo abaixo:</div>
<div>
<br /></div>
<div>
<span style="background-color: #b6d7a8;">MODEL.collection.update({_id: MODEL.id}, { "$set" => { lala: "popo" }, "$addToSet" => { list_ids: {"$each" => lists.map(&:id)} } })</span></div>
<div>
<span style="background-color: #b6d7a8;"><br /></span></div>
<div>
<span style="background-color: white;">O método collection.update é o que o mongoid utiliza internamente para executar as queries no mongodb e pelos testes que fizemos é muito mais rápido do que se utilizássemos o método <i>save</i> do objeto.</span></div>
<div>
<span style="background-color: white;"><br /></span></div>
<div>
<span style="background-color: white;">* Créditos também ao @marciotrindade e Claudio Bruno Martins</span></div>Anonymoushttp://www.blogger.com/profile/05453335211403377349noreply@blogger.com0tag:blogger.com,1999:blog-1666167953601937361.post-6001053680837191142012-04-05T06:57:00.000-07:002012-04-05T06:57:08.129-07:00Campos customizáveis com Rails, MongoDB e MongoidEm algumas situações queremos ter um modelo onde alguns campos podem ser customizáveis pelo cliente, vou dar um exemplo de como implementar isso com Rails, MongoDB e Mongoid<br />
<p><h3>
Onde guardar os campos customizáveis</h3></p>
<div>
A primeira idéia seria se aproveitar do fato do Mongo não ter uma estrutura definida para as collections (tabelas) e criar os campos customizáveis dinamicamente no modelo. No mongoid existe a configuração <i><a href="http://mongoid.org/docs/documents/dynamic.html" target="_blank">allow_dynamic_fields</a></i> que permite que sejam inseridos campos dinamicos no modelo. Mas nessa solução temos alguns problemas, entre eles:</div>
<div>
<ol>
<li>perdemos o controle dos campos customizados que foram criados, pois teriamos que varrer cada documento e ver quais campos existem</li>
<li>nao temos o controle do tipo de campo customizado que foi criado, por exemplo não saberíamos se ele deve se comportar como uma string, data ou inteiro</li>
<li>temos que nos preocupar em proteger os campos default, por exemplo state, id, created_at, etc.. e não permitir que o usuário consiga apagar ou editar esses campos</li>
<li>teríamos que implementar getters e setters no modelo para esses campos, pois não conseguiríamos definir os <i><a href="http://mongoid.org/docs/documents/fields.html" target="_blank">fields</a></i> que é o jeito padrão do mongoid</li>
</ol>
</div>
<div>
A sugestão é criar um campo no modelo chamado custom_fields (ou algo parecido) e externamente um cadastro de campos customizáveis, desse jeito temos algumas vantagens:</div>
<div>
<ol>
<li>temos a lista dos campos customizáveis que existem e seus tipos (data, string, inteiro, etc..)</li>
<li>só precisamos liberar o campo custom_fields para alteração e os campos default podem ficar protegidos no modelo</li>
<li>podemos fazer buscas tipadas, por exemplo se um campo for do tipo data, buscar por um range de datas</li>
</ol>
Utilizando mongoid, a implementação ficaria desse jeito:</div>
<div>
<br /></div>
<div>
<span style="background-color: #93c47d;">field :custom_fields, type: Hash , default: {}</span><br />
<br />
Desse jeito, no mongodb, os campos customizáveis ficam armazenados do mesmo jeito que se fossem <i><a href="http://mongoid.org/docs/relations/embedded/1-n.html" target="_blank">embed documents</a></i><br />
<p><h3>
Criando índice de campos customizáveis</h3></p>
<div>
Porém quando implementamos essa solução, tivemos o receio de que não conseguiriamos criar um índice no mongo para otimizar as buscas por esses campos customizáveis, aí veio a grande surpresa do Mongo!</div>
</div>
<div>
<br /></div>
<div>
O Mongo permite que sejam criados índices desses campos customizáveis mesmo que alguns documentos dessa collection não tenham esse campo, e melhor ainda, mesmo que nenhum documento tenha esse campo customizável. Desse jeito podemos por exemplo, criar um índice em "custom_fields.empresa" mesmo que esse campo ainda não exista, mas quando ele for criado já terá um índice!</div>
<div>
<br /></div>
<div>
No exemplo abaixo temos uma busca feita no mongo sem o índice e logo após a criação do índice e a nova busca. Podemos ver que na primeira, foram percorridos os 1002 documentos e na 2a, somente os 482 do sexo "fem"</div>
<div>
<br /></div>
<script src="https://gist.github.com/2291445.js?file=mongo_shell">
</script>
<br />
<div>
<br />
*Créditos também ao @marciotrindade e Claudio Bruno Martins por esse conteúdo</div>
<div>
<br /></div>
<div>
<br /></div>Anonymoushttp://www.blogger.com/profile/05453335211403377349noreply@blogger.com0tag:blogger.com,1999:blog-1666167953601937361.post-92233096888917794902012-03-19T05:16:00.000-07:002012-03-19T05:16:51.326-07:00Init script para Mongos no DebianProcurei em vários lugares um init script para subir o serviço MONGOS do MONGODB e não achei, resolvi fazer um baseado no init script do mongodb:
<br />
<br />
<script src="https://gist.github.com/2109669.js">
</script>Anonymoushttp://www.blogger.com/profile/05453335211403377349noreply@blogger.com0tag:blogger.com,1999:blog-1666167953601937361.post-710351862890973612011-12-19T03:44:00.000-08:002011-12-19T03:45:39.891-08:00Protegendo linhas do crontab com FLOCKEm algumas situações queremos colocar uma linha no crontab que rode de tempos em tempos, mas queremos garantir de algum modo, que esta não ira rodar em paralelo caso a execução anterior não tenha sido finalizada, por exemplo:<br />
<br />
*/1 * * * * root /sbin/exemplo/processa_relatorios.asp -t diario<br />
<br />
Se as 18:23 o comando <i>processa_relatorios.asp</i> começar e as 18:24 não tiver terminado, teremos 2 execuções em paralelo deste, que pode gerar resultados monstruosos.<br />
<br />
Várias pessoas (inclusive eu) acabam implementando algum mecanismo de lock na aplicação (ou no comando) para que ele consiga saber que já existe outra instância rodando e que não poderá rodar novamente caso o crontab dispare, mas descobri que existe o comando FLOCK, disponivel no Debian e em algumas outras versões de linux, que pode resolver isso com mais facilidade!<br />
<br />
A linha de cron para esse exemplo ficaria assim:<br />
<br />
*/1 * * * * root flock -w 0 /tmp/lock_relatorios -c "/sbin/exemplo/processa_relatorios.asp -t diario"<br />
<br />
onde:<br />
"-w 0" indica que deve esperar 0 segundos caso o comando esteja em execução (isto é, vai desistir de rodar o comando pois não há tempo de espera)<br />
"-c" é o comando a ser executado<br />
"/tmp/lock_relatorios" é o arquivo que será <i>lockado</i> para a execução desse comando<br />
<br />
Outro exemplo:<br />
<br />
- arquivo /etc/cron.d/teste<br />
<br />
*/1 * * * * root flock -w 0 /tmp/test -c "date && sleep 70" >> /tmp/log.txt<br />
<br />
- a saida do log será:<br />
<br />
<br />
Mon Dec 19 09:36:01 BRST 2011<br />
Mon Dec 19 09:38:01 BRST 2011<br />
Mon Dec 19 09:40:01 BRST 2011<br />
<div>
<br /></div>
<div>
Nesse caso podemos ver que não rodou a cada minuto pois havia um "sleep 70" que estava <i>segurando</i> a execução do comando.</div>Anonymoushttp://www.blogger.com/profile/05453335211403377349noreply@blogger.com0tag:blogger.com,1999:blog-1666167953601937361.post-41575636819290724942011-09-14T06:06:00.000-07:002011-12-19T03:45:50.900-08:00Git push para remote diferente do origin - Everything up-to-dateEm vários projetos, precisamos trabalhar em um fork do repositório oficial para futuramente fazermos um merge request (ou pull request) nele.<br />
<br />
O que costumo fazer para isso é clonar o repositorio principal e criar um branch local (work, por exemplo), como abaixo:<br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">git clone https://github.com/tinymce/tinymce.git</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">git remote add perrella git@github.com:fabioperrella/tinymce.git</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">git fetch</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">git checkout -b work</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
Com isso faço meus commits no branch <i>work</i> e depois envio os commits para o branch remoto <i>perrella/master</i> assim:<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-family: 'Times New Roman';"><br /></span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">git push perrella master</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span class="Apple-style-span" style="font-family: inherit;">Mas ocorre esta mensagem: <i>Everything up-to-date</i></span><br />
Você pode ter certeza que nada foi enviado olhando nos commits deste branch no github ou vendo no <i>gitk --all</i> ou no <i>gitx</i> por exemplo.<br />
<span class="Apple-style-span" style="font-family: inherit;"><br /></span><br />
<span class="Apple-style-span" style="font-family: inherit;">A solução para isso é simples (apesar de que não é simples entender na documentação do git push):</span><br />
<span class="Apple-style-span" style="font-family: inherit;"><br /></span><br />
<span class="Apple-style-span" style="font-family: inherit;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">git push perrella <span class="Apple-style-span" style="color: red;">work</span>:master</span></span><br />
<span class="Apple-style-span" style="font-family: inherit;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span></span><br />
<span class="Apple-style-span" style="font-family: inherit;">Onde <i>work</i> é o nome do branch local que você quer enviar para o branch remoto master.</span><br />
<span class="Apple-style-span" style="font-family: inherit;"><br /></span><br />
<span class="Apple-style-span" style="font-family: inherit;">Agradecimentos ao @marciotrindade pela ajuda com isso!</span><br />
<span class="Apple-style-span" style="font-family: inherit;"><br /></span><br />
Se alguém tiver um jeito melhor de fazer isso, comente ai!<br />
<br />
vlw!Anonymoushttp://www.blogger.com/profile/05453335211403377349noreply@blogger.com1tag:blogger.com,1999:blog-1666167953601937361.post-20465841809831389242011-09-07T04:56:00.000-07:002011-12-19T03:46:13.498-08:00Ubuntu Ruby 1.9.2 bug no YAML<br />
Pegamos um bug do Yaml no ruby 1.9.2 (no Ubuntu) que não pegava valores de configuração específica de um enviroment.<br />
*obs: esse problema não ocorre no Mac<br />
<br />
Por exemplo, com essa conf:<br />
<br />
<i>defaults: &defaults</i><br />
<i> default_domain: 'defakto.com.br'</i><br />
<i>development:</i><br />
<i> servers: ['server1.defakto.com.br']</i><br />
<i> <<: *defaults</i><br />
<i>test:</i><br />
<i> servers: ['</i><i>server2.defakto.com.br</i><i>', '</i><i>server3.defakto.com.br</i><i>']</i><br />
<i> <<: *defaults</i><br />
<br />
Com essa conf, no env "test" a config "servers" retornava <i>nil</i><br />
<br />
O problema está mais ou menos explicado <a href="http://pivotallabs.com/users/mkocher/blog/articles/1692-yaml-psych-and-ruby-1-9-2-p180-here-there-be-dragons" target="_blank">neste link</a> e <a href="http://stackoverflow.com/questions/6140493/database-yml-references-not-working" target="_blank">neste outro link</a> tem a solução que é basicamente colocar a linha abaixo no application.rb:<br />
<br />
<i>YAML::ENGINE.yamler = 'syck'</i><br />
<br />
vlw!Anonymoushttp://www.blogger.com/profile/05453335211403377349noreply@blogger.com0tag:blogger.com,1999:blog-1666167953601937361.post-13151969214704576002011-05-13T12:19:00.001-07:002011-12-19T03:46:26.719-08:00CKEditor- Como exibir o label de um botãoTemos um projeto que utiliza o CKEditor e sempre que queremos atualizá-lo, precisamos reaplicar as configurações que fizemos na versão anterior.<br />
<br />
Uma coisa que sempre esqueçemos como fazer, pois é uma <i>gambi</i>, é como exibir os labels de um botão. Fazemos isso pois consideramos que o ícone de alguns botões não são auto-explicativos e precisam de um label ao lado para que nosso usuário entenda sua função.<br />
<br />
Como padrão, só é exibido o label do botão "Código-Fonte", com isso conseguimos descobrir que todos os labels estão no html, porém escondidos!<br />
<br />
Para exibí-los, basta dar um show() nos labels que estão escondidos.<br />
<br />
No nosso caso, adicionamos o seguinte código no config.js para que fique claro o que foi feito num próximo upgrade:<br />
<br />
<pre class="brush: js">CKEDITOR.on('instanceReady',function(ev){
$('.cke_skin_v2 .cke_button_preview .cke_label').show();
$('.cke_skin_v2 .cke_button_maximize .cke_label').show();
$('.cke_skin_v2 .cke_button_pastefromword .cke_label').show();
$('.cke_skin_v2 .cke_button_Fields .cke_label').show();
});
</pre><br />
Agradecimentos ao @marciotrindade pela ajuda<br />
<br />
É isso!Anonymoushttp://www.blogger.com/profile/05453335211403377349noreply@blogger.com1tag:blogger.com,1999:blog-1666167953601937361.post-45601605729017800342011-04-18T16:52:00.000-07:002011-12-19T03:47:25.245-08:00Resolvendo erro "Redirect:Controller could not be found" no CakePHPAcabei de perder quase 1 hora para resolver este problema ridículo, então merece um post!<br />
<br />
Estou fazendo um projeto com CakePHP, meu ambiente de desenvolvimento é um Ubuntu com Apache2 e ao acessar a url <i>http://localhost/users</i> , estava aparecendo o erro abaixo:<br />
<br />
<span class="Apple-style-span" style="font-size: 24px; font-weight: bold;">Missing Controller</span><br />
<br />
<div class="error"> <strong>Error: </strong> <em>Redirect:Controller</em> could not be found.</div><div class="error"> <strong>Error: </strong> Create the class <em>Redirect:Controller</em> below in file: app/controllers/redirect:controller.php</div><pre><?php
class Redirect:Controller extends AppController {
var $name = 'Redirect:';
}
?>
</pre><pre></pre><pre><span class="Apple-style-span" style="font-family: 'Times New Roman'; white-space: normal;">Depois de muito investigar, percebi que o problema era um arquivo users.csv que estava na pasta root do projeto. Com isso, o parâmetro <i>url</i> do $_GET do PHP estava vindo "<i>redirect:/app/webroot/users.csv" </i>e por isso o CakePHP se perdia.</span></pre><pre><span class="Apple-style-span" style="font-family: 'Times New Roman';"><span class="Apple-style-span" style="white-space: normal;"><i>
</i></span></span></pre><pre><span class="Apple-style-span" style="font-family: 'Times New Roman';"><span class="Apple-style-span" style="white-space: normal;">Só não consegui entender exatamente o porquê disso, se alguem souber explicar eu agradeço, mas está ligado ao mod_rewrite do apache2, no CakePHP estou utilizando o .htaccess padrão.</span></span></pre><pre><span class="Apple-style-span" style="font-family: 'Times New Roman';"><span class="Apple-style-span" style="white-space: normal;">
</span></span></pre><pre><span class="Apple-style-span" style="font-family: 'Times New Roman';"><span class="Apple-style-span" style="white-space: normal;">Pelo menos a solução foi encontrada: <span class="Apple-style-span" style="font-size: large;">remover todos os arquivos inúteis da pasta base do projeto</span>.</span></span></pre><pre><span class="Apple-style-span" style="font-family: 'Times New Roman';"><span class="Apple-style-span" style="white-space: normal;">
</span></span></pre><pre><span class="Apple-style-span" style="font-family: 'Times New Roman';"><span class="Apple-style-span" style="white-space: normal;">Até a próxima!</span></span></pre><pre><span class="Apple-style-span" style="font-family: 'Times New Roman';"><span class="Apple-style-span" style="white-space: normal;">
</span></span></pre><pre><span class="Apple-style-span" style="font-family: 'Times New Roman';"><span class="Apple-style-span" style="white-space: normal;">
</span></span></pre>Anonymoushttp://www.blogger.com/profile/05453335211403377349noreply@blogger.com0tag:blogger.com,1999:blog-1666167953601937361.post-28313098751122442702011-03-26T06:55:00.000-07:002011-12-19T03:47:37.818-08:00Cucumber + Capybara + Jquery: Como esperar requisições Ajax terminaremJá tive vários problemas com testes de cucumber que quebram intermitentemente pois as vezes não esperam as requisições Ajax terminarem. Em vários casos desistimos desses testes pois não tínhamos achado uma solução.<br />
<br />
Porém essa semana dei uma nova pesquisada e achei uma solução que está funcionando bem até agora.<br />
<br />
O princípio é usar a função <i><a href="http://stackoverflow.com/questions/3148225/jquery-active-function">active</a></i> do <i>Jquery</i> para saber quantas requisições de ajax (feitas pelo Jquery) ainda estão ativas.<br />
<br />
Com isso, criei um novo <i>step</i> para meus testes Cucumber:<br />
<br />
<pre class="brush: ruby">Given /^I wait for ajax loading$/ do
5.times do
break if page.evaluate_script("$.active") == 0
sleep 1
end
end</pre><br />
E com isso é só utilizar nos testes assim:<br />
<br />
<pre class="brush: ruby">Given I follow "Salvar"
And I wait for ajax loading
Then ...
</pre><br />
É isso!Anonymoushttp://www.blogger.com/profile/05453335211403377349noreply@blogger.com3tag:blogger.com,1999:blog-1666167953601937361.post-45705038969734341732011-01-28T02:23:00.000-08:002011-12-19T03:48:16.788-08:00Problemas com PHP GetText no DebianDica de como fazer funcionar o php gettext em um servidor Debian<br />
<br />
No Ubuntu, conseguimos fazer funcionar seguindo <a href="http://www.sourcerally.net/regin/49-How-to-get-PHP-and-gettext-working-(ubuntu,-debian">este Tutorial</a><br />
<br />
No Debian, podemos seguir este mesmo, mas é preciso 1 passo a mais:<br />
<br />
- <span class="Apple-style-span" style="font-family: Helvetica, Arial, sans-serif; font-size: 13px; line-height: 17px;">descomentar a linha 'es_AR' no arquivo /etc/locale.gen (no meu caso estou traduzindo para o es_AR)</span><br />
<span class="Apple-style-span" style="font-family: Helvetica, Arial, sans-serif; font-size: 13px; line-height: 17px;">- rodar o comando </span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: 13px; line-height: 16px; white-space: pre;">locale-gen</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: 13px; line-height: 16px; white-space: pre;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: 13px; line-height: 16px; white-space: pre;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: 13px; line-height: 16px; white-space: pre;">Dessa maneira funcionou!</span>Anonymoushttp://www.blogger.com/profile/05453335211403377349noreply@blogger.com0tag:blogger.com,1999:blog-1666167953601937361.post-45775546359004726582010-08-16T18:16:00.000-07:002011-12-19T03:48:36.055-08:00Resolvendo problemas de input not found no CucumberNo Cucumber podemos fazer testes que preenchem campos de texto, como abaixo:<br />
<br />
<pre class="brush: ruby">When I fill "login" with "usuario"
</pre><br />
Se o input não tiver um label associado a ele corretamente, o Cucumber não achará o campo e lançará um erro.<br />
<br />
Para que um label esteja associado corretamente a um input, o atributo <b>for</b> do <b>label</b> deve ser o mesmo que o <b>id</b> do <b>input</b>, por exemplo:<br />
<br />
<pre class="brush: html"><label for="login">Login</label> <input id="login" name="login" type="text" />
</pre><br />
<br />
Agora a parte legal, é que se quisermos testar se a associação entre o label e o input está correta, basta clicar no label e ver se o cursor se move para dentro do input, como abaixo:<br />
<br />
<label for="login_input">Login (clique aqui!!)</label> <input id="login_input" name="login" type="text" /><br />
<br />
No exemplo abaixo não deve funcionar pois a associação está errada:<br />
<br />
<label for="login_input_errado">Login (clique aqui!!)</label> <input id="login_input" name="login" type="text" /><br />
<br />
<br />
Se esse teste não funcionar, provavelmente você terá problemas ao rodar o Cucumber.<br />
<br />
Caso queira passar longe desse problema, evite criar códigos HTML na mão e utilize os helpers <i><b>text_field</b></i> e o <i><b>label</b></i> do Rails<br />
<br />
E agora vou aproveitar para agradecer o Autor do post de como utilizar o <a href="http://blog.cartercole.com/2009/10/awesome-syntax-highlighting-made-easy.html">Syntax Highlighting no Blogger</a><br />
<br />
vlw!Anonymoushttp://www.blogger.com/profile/05453335211403377349noreply@blogger.com2tag:blogger.com,1999:blog-1666167953601937361.post-35662691295281262152010-07-15T04:06:00.000-07:002011-12-19T03:48:55.634-08:00Problema com chave pública SSH (id_rsa.pub) para acesso a repositório GIT no Ubuntu 9.10Mais um problema daqueles que faz perdermos alguns minutos importantes da nossa vida<div><br /></div><div>Esta semana estava configurando um desktop Ubuntu 9.10 para acessar um repositório GIT no Gitorious interno que temos na empresa.</div><div><br /></div><div>Normalmente é uma tarefa muito simples (mais detalhes em <a href="http://help.github.com/linux-key-setup/">http://help.github.com/linux-key-setup/</a>), mas no meu caso não estava funcionando. Ao fazer push e pull, o git estava pedindo senha para acesso, que não deve acontecer quando se utiliza chave pública.</div><br /><div><br /></div><div>Após algumas pesquisas na web, descobri a solução (não o problema ao certo)</div><div><br /></div><div>Bastou se deslogar e logar novamente no Ubuntu e funcionou!</div><div><br /></div><div>Até mais!</div>Anonymoushttp://www.blogger.com/profile/05453335211403377349noreply@blogger.com0tag:blogger.com,1999:blog-1666167953601937361.post-22975590597851632532010-07-01T17:42:00.000-07:002015-10-08T05:29:18.334-07:00Rails ssl_allowed e ssl_requiredResolvi fazer esse post para ajudar pessoas que tenham o mesmo problema que tivemos hoje.<br />
<div>
<br /></div>
<div>
No sistema que estamos desenvolvendo, há uma integração com o <a href="http://www.pagamentodigital.com.br/">Pagamento Digital</a> (PD), onde nosso sistema recebe um POST deste para atualizar informações de um pedido.</div>
<div>
<br /></div>
<div>
Ao colocar o sistema no ambiente de integração (RAILS_ENV=production), este passou a utilizar SSL e começamos a ter problemas no processamento do POST de retorno do PD. Ao testar, víamos no log do servidor (log/production.log) que estava sendo feito um redirecionamento (302) para a versão não SSL (http) desta URL.</div>
<div>
<br /></div>
<div>
Para ficar mais claro, o PD fazia post para nossa url <span class="Apple-style-span" style="color: #3333ff;">https://lalala.com/return</span> mas internamente a aplicação redirecionava para <span class="Apple-style-span" style="color: #3366ff;">http://lalala.com/return</span>, perdendo todos os parâmetros que haviam no POST original.</div>
<div>
<br /></div>
<div>
Depois de quebrar a cabeça, descobrimos que nosso sistema estava utilizando o plugin <span class="Apple-style-span" style="color: #3366ff;">ssl_requirement.</span> Esse plugin oferece um modo de configurar actions que permitem funcionar via SSl (<span class="Apple-style-span" style="color: red; font-family: 'Bitstream Vera Sans Mono', Courier, monospace; font-size: 11px; line-height: 15px; white-space: pre;">ssl_allowed</span>) e actions que devem funcionar somente via SSL (<span class="Apple-style-span" style="color: red; font-family: 'Bitstream Vera Sans Mono', Courier, monospace; font-size: 11px; line-height: 15px; white-space: pre;">ssl_required</span>).</div>
<div>
<br /></div>
<div>
No nosso caso, bastou definir no controller que a action permitia o uso de SSL com a diretiva <span class="Apple-style-span" style="color: red; font-family: 'Bitstream Vera Sans Mono', Courier, monospace; font-size: 11px; line-height: 15px; white-space: pre;">ssl_allowed :nome_da_action</span></div>
<div>
<br /></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: 'Bitstream Vera Sans Mono', Courier, monospace; font-size: 11px; line-height: 15px; white-space: pre;"><span class="Apple-style-span" style="color: black; font-family: Georgia, serif; font-size: 16px; line-height: normal; white-space: normal;">Mais informações sobre este plugin em </span></span><a href="http://github.com/rails/ssl_requirement">http://github.com/rails/ssl_requirement</a></div>
<div>
<br /></div>
<div>
Por hoje é isso!</div>
Anonymoushttp://www.blogger.com/profile/05453335211403377349noreply@blogger.com1