Back-End

26 jun, 2012

Gerenciando seu ambiente com o RVM

Publicidade

Alguém de vocês possui apenas um projeto com Ruby? É impossível ter apenas um! Sabemos que cada projeto usa diversas gems, mas como gerenciar isso? Você já deve ter se perguntado: “como faço para organizar um projeto com Rails 3.1 e um outro com Rails 3.0?” ou “e se em um projeto eu quiser utilizar a gem devise 1.x.x e em outro o 2.x.x?”.

Pois bem, o RVM está aí e veio para faciliatr a sua vida!

O que é o RVM?

A sigla significa Ruby Version Manager, que para nós – resumidamente – seria algo como um “gerenciador de versões” para o Ruby. Ele criar ambientes isolados para desenvolver em Ruby, dando condições para usar várias versões de ruby e gems em uma mesma máquina de forma clara e sem conflitos.

Instalando o RVM

Para instalar o RVM, recomendo que você possua um ambiente UNIX e tenha o Git instalado – ele será usado tanto para instalar e atualizar o RVM, quanto para o Ruby.

Abra o seu terminal e digite:

$bash -s stable <<(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer)
# Existe uma exceção para quem utiliza o Lion OS, recomendo essa leitura: http://www.frederico-araujo.com/2011/07/30/installing-rails-on-os-x-lion-with-homebrew-rvm-and-mysql/.

Logo após a instalação, abra o seu .bash_profile ou .bashrc e acrescente esse comando:

echo '[[ -s "$HOME/.rvm/scripts/rvm" ]] && . "$HOME/.rvm/scripts/rvm" # Load RVM function' >> ~/.bash_profile
source ~/.bash_profile
S1=”\$(~/.rvm/bin/rvm-prompt) $PS1

Esta segunda linha é para recarregar o seu bash com o RVM e a terceira é para que a versão do ruby que você está utilizando apareça no prompt.

Reinicie o seu console e digite “rvm”, pois a esta altura ele já deve estar funcionando regularmente 

Instalando versões do Ruby

Com o uso do RVM, é possível instalar qualquer implementação Ruby. Com ele é possível instalar o próprio Ruby, o Ruby Enterprise e o Jruby. Para isso, vamos testar o RVM instalando o 1.9.2-p136. Faça isso no terminal e vá tomar um café, pois é provável que demore um pouco:

$ rvm install 1.9.2-p136

Você pode setar essa versão do Ruby como padrão do RVM dessa forma:

$ rvm --default 1.9.2-p136

E caso deseje voltar para a versão instalada no seu sistema (o Mac OSx costuma vir com a 1.8.7 já instalada), utilize o comando:

$ rvm use system

E para listar os rubies instalados, digite:

$ rvm list

# => ruby-1.9.2-p136 [ x86_64 ]

# ruby-1.9.2-p290 [ x86_64 ]
# ruby-1.9.3-preview1 [ x86_64 ]

Agora você está com a versão 1.9.2-p136 instalada e pronta para receber gems.

Instalando Gems

Digite no seu terminal o comando “gem list” e perceba que suas gems “desapareceram”. Não se assuste, é exatamente o que deveria acontecer, pois cada rubie tem seu ambiente totalmente separado.

Para ver todas as informações do seu rubie, digite “rvm info” e obterá algo do tipo:

$ rvm info

ruby-1.9.2-p136@adena:

system:
uname: "Darwin Uriel-MacbookPro.local 11.2.0 Darwin Kernel Version 11.2.0: Tue Aug 9 20:54:00 PDT 2011; root:xnu-1699.24.8~1/RELEASE_X86_64 x86_64"
bash: "/bin/bash => GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin11)"
zsh: "/bin/zsh => zsh 4.3.11 (i386-apple-darwin11.0)"

rvm:
version: "rvm 1.8.3 by Wayne E. Seguin (wayneeseguin@gmail.com) [https://rvm.beginrescueend.com/]"

ruby:
interpreter: "ruby"
version: "1.9.2p136"
date: "2010-12-25"
platform: "x86_64-darwin11.1.0"
patchlevel: "2010-12-25 revision 30365"
full_version: "ruby 1.9.2p136 (2010-12-25 revision 30365) [x86_64-darwin11.1.0]"

homes:
gem: "/Users/uriel/.rvm/gems/ruby-1.9.2-p136@adena"
ruby: "/Users/uriel/.rvm/rubies/ruby-1.9.2-p136"

binaries:
ruby: "/Users/uriel/.rvm/rubies/ruby-1.9.2-p136/bin/ruby"
irb: "/Users/uriel/.rvm/rubies/ruby-1.9.2-p136/bin/irb"
gem: "/Users/uriel/.rvm/rubies/ruby-1.9.2-p136/bin/gem"
rake: "/Users/uriel/.rvm/gems/ruby-1.9.2-p136@adena/bin/rake"

environment:
PATH: "/Users/uriel/.rvm/gems/ruby-1.9.2-p136@adena/bin:/Users/uriel/.rvm/gems/ruby-1.9.2-p136@global/bin:/Users/uriel/.rvm/rubies/ruby-1.9.2-p136/bin:/Users/uriel/.rvm/bin:/opt/local/bin:/opt/local/sbin:/Library/Frameworks/Python.framework/Versions/2.7/bin:/Library/Frameworks/Python.framework/Versions/2.6/bin:/usr/local/bin:/usr/local/sbin:/opt/python/bin:/Users/uriel/lib/go/bin:/opt/android-sdk/tools:/opt/android-sdk/platform-tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/X11/bin:/usr/local/git/bin"
GEM_HOME: "/Users/uriel/.rvm/gems/ruby-1.9.2-p136@adena"
GEM_PATH: "/Users/uriel/.rvm/gems/ruby-1.9.2-p136@adena:/Users/uriel/.rvm/gems/ruby-1.9.2-p136@global"
MY_RUBY_HOME: "/Users/uriel/.rvm/rubies/ruby-1.9.2-p136"
IRBRC: "/Users/uriel/.rvm/rubies/ruby-1.9.2-p136/.irbrc"
RUBYOPT: ""
gemset: "adena"

Este comando é muito importante e passa todas as informações sobre o ambiente da versão do seu Ruby: onde está instalado, se possui Gemset – e onde ele se encontra, onde as gems estão instaladas etc.

Vamos instalar a gem do Ruby on Rails nesse ambiente? Então utilize o comando:

$ gem install rails -v=3.1 --no-ri --no-rdoc

# Não utilize sudo! É considerado uma má prática, você já possui o RVM para gerenciar seus rubies, esqueça o sudo

Faça um teste após a instalação: liste as gems desse rubie e depois liste as gems instaladas de um outro ruby – pode ser a do próprio sistema. Você verá a diferença.

 Gemsets

Essa é a parte mais interessante ao utilizar essas ferramentas. Vamos supor que eu esteja utilizando a versão 1.9.2-p136 para vários projetos, mas queira separar as gems de cada um: as Gemsets caem como luva. Talvez você não veja muita utilidade agora, mas eu as uso a todo momento. Na Giran utilizo um gemset específico para a plataforma Adena (logo, gemset @adena) e o mesmo rubie para meu outro projeto de CMS (logo, @zephyr), é assim que faço para utilizar a mesma rubie (1.9.2-p136) sem misturar as gems de cada projeto. Isso evita conflitos e logo você perceberá o quão é crucial. Além disso, você pode utilizar uma gemset como se fosse um sandbox, isto é, testar gems em uma mesma rubie. Vamos supor que eu quero testar uma versão específica do Rails (a mais atual, 3.2) nessa mesma rubie citada, por exemplo.

Na prática

Vamos lá, vamos criar uma gemset para um projeto específico: Um CMS.

$ rvm gemset create cms && rvm gemset use cms

Além de criar, você ainda setou essa gemset como padrão a ser utilizada. Fique à vontade para começar seu projeto de CMS com as gems que quiser – existe uma infinidade de gems para você brincar.

Para finalizar, vou dar duas dicas importantes: O uso da gemset global e como setar um arquivo .rvmrc em um projeto Rails.

  • Gemset global

E se você quiser que todos os seus projetos de uma rubie utilizem uma gem específica, como o rake, por exemplo? Você iria instalar em cada gemset o rake? E se você quiser que todos os seus projetos web sigam a evolução do rails?!

Bom, a solução é utilizar uma gemset global, que é responsável por compartilhar gems entre todas as gemsets de uma rubie. Caso precise de fazer isso utilize assim:

$ rvm gemset use global

$ rvm install rake --no-ri --no-rdoc

Arquivo .rvmrc

Se você é railer e usa RVM essa dica é essencial! Os arquivos .rvmrc são indispensáveis para realizar um “setup” do ambiente uma vez que você esteja na pasta de um projeto. Digamos que você tenha baixado um projeto ruby de um amigo em seu repositório online, se o projeto dele possuir esse .rvmrc é muito capaz que ele já prepare todo o ambiente em sua máquina a partir do momento em que você acessar o diretório do projeto.

Espero que você esteja com sua gemset do CMS criada; então como criamos esse arquivo .rvmrc?

$ rvm use 1.9.2-p136@cms --rvmrc --create

Provavelmente ele criará um arquivo .rvmrc com essas linhas:

#!/usr/bin/env bash

# This is an RVM Project .rvmrc file, used to automatically load the ruby
# development environment upon cd'ing into the directory

# First we specify our desired <ruby>[@<gemset>], the @gemset name is optional.
environment_id="ruby-1.9.2-p136@cms"

#
# Uncomment following line if you want options to be set only for given project.
#
# PROJECT_JRUBY_OPTS=( --1.9 )

#
# First we attempt to load the desired environment directly from the environment
# file. This is very fast and efficient compared to running through the entire
# CLI and selector. If you want feedback on which environment was used then
# insert the word 'use' after --create as this triggers verbose mode.
#
if [[ -d "${rvm_path:-$HOME/.rvm}/environments" \
&& -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
then
\. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"

if [[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]]
then
. "${rvm_path:-$HOME/.rvm}/hooks/after_use"
fi
else
# If the environment file has not yet been created, use the RVM CLI to select.
if ! rvm --create use "$environment_id"
then
echo "Failed to create RVM environment '${environment_id}'."
exit 1
fi
fi

#
# If you use an RVM gemset file to install a list of gems (*.gems), you can have
# it be automatically loaded. Uncomment the following and adjust the filename if
# necessary.
#
# filename=".gems"
# if [[ -s "$filename" ]]
# then
# rvm gemset import "$filename" | grep -v already | grep -v listed | grep -v complete | sed '/^$/d'
# fi

# If you use bundler, this might be useful to you:
# if command -v bundle && [[ -s Gemfile ]]
# then
# bundle install
# fi

p.s.: Reparem nas últimas linhas. Você pode instruir o seu arquivo .rvmrc a rodar um bundle install – caso o usuário já tenha a gem bundler instalada – e instalar todas as gems do Gemfile do projeto Rails. Interessante, não?

Pronto, você agora já pode ficar tranquilo. Se alguém der um git clone em seu projeto e após baixado ele acessar a pasta do projeto, o .rvmrc será responsável por criar a gemset para o rubie (tal como @cms).

Obs.: A única parte que arbitrariamente o .rvmrc vai cobrar algo ou possivelmente dará um erro é se o usuário não tiver uma rubie 1.9.2-p136. Porém, uma vez com a rubie instalada, o usuário terá a gemset criada (@cms) a partir do momento que estiver no diretório do projeto clonado.

Enfim, essa foi uma cobertura um pouco superficial do RVM. No entanto, ele possui uma documentação muito vasta. Confira os comandos e outras informações em seu site oficial.

Um abraço a todos!