Personalizando e Estendendo Rails

Rails é conhecido por ser um framework "opinativo" - ele oferece respostas para quase todas as questões sobre construção de aplicações web modernas. Mas e se você precisar fazer as coisas de forma diferente? Neste tutorial prático, vamos explorar quatro formas de personalizar o Rails para atender às suas necessidades específicas.

A Flexibilidade do Rails Moderno

Nos primeiros dias do Rails, personalizar o framework era difícil ou impossível. A partir do Rails 3, muito esforço foi dedicado a torná-lo mais customizável. Com o Rails 7, desenvolvedores têm a flexibilidade de usar as ferramentas que preferem ou que funcionam da maneira que desejam trabalhar.

Vamos explorar quatro substituições importantes: Web Components em vez de Stimulus, RSpec em vez do MiniTest padrão, Slim em vez de ERB, e gerenciamento de CSS via Webpack. O melhor de tudo: você não precisa jogar fora as partes que funcionam para usar alternativas.

1. Criando um Web Component Reutilizável

Web Components são uma forma padrão da indústria de estender o próprio HTML para implementar comportamentos e apresentações customizadas. Vamos criar um componente que exibe a hora atual usando a biblioteca lit.

Instalando e Configurando

Primeiro, "fixamos" o pacote lit na nossa aplicação:

> bin/importmap pin lit
# Pinning "lit" to https://.../index.js
# Pinning "@lit/reactive-element" to https://.../reactive-element.js
# Pinning "lit-element/lit-element.js" to https://.../lit-element.js

Implementando o Componente

Crie o diretório app/javascript/elements e um arquivo current-time.js com o seguinte conteúdo:

import {html, css, LitElement} from 'lit';

class HoraAtual extends LitElement {
  static styles = css`span { color: blue }`;
  
  render() {
    return html`${new Date().toLocaleTimeString()}`;
  }
}

customElements.define('hora-atual', HoraAtual);

Este código importa três propriedades do pacote lit e define uma classe que estende LitElement, definindo um estilo com escopo apenas para este elemento e uma função render que retorna um fragmento HTML.

Registrando o Componente

Adicione uma única linha ao arquivo app/javascript/application.js:

// Configure your import map in config/importmap.rb
import "@hotwired/turbo-rails"
import "controllers"
import "./elements/current-time.js"

Agora você pode usar o componente em qualquer template HTML:

<hora-atual>hora-atual>

2. Testando com RSpec

RSpec é uma alternativa ao MiniTest que o Rails usa por padrão. É diferente em quase todos os aspectos, e muitos desenvolvedores o preferem por sua sintaxe legível que se assemelha ao inglês natural.

Instalação e Configuração

Adicione o rspec-rails ao seu Gemfile nos grupos de desenvolvimento e teste:

group :development, :test do
  gem 'rspec-rails'
end

Após executar bundle install, use o gerador para configurar o RSpec:

> bin/rails generate rspec:install
create .rspec
create spec
create spec/spec_helper.rb
create spec/rails_helper.rb

Exemplo: Testando o Model Cart

Vamos comparar um teste tradicional do Rails com sua versão em RSpec. Primeiro, o teste original:

class CarrinhoTest < ActiveSupport::TestCase
  def setup
    @carrinho = Carrinho.create
    @livro_um = produtos(:ruby)
    @livro_dois = produtos(:dois)
  end
  
  test "adicionar produtos únicos" do
    @carrinho.adicionar_produto(@livro_um).save!
    @carrinho.adicionar_produto(@livro_dois).save!
    assert_equal 2, @carrinho.itens_linha.size
  end
end

Agora, a versão em RSpec:

RSpec.describe Carrinho, type: :model do
  fixtures :produtos
  subject(:carrinho) { Carrinho.new }
  let(:livro_um) { produtos(:ruby) }
  let(:livro_dois) { produtos(:dois) }

  describe "#adicionar_produto" do
    context "ao adicionar produtos únicos" do
      before do
        carrinho.adicionar_produto(livro_um).save!
        carrinho.adicionar_produto(livro_dois).save!
      end

      it "tem dois itens de linha" do
        expect(carrinho.itens_linha.size).to eq(2)
      end
    end
  end
end

Estrutura e Convenções do RSpec

O RSpec usa algumas convenções importantes:

  • subject() - declara o objeto foco do teste
  • let() - declara dados auxiliares
  • describe() - agrupa testes relacionados a um método
  • context() - define contextos específicos de teste
  • it() - define um exemplo (teste individual)
  • before() - código de configuração executado antes dos testes

A sintaxe de expectativa do RSpec é bem diferente:

# Sintaxe RSpec
expect(valor_atual).to eq(valor_esperado)

Documentação Legível

Um benefício interessante do RSpec é que você pode gerar documentação legível diretamente dos seus testes:

> bin/rails spec SPEC_OPTS="--format=doc"

Carrinho
  #adicionar_produto
    ao adicionar produtos únicos
      tem dois itens de linha
      tem um preço total da soma dos dois itens

3. Templates HTML com Slim

Slim é uma linguagem de templates que pode substituir o ERB. Foi projetada para exigir muito menos código para atingir os mesmos resultados, usando uma estrutura aninhada em vez de tags HTML.

Comparação: ERB vs Slim

Aqui está o mesmo código em ERB:

<h2><%= t('.titulo') %>h2>
<table>
  <%= render(carrinho.itens_linha) %>
  <tr class="linha_total">
    <td colspan="2">Totaltd>
    <td><%= number_to_currency(carrinho.preco_total) %>td>
  tr>
table>

E em Slim:

h2
  = t('.titulo')
table
  = render(carrinho.itens_linha)
  tr.linha_total
    td colspan=2
      Total
    td
      = number_to_currency(carrinho.preco_total)

Sintaxe do Slim

O Slim trata cada linha como uma tag HTML de abertura, e qualquer coisa indentada sob essa linha será renderizada dentro da tag. Aqui estão os elementos principais:

  • = - para acessar helpers e variáveis de instância
  • - - para executar lógica Ruby (loops, condicionais)
  • . - para adicionar classes CSS

Exemplos práticos:

/ Loop sobre produtos
ul
  - @produtos.each do |produto|
    li
      - if produto.disponivel?
        = link_to produto.nome, produto_path(produto)
      - else
        = "#{produto.nome} fora de estoque"

/ Classes CSS
h1.titulo Este título tem a classe "titulo"!

/ Div implícita com classe
.login-form
  input type=text name=usuario
  input type=password name=senha

Instalação

Instalar o Slim é simples:

bundle add slim-rails

Após a instalação, seu aplicativo Rails renderizará automaticamente arquivos terminados em .slim como templates Slim. Os geradores Rails também criarão arquivos Slim em vez de ERB automaticamente.

Outras Customizações Possíveis

O ecossistema Rails está repleto de plugins e melhorias para atender necessidades comuns:

  • Kaminari - paginação para navegar por centenas ou milhares de registros
  • Ransack e Searchkick - formas avançadas de pesquisar seu banco de dados
  • CarrierWave - upload de arquivos simplificado
  • RuboCop - verificação de estilo de código consistente
  • Brakeman - verificação de vulnerabilidades de segurança comuns

Conclusão: Encontrando o Equilíbrio

Customizar as "bordas" do Rails - como CSS, templates HTML e testes - tende a ser mais direto e oferece mais opções. Customizar os componentes internos do Rails, como substituir completamente o Active Record, é mais difícil e você estaria desistindo de muitos benefícios.

O acoplamento forte geralmente é visto como um problema, mas é justamente esse acoplamento que permite que você seja tão produtivo usando Rails. Quanto mais você transforma seu aplicativo Rails em uma montagem fracamente acoplada de bibliotecas não relacionadas, mais trabal

Comentários (0)

Nenhum comentário:

Postar um comentário