Pressione enter para ver os resultados ou esc para cancelar.

Descomplicando o Rails: A instalação

Salve galera, tudo certo? Hoje vamos iniciar em uma jornada cheia de aprendizados, rumo à construção de uma aplicação em Ruby on Rails. A ideia é evoluir com tecnologias do momento como Docker, Next.js, GraphQL e Postgres. Com essa combinação em mãos, temos o suficiente para transformar suas ideias em realidade de forma rápida e eficiente. Então, prepare seu café (sem açúcar) e seja bem-vindo a bordo para a instalação do Ruby on Rails.

Esse é o início de uma série de tutoriais. Ao final desse post você vai ter uma aplicação em Rails, conectada com um banco de dados pronta para ser desenvolvida. O repositório dessa aplicação está em https://github.com/matheuslemke/my-book-shelf.

Ruby ou Ruby on Rails?

Está aí uma questão que pode gerar confusão para qualquer iniciante nesse mundo de RoR. Como um dos meus vícios é fazer analogias, pra explicar essa questão, pense na diferença entre a maçã e uma torta de maçã.

A maçã é uma fruta versátil que, além de poder ser aproveitada individualmente, tem sua importância como ingrediente em diversas receitas. Assim é o Ruby, uma linguagem dinâmica, conhecida por sua elegância e simplicidade. Lançada oficialmente em 1995, o Ruby é uma linguagem open-source, que, segundo o W3Techs é a linguagem que mais ganhou popularidade em 2024 e a 3ª linguagem mais popular no mundo.

Em uma tarde de domingo após o almoço, a torta de maçã é perfeita pra suprir a necessidade doentia de um doce. Perceba que, diferente da maçã, a torta de maçã serve para uma finalidade muito mais específica, mas não perde a essência do seu ingrediente principal. Assim é o Ruby on Rails, ou somente Rails. Um poderoso framework server-side open source escrito em Ruby para construção de aplicações web. Fornece diversas facilidades para o desenvolvedor, como a implementação do padrão ActiveRecord, filosofia de ‘convenções sobre configurações’ na sua essência e a necessidade de escrever pouco código para implementar soluções eficazes.

Em resumo, precisa de maçã pra fazer torta de maçã. Mas se você não precisa de uma torta, talvez a maçã resolva a sua necessidade.

Preparando o ambiente

Gosto de uma fala do John Elder, escritor de dois best-sellers na Amazon sobre intrudução ao Ruby e Ruby on Rails:

O mais difícil ao aprender Rails é instalar Rails no seu computador

Eu posso montar um tutorial, ou você pode seguir o guia do site oficial, ou utilizar um instalador automático… Provavelmente não vai ser tão simples. Não duvide do quão frustrante pode ser para se conseguir instalar o Rails na sua máquina.

Pensando nisso, a sugestão é utilizarmos o Docker como plataforma de execução e instalação, eliminando a necessidade de instalar o Rails. Sendo assim, as únicas instalações necessárias para nosso tutorial serão a do Docker e Docker compose.

Vou ignorar a necessidade de ter um editor de código, git, um SO que preste… Enfim…

Agora, chega de conversinha e bora pra prática.

Criando a imagem base do Ruby

A ideia aqui é iniciar a criação da imagem base para nossa aplicação Rails. Se quiser ir direto ao ponto, pode fazer o checkout da tag 1-create-ruby-image:

git clone -b 1-create-ruby-image <https://github.com/matheuslemke/my-book-shelf>

1. Criar o diretório para nossa aplicação

mkdir my-book-shelf

2. Criar o Dockerfile

Esse arquivo é o responsável pela imagem base do Ruby. É a partir dessa imagem que vamos criar um container para rodar nossa aplicação Rails:

cd my-book-shelf

touch Dockerfile

3. Especificar a versão do Ruby no Dockerfile

A imagem do rails no docker hub está depreciada (ou deprecada como escuto por aí nos corredores da Taller). Sendo assim, a imagem que vamos utilizar é a do Ruby na sua versão 3.2.2.

FROM ruby:3.2.2

WORKDIR /usr/src/app

O comando FROM especifica que vamos partir da versão 3.2.2 e WORKDIR será o diretório padrão ao rodar os comandos no futuro container.

4. Criar o docker compose

Com o docker compose podemos rodar aplicações com multi-containers e centralizarmos tudo em um arquivo só. Sem ele, teríamos que rodar a imagem do banco e do app em diferentes arquivos e parâmetros. Sendo assim, dentro da pasta do app:

touch docker-compose.yml

5. Configurar o container usando o docker compose

No arquivo docker-compose.yml inclua o seguinte:

version: '3'

services:
  web:
    build: .
    ports:
      - "3000:3000"
    volumes:
      - .:/usr/src/app

Nesse arquivo estamos especificando um serviço chamado web, que irá ser construído com base no Dockerfile presente no diretório atual, ou seja “.” . Além disso, estamos exportando a porta 3000 e declarando um volume do conteúdo completo do diretório atual.

Criando a aplicação Rails

Com isso, temos preparada uma imagem de um ambiente Ruby para construir nossa aplicação. Vamos usar a api do próprio Rails para criar nosso website, usando o comando rails new.

1. Construir a imagem do Ruby

Vamos rodar o serviço chamado web, que irá construir a imagem do Ruby:

docker compose run --service-ports web bash

O docker compose não expõe as portas caso o parâmetro --service-ports não seja passado. O argumento bash é a instrução para iniciarmos uma sessão no terminal da imagem do Ruby. Assim, o Docker irá iniciar o download da imagem do Ruby para sua máquina, e, se tudo der certo, você estará dentro de um container, rodando a imagem que acabamos de construir.

Se esse é o caso, você pode verificar a versão do Ruby com:

ruby --version

2. Instalar o Rails na imagem

Agora, vamos instalar o Rails nesse container, e, em seguida, verificar se ocorreu tudo certo:

gem install rails
# depois da instalação...
rails --version

Nesse momento, é a hora de usar a api do Rails para criar uma nova aplicação. Para preparar a integração com o postgres, podemos passar um parâmetro da seguinte forma:

3. Criar uma aplicação Rails

rails new . --database=postgresql

Provavelmente, ao rodar esse comando, irá surgir um prompt do Rails perguntando se você deseja sobrescrever o Dockerfile. A resposta é NÃO! Sendo assim, é só negar a sobrescrita e aguardar a criação da aplicação. Vou destacar essa parte porque é importante:

⚠️ NÃO aceite a sobrescrita do Dockerfile!

Depois desse comando, você pode verificar os arquivos e diretórios criados pelo Rails para iniciarmos o desenvolvimento da nossa aplicação. Tá ficando massa!

Facilitando a manutenção

Estamos prontos para iniciar o desenvolvimento… Mas ainda não vimos nenhuma tela. Infelizmente, ainda não configuramos o banco, e podemos verificar que algo está errado se tentarmos abrir a aplicação no browser. Para isso, dentro do container, vamos iniciar o servidor do Rails:

rails s -b 0.0.0.0

Se abrir o browser, deve perceber um erro de conexão com o banco de dados, algo similar a:

ActiveRecord::ConnectionNotEstablished Error
Screenshot da tela de erro ActiveRecord::ConnectionNotEstablished

Isso por que as configurações do banco de dados da aplicação estão apontando para um banco que ainda não existe… Mas por pouco tempo. Vamos trazê-lo à vida daqui a pouco! Antes, vamos para o processo de “jardinagem” e aparar as arestas para nosso desenvolvimento ficar mais fluído.

1. Copiar os arquivos gerados para dentro da imagem

Pressione Ctrl+C para parar o container.

No Dockerfile, incremente as duas linhas com o comando COPY e RUN:

FROM ruby:3.2.2

WORKDIR /usr/src/app

COPY . .
RUN bundle install

O comando COPY vai incluir na imagem todos os arquivos gerados pelo Rails. E o RUN será o responsável por instalar todas as dependências do projeto, basicamente, tudo o que está dentro do Gemfile.

2. Remover imagens e containers desnecessários (opcional)

Esse passo é opcional. É mais uma questão de capricho — chamamos carinhosamente de jardinagem aqui na Taller.

Remova os containers e imagens previamente gerados pela aplicação. Cuidado pra não remover nada que não queira (e isso rola muito). Então, só pra lembrar:

docker ps -a # listar os containers
docker rm CONTAINER_ID # remover o container

docker images # listar as imagens
docker rmi IMAGE_ID # remover a imagem

Eu prefiro sempre fazer isso, principalmente quando uso docker compose. A cada vez que iniciamos os containers com docker compose up novos containers são criados com ids às vezes aleatórios. Então, fica a dica: se não cuidar do jardim dos containers, logo deve criar mato.

3. Iniciar o servidor do Rails automaticamente

Imagine a chatice que seria se tivesse que iniciar o servidor toda vez que iniciar o container. Muita gente culpa o docker, o compose ou até a o rails por isso… Mas não tem nada a ver. O que vamos fazer agora nos garante que, toda vez que iniciar o container, ou seja, quando rodarmos docker compose up podemos ter certeza que o servidor vai iniciar automaticamente.

Além disso, já vamos incluir o serviço do banco de dados, preparando o “jardim” para o próximo passo. Seu docker-compose.yml deve ficar mais ou menos assim:

version: '3'

services:
  db:
    image: postgres
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: password
  web:
    build: .
    ports:
      - "3000:3000"
    volumes:
      - .:/usr/src/app
    command: ["rails", "s", "-b", "0.0.0.0"]
    depends_on:
      - db

O serviço db inclui as configurações do banco postgres (calma que vamos mexer nele agorinha). No serviço web incluímos um command, que é o primeiro comando executado ao iniciar o container. Também a propriedade depends_on, que o próprio nome já diz… Com isso, o serviço web não inicia até que o banco de dados esteja pronto.

Bora mexer no banco que tá muita conversinha isso aqui.

Configurando o banco de dados

1. Especificar as credenciais

No arquivo config/database.yml, na configuração default, vamos incluir o seguinte:

default: &default
  adapter: postgresql
  encoding: unicode
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  host: db
  username: postgres
  password: password

Os parâmetros host, username e password podem variar. Mas fique tranquilo… O importante aqui é as credenciais estarem de acordo com o que especificamos no docker-compose.yml, que é quem levanta nosso banco de dados.

2. Criar o banco de dados

Bora rodar essa parada e ver a mágica acontecer:

docker compose up

Esse simples comando vai baixar a imagem do postgres, iniciar o serviço do banco de dados, instalar as dependências do projeto e iniciar o servidor rails na porta 3000… Pense de bão piá do céu!

Agora, em um outro terminal, vamos criar o banco de dados especificado no arquivo config/database.yml:

docker compose run web rake db:create

Aqui, basicamente, vamos rodar o serviço web com o comando rake db:create. Esse comando conecta no serviço do postgres e cria um banco de dados de maneira automáticamágica. Esse utilitário do Rails é poderosíssimo e garanto que vamos usá-lo muito ainda nessa jornada.

Abra no browser o endereço localhost:3000 e agora sim devemos ter a aplicação rodando perfeitamente:

Tela de instalação inicial do Ruby on Rails
Tela de instalação inicial do Ruby on Rails

Próximos passos

Depois da instalação, agora é mexer no código!

Essa estante de livros ainda nem nasceu e já deu pra aprender bastante coisa. No próximo capítulo vamos meter a cara no Rails e conversar sobre modelagem, MVC, convenções, etc. Vai ser massa! Não tenho dúvidas.

Se quiser partir de onde paramos, é só fazer o clone da branch na tag 2-config-database-rails-app:


git clone -b 2-config-database-rails-app <https://github.com/matheuslemke/my-book-shelf>

# ou se já tiver a branch aí:
git switch 2-config-database-rails-app --detach

Qualquer feedback pode deixar nos comentários. Bora trocar ideia. E pra quem ficou até aqui, na seção de referências vou incluir uma recomendação de onde aprender Rails em 6 sites totalmente free.

Tmj.

Referências