Olá, dev!
Algumas pessoas podem te aconselhar a não utilizar os geradores automáticos do Rails para a criação de models, controllers e afins. "Faça manualmente", dizem eles. Eu não concordo com essa afirmação! Meu conselho é que você descubra profundamente como eles funcionam e a partir daí, decida se vale, ou não, a pena utilizar.
Neste artigo, vou falar sobre o gerador mais utilizado, e também o mais útil: o gerador de models. Tenho certeza que após esse artigo você vai mudar de ideia e começará a utilizar esse recurso tão prático, caso ainda não o utilize. Afinal, ele ajuda você a economizar tempo, aumentar sua produtividade, e tornar o processo de criação mais consistente.
Vamos lá!
Uso básico
rails g model product name
O comando acima é responsável por criar o model de produtos com um campo de nome, por convenção o tipo será string. Serão gerados também uma migration, responsável pela criação da tabela no banco de dados, um arquivo de teste unitário e um de factory, caso a estrutura de testes esteja habilitada em seu projeto.
Considerando a convenção aplicada pelo Rails, a tabela responsável por armazenar os dados dessa classe será products, que é de acordo com a convenção, o plural do nome de nossa classe.
É possível adicionar mais atributos? Claro que sim! Você pode fazer da seguinte forma:
rails g model product name upc_code description
Usando o comando acima, será criado juntamente com o model 3 campos do tipo string: name, upc_code e description. Você pode adicionar quantos campos precisar, basta apenas separar cada um deles por espaço.
É possível fazer mais do que isso! Podemos definir tipos para cada atributo de nossa classe. Veja a seguir:
rails g model product name unit_value:float available:boolean
Conforme ilustrado pelo exemplo acima, é necessário separar o atributo, e seu respectivo tipo, com dois pontos (:). Por padrão, o Rails é capaz de reconhecer os seguintes tipos:
- integer
- primary_key
- decimal
- float
- boolean
- binary
- string
- text
- date
- time
- datetime
- timestamp
Além das opções acima, é possível definir outros tipos aos seus atributos, como json ou uuid. Isso vai depender do adapter utilizado por sua aplicação. Como isso é um assunto todo à parte prefiro deixar para outro post. Mas é muito importante saber que isso é possível.
Relacionamentos
Vamos considerar que nossa classe de produtos possui uma categoria vinculada. É possível adicionar um relacionamento do tipo belongs_to utilizando o comando:
rails g model product category:references name
Este comando irá gerar a tabela de produtos com o campo inteiro category_id com um índice, e uma chave estrangeira vinculada.
class CreateProducts < ActiveRecord::Migration
def change
create_table :products do |t|
t.references :category
t.string :name
t.timestamps
end
end
end
Para um relacionamento polimórfico utilize a sintaxe abaixo:
rails generate model product supplier:references{polymorphic}
Herança e escopos
Você também pode passar a opção --parent
no gerador. Ele herdará da classe definida, gerando assim um single table inheritance. A ideia de uma herança de tabela única parte do princípio que podemos utilizar uma única tabela para armazenar os dados de diferentes classes. Cada classe possui ações diferentes, de acordo com o tipo do objeto.
rails g model book --parent product
Este comando irá gerar uma classe igual a essa:
class Book < Product
end
Dentre as diversas opções que esse recurso nos permite, você pode criar um model dentro de algum escopo, ou namespace, passando algo como módulo/classe
, apenas separando os nomes por uma barra, como podemos ver à seguir:
rails g model financial/account
Inserido o comando, o Rails irá criar a classe de model e um arquivo relacionado ao módulo. A classe Financial::Account
será gerada no arquivo app/models/financial/account.rb
, e um arquivo para armazenar as configurações relacionadas ao módulo, ou namespace, será gerado no arquivo app/models/financial.rb
. O conteúdo dos respectivos arquivos será similar ao apresentado abaixo:
module Financial
class Account < ApplicationRecord
end
end
module Financial
def self.table_name_prefix
'financial_'
end
end
No banco de dados, esse escopo será apresentado na forma de prefixo. A tabela responsável por armazenar os dados de contas, dentro do módulo financeiro de nosso sistema de exemplo, será chamada financial_accounts
. Esse é um recurso indispensável para a organização de sistema que possuam mais de um módulo, ou domínio.
Uso avançado
Mas não param por aí as possibilidades que fazem o processo de geração de models dentro de uma aplicação Rails ser menos monótono e mais produtivo.
Você deve saber que um índice de busca pode melhorar significativamente o desempenho de consultas no banco de dados. Há também uma forma de cria-los juntamente com nosso model.
rails g model user email:string:index birth:date:index
E um índice de unicidade? Também é possível gerar!
rails g model user email:string:uniq
Até mesmo podemos delimitar o tamanho de nossos campos. Vamos considerar em nosso exemplo que o CPF de cada usuário ficará limitado a 11 caracteres.
rails g model user cpf:string{11}
Existe uma exceção! Caso você esteja definindo um campo do tipo decimal você deverá utilizar aspas simples durante a declaração. Isso acontece devido as opções de precisão e escala necessárias para esse tipo de campo.
É vital que você siga essa orientação. Caso contrário, o resultado será frustrante. Caso queira entender melhor, a explicação completa deste caso está no repositório oficial do Rails, nesse Pull Request aqui.
Nosso campo de valor unitário possuirá o tamanho (precisão) de 10 dígitos, sendo duas casas decimais de escala.
rails g model product name 'unit_value:decimal{10,2}'
Você ainda pode combinar algumas opções. Vamos aplicar ao CPF um índice de unicidade, impedindo que mais de um usuário possa criado no banco de dados com os mesmos dados.
rails g model user cpf:string{11}:uniq email:string{100}
Como você pode ver, existem muitos recursos úteis no gerador de models do Rails que podem diminuir o tempo de desenvolvimento.
Até a próxima!