Uma aplicação Ruby simples a partir do zero com Active Record
Damian Watroba
Software Engineer
O MVC é um padrão de design que divide as responsabilidades de uma aplicação para facilitar a sua movimentação. O Rails segue esse padrão de design por convenção.
Gosto de trabalhar com Carris porque posso criar fácil e rapidamente uma aplicação que funcione e mostrá-la ao mundo ou apenas aos meus amigos. No entanto, há tipos de aplicações que não precisam de uma estrutura tão grande como Carris e todas as suas funcionalidades.
Pode acontecer que a nossa aplicação necessite apenas de M (Modelo) de todo o padrão MVC Modelo-Controlador. Vale a pena iniciar uma projeto em Carris se soubermos que a parte V-C (View-Controller) não será necessária?
É bom saber que Registo ativo O Active Model, o Action Pack e o Action View, que são responsáveis pelo MVC, podem ser utilizados independentemente fora do Carris. Isto permite nós para criar um simples Rubi aplicação que tem uma ligação à base de dados e desenvolvê-la sem as desnecessárias código e bibliotecas que obteríamos num pacote ao executar o comando rails new.
Descrevi passo a passo como conseguir isto e pode encontrar todo o código no GitHub. O link está no final deste artigo.
Estrutura
Para iniciar o nosso projeto, não precisamos de muito. Vamos começar por criar um ficheiro Ficheiro Gemfile onde adicionamos as gemas que precisamos para trabalhar na aplicação, juntamente com a versão do Rubi que iremos utilizar.
Uma opção README.md serve para descrever como funciona a nossa aplicação e como continuar a trabalhar nela, tanto para nós como para outros programadores que queiram desenvolver o projeto connosco no futuro.
cat README.md
Aplicação #
O QUE FAZER: Eliminar isto e o texto acima, e descrever a sua aplicação
aplicação diretório com aplicação.rb que será responsável pela configuração e carregamento das bibliotecas e ficheiros que iremos adicionar à nossa aplicação. Lembre-se de executar instalação do pacote para gerar o Gemfile.lock. A estrutura da nossa aplicação nesta fase deve ter o seguinte aspeto:
Com esta estrutura preparada, podemos considerar qual o motor de base de dados a escolher e configurar. Para este artigo, escolhi o PostgresQL, com o qual tenho mais experiência. Ele também pode ser MySQL ou SQlite3, ou qualquer outro motor que trabalhe com Registo ativo. Ao escolher a tecnologia, é bom guiar-se pelo objetivo da aplicação, para que será utilizada e qual será a sua finalidade.
Para uma configuração rápida e simples da base de dados, utilizei doca e docker-compose. Não pretendo entrar em pormenores sobre a configuração destas ferramentas, os seus prós e contras, mas se nunca utilizou o docker antes, recomendo que consulte a documentação oficial do Docker e Docker Compose para mais informações.
Também precisaremos de adicionar ao nosso Ficheiro Gemfile
gem 'pg'
e para o nosso aplicação.rb ficheiro
# app/application.rb
require 'pg'
módulo Aplicação
class Error < StandardError; end
# O seu código vai para aqui...
end
Migrações autónomas, Rake
O próximo passo na configuração da nossa aplicação é adicionar a variável migrações autónomas e ancinho o que nos permitirá gerir as nossas migrações tal como no Rails e ter acesso aos comandos rake db:.
Atualização Ficheiro Gemfile com as jóias necessárias e fazer um instalação do pacote
Gema # utilizada em aplicações não-rails e não-ruby
gem 'standalone_migrations'
# standalone_migrations precisa do rake para ser capaz de criar migrações e executá-las, como no Rails
gem 'rake'
# Gem necessária para carregar variáveis de ambiente
gem 'dotenv'
Vamos adicionar um Rakefile para o nosso projeto no diretório raiz, onde iremos carregar dotenv e migrações autónomas que adicionámos anteriormente
Com o Rakefile configurado desta forma, podemos verificar se o nosso ancinho está a funcionar utilizando o rake -T que deve retornar uma lista de comandos disponíveis na nossa aplicação.
Antes de rake db:createPara isso, ainda precisamos de um ficheiro de configuração no nosso projeto para nos ligarmos à instância Postgres. Para fazer isso, precisamos criar um diretório db junto com um arquivo config.yml que deve ser parecido com o ficheiro abaixo:
# db/config.yml
predefinição: &default
adaptador: postgresql
codificação: unicode
pool:
base de dados:
nome de utilizador:
password:
anfitrião:
port:
desenvolvimento:
<<: *default
teste:
<<: *default
staging:
<<: *default
produção:
<<: *default
Como pode ver, utilizei variáveis de ambiente para configurar a ligação ao nosso Postgres, onde vamos guardar dados sensíveis que não devem estar no repositório. Para isso, utilizei a variável gem dotenvque também foi acrescentado no Rakefile juntamente com migrações autónomas. Se estivermos a utilizar o Git para gerir o controlo de versões da nossa aplicação, lembremo-nos de adicionar um .gitignore onde iremos desativar a possibilidade de rastrear o ficheiro .env do nosso projeto.
# .gitignore
.env*
!.env.exemplo
e adicionar um.env que contém o ficheiro ENV corretamente configurado
Nesta fase, devemos ser capazes de executar o rake db:create que criará a base de dados
Vamos tentar adicionar uma nova migração através de rake db:new_migration name=, onde criamos um postos mesa com um :título coluna
# frozen_string_literal: true
classe CreatePosts < ActiveRecord::Migration[6.0]
def change
criar_tabela :posts do |t|
t.string :título
fim
fim
fim
Deves notar que o db/migrate foi automaticamente adicionado e o diretório schema.rb foi criado após uma migração bem sucedida. Atualmente, a estrutura do nosso projeto é a seguinte
Por último, mas não menos importante, outro passo na criação da nossa aplicação é adicionar registo ativo e sua configuração. Para isso, vamos precisar de atualizar o nosso Gemfile com mais 3 gems:
Porque acrescentamos erva e ymal é explicado abaixo nos comentários. Toda a registo_activo configuração estará no ficheiro app/application.rb ficheiro.
Vamos ver o que acontece aqui, um por um:
# frozen_string_literal: true
# Se quisermos executar a aplicação em ambientes diferentes,
# por exemplo, teste ou produção, é bom definir o valor ENVIRONMENT
# no início, que é obtido a partir da variável de ambiente
# ou `development` por padrão.
ENV['ENVIRONMENT'] ||= 'development'
# Para usar as gems adicionadas, precisamos carregá-las usando o método Kernel#require,
# que carrega o ficheiro ou biblioteca passado como parâmetro
require 'pg'
require 'active_record'
require 'dotenv'
require 'yaml'
requerer 'erb'
# Por padrão o Dotenv.load para carregar variáveis de ambiente chega até
# para o arquivo `.env`, então se quisermos usar outros ambientes, vale a pena
# estender isso para o método abaixo, que irá primeiro para um conjunto de desenvolvimento
# ambiente procurará por um arquivo terminado em `.env.development.local`,
# depois `.env.development` e finalmente `.env`.
Dotenv.load(".env.#{ENV.fetch('ENVIRONMENT')}.local", ".env.#{ENV.fetch('ENVIRONMENT')}", '.env')
# Método necessário para carregar as definições da base de dados
def db_configuration
# O método abaixo devolve o caminho para o ficheiro com a nossa configuração
db_configuration_file_path = File.join(File.expand_path('..', __dir__), 'db', 'config.yml')
# Tendo o caminho para o ficheiro, podemos ler os seus valores. Como o ficheiro config.yml
# contém variáveis de ambiente e, como você deve ter notado,
# a sintaxe erb , nós também precisamos usar a gem erb. Sem isso,
# os valores das variáveis não serão lidos corretamente e o activerecord
# não será capaz de se conectar ao postgres. O método a seguir retornará
# a configuração como uma string
db_configuration_result = ERB.new(File.read(db_configuration_file_path)).result
# Usando a gem `yaml` adicionada anteriormente, podemos carregar nossa configuração com segurança
YAML.safe_load(db_configuration_result, aliases: true)
fim
# Finalmente, precisamos criar uma conexão entre o activerecord e o postgres
# usando o método `establish_connection
ActiveRecord::Base.establish_connection(db_configuration[ENV['ENVIRONMENT']])
módulo Application
class Error < StandardError; end
# O teu código vai para aqui...
end
Já temos as configurações, por isso podemos adicionar o modelo Post no nosso rubi app.
`├── app`
`│ └─── modelos`
`│ └─── post.rb`
app/models/post.rb
# frozen_string_literal: true
class Post < ActiveRecord::Base;end
e lembre-se de carregar o ficheiro em aplicação.rb
requerer 'app/models/post'
Além disso, lembre-se de adicionar require 'app/runner' para app/application.rb
Se quisermos adicionar novos ficheiros à nossa aplicação, serviços, mais modelos, temos de os carregar em aplicação.rb.
RESUMO
Atualmente, a nossa aplicação ruby está pronta para continuar. Nós configurámos:
ligação à base de dados,
Registo ativo,
Migrações autónomas com rake
Como se pode ver, nem sempre é necessário utilizar carris novo. Desta forma, evitamos código desnecessário na nossa aplicação que não é utilizado. Temos mais controlo sobre o desenvolvimento da nossa aplicação. Podemos adicionar mais bibliotecas e lógica comercial ao longo do tempo. Podemos utilizar esta aplicação configurada para criar um crawler ou scraper, ligar a uma API externa a partir da qual iremos obter informações e armazená-las na nossa própria base de dados ou carregar ficheiros e extrair informações interessantes dos mesmos. Desejo-vos boa sorte para o desenvolvimento das vossas próprias aplicações!
BÓNUS
A nossa aplicação também precisa de ser iniciada de alguma forma. Podemos fazê-lo de várias formas, por exemplo, a partir do terminal. Podemos criar um exe/app que carregará a lógica da nossa aplicação a partir do ficheiro 'app/application' e executar a nossa aplicação através do ficheiro Corredor adicionado ao diretório da aplicação.