O ActiveRecord é uma espécie de ORM (Object Relation Mapping), isto significa que ele é responsável por mapear classes da aplicação para tabelas do banco de dados. Esse módulo representa o Modelo na arquitetura Model, View e Control, que é responsável pela lógica do sistema e pela representação de dados. Além disso, ele facilita a manipulação de objetos persistentes de uma tabela, sem que o desenvolvedor escreva uma linha de SQL sequer. Além disso, ele também fornece recursos para que um modelo seja validado antes de ser persistido em uma base de dados. Isso tudo escrevendo pouca ou nenhuma configuração, já que o framework Rails favorece a convenção sob a configuração.
A fim de seguir os exemplos apresentados durante esse artigo, é necessário que o leitor possua o Ruby e o Rails instalado na sua máquina. O tópico seguinte dá uma explicação rápida de como configurar o ambiente de desenvolvimento nos sistemas operacionais mais comumente usados.
Instalação
O primeiro passo para a configuração do ambiente é a instalação ao Ruby. Para ambiente Debian ou Ubuntu o comando apresentado a seguir deverá ser executado no terminal.
sudo apt-get install ruby-full
Já para ambientes como os sistemas operacionais Fedora e CentOS, o comando de instalação será semelhante ao mostrado a seguir:
sudo yum install ruby
Após o término da instalação da linguagem é possível ver se tudo aconteceu corretamente executando o comando apresentado a seguir, que deve retornar a impressão da versão da linguagem:
ruby --version
ruby 2.1.5p273 (2014-11-13) [x86_64-linux-gnu]
ou apenas
ruby -v
ruby 2.1.5p273 (2014-11-13) [x86_64-linux-gnu]
O passo seguinte é instalar o framework Rails, que nada mais é do que uma gem (semelhantes aos .jar's do Java) ou biblioteca. Utilize o comando a seguir para instalação do framework:
gem install rails
Para o sistema operacional Windows as ferramentas RubyInstaller e RailsInstaller facilitam a configuração do ambiente, então basta fazer o download da versão desejada e seguir a instalação padrão apresentada no setup.
Classes Modelos
As classes que representam a camada de negócio de uma aplicação Rails ficam localizadas no diretório app/models, que é gerado automaticamente durante a criação da aplicação. Para que uma classe tenha acesso aos recursos que o ActiveRecord fornece é necessário que ela estenda a classe Base desse módulo como mostra o código a seguir:
class Produto < ActiveRecord::Base
end
O framework automaticamente associaria essa classe com uma tabela no banco de dados chamada produtos e todas as colunas dela funcionariam como atributos de instância da classe Produto. Isso será explanado com exemplos logo a frente.
Criação de Aplicação para Exemplos
Para executar alguns testes com o ActiveRecord essa sessão apresenta a criação de uma aplicação de exemplo. Começaremos com a escolha de um diretório: navegue até ele pelo terminal ou prompt de comando e depois de acessado basta digitar o comando apresentado a seguir:
~/RailsProjects$ rails new testes_rails
Esse comando faz uso do gerador do framework para construir toda a estrutura inicial da aplicação.
O resultado da execução desse comando deve ser semelhante a saída apresentada na Listagem 1.
Listagem 1. Saída ou resultado do comando de criação da aplicação.
create
create README.rdoc
create Rakefile
create config.ru
create .gitignore
create Gemfile
create app
create app/assets/javascripts/application.js
create app/assets/stylesheets/application.css
create app/controllers/application_controller.rb
create app/helpers/application_helper.rb
create app/views/layouts/application.html.erb
create app/assets/images/.keep
create app/mailers/.keep
create app/models/.keep
create app/controllers/concerns/.keep
create app/models/concerns/.keep
[…]
run bundle install
Resolving dependencies...
Bundle complete! 12 Gemfile dependencies, 54 gems now installed.
Criação do Primeiro Modelo
Agora já é possível construir uma classe de modelo e conectá-la a uma tabela no banco de dados. Para isso basta criar um arquivo dentro do diretório app/models com o nome da classe que desejar.
Existem alguns detalhes importantes para lembrar referente a nomenclaturas:
- A extensão do arquivo deve ser “.rb”;
- O nome do arquivo e da classe devem estar no singular;
- O nome do arquivo deve estar em letras minúsculas e, caso seja uma palavra composta, deve estar separada por “_” underscore ou underline. Por exemplo “nota fiscal” ficaria “nota_fiscal.rb”
- O nome da classe deve iniciar com letra maiúscula e as subsequentes devem ser minúsculas. Caso se trate de uma palavra composta cada letra inicial de palavras subsequentes deve estar também em caixa alta. Por exemplo “conta corrente” ficaria “ContaCorrente”.
O código a seguir apresenta a criação de um modelo na aplicação de exemplo construída anteriormente:
class Usuario < ActiveRecord::Base
end
Note que não há nada de extraordinário nela, apenas uma classe que estende de ActiveRecord::Base, que tem por objetivo estar associada ou representar uma tabela do banco de dados.
A classe Usuario não está (pelo menos ainda não) ligada a nenhuma estrutura do banco. Para fazer essa ligação basta criar uma tabela seguindo as convenções de nomeação do Rails. O framework vai pluralizar o nome de classe e procurar na base de dados uma relação com esse nome no plural. Isso significa que a tabela correspondente a classe Usuario teria o nome usuarios.
Porém, antes de criar essa tabela é importante atentar para um detalhe: o framework Rails vai pluralizar o nome das classes de acordo com as regras do idioma inglês, por exemplo a palavra “autor” seria pluralizada como “autors” e não “autores”, ou “qualificação” seria pluralizada como “qualificaçãos” e não “qualificações”.
É possível dizer ao Rails como ele deve pluralizar as palavras por meio do arquivo config/initializers/inflections.rb. Veja no bloco de código apresentado na Listagem 2 a mudança dessa regra para as palavras “autor” e “qualificação” que citamos. Perceba que para isso apenas é necessário passar a palavra no singular seguida de como se deseja pluralizar para o método inflect.irregular.
Listagem 2. Alteração da pluralização das palavras “autor” e “qualificacao”.
ActiveSupport::Inflector.inflections(:en) do |inflect|
inflect.irregular 'qualificacao', 'qualificacoes'
inflect.irregular 'autor', 'autores'
end
No caso da classe Usuario não será necessário alterar a regra de pluralização, então para ligar essa classe à base de dados basta simplesmente criar uma tabela chamada usuarios.
Antes disso precisamos que a aplicação tenha um banco de dados e o código a seguir apresenta o comando Rails para essa tarefa:
~/RailsProjects/testes_rails$ rake db:create
Note que esse comando deve ser executado dentro do diretório da aplicação e ele não imprimirá nada no terminal.
A fim de que o desenvolvedor possa alterar as estruturas do banco de dados da aplicação, o Rails oferece um console que permite manipulá-lo. Para isso basta digitar o comando rails dbconsole dentro do diretório da aplicação. Nesse console é possível executar comandos SQL para fazer consultas na base da aplicação ou para modificar a sua estrutura (criando, excluindo ou alterando tabelas).
Para seguir com os exemplos vamos criar uma tabela chamada usuarios e o Rails automaticamente vai associá-la com a classe Usuario que foi criada. Veja na Listagem 3 o código de criação para essa tabela.
Listagem 3. Código SQL de criação da tabela usuarios executado pelo dbconsole do Rails.
sqlite> CREATE TABLE usuarios(
...> id INTEGER PRIMARY KEY AUTOINCREMENT,
...> nome varchar(70),
...> email varchar(70),
...> login varchar(30),
...> senha varchar(10)
...> );
Após a tabela criada a classe Usuario já está conectada a tabela usuarios. É possível comprovar isso acessando o Rails console, que simula a aplicação sendo executada. Para acessá-lo basta digitar no terminal o comando rails console. Ele permite executar o código ruby inclusive fazendo operações com o banco de dados da aplicação.
Veja na Listagem 4 que a classe usuario, após a criação de sua respectiva tabela, já possui os métodos para recuperar (get's) e modificar (set's) atributos com os mesmos nomes das colunas.
Listagem 4. Uso dos métodos para recuperar e modificar atributos da classe Usuario.
~/RailsProjects/testes_rails$ rails console
Loading development environment (Rails 4.2.4)
irb(main):001:0> usuario1 = Usuario.new
irb(main):002:0> usuario1.nome = "João da Silva"
=> "João da Silva"
irb(main):003:0> usuario1.email = "joao@silva.com"
=> "joao@silva.com"
irb(main):004:0> usuario1.login = "joao.silva"
irb(main):005:0> usuario1.senha = "12345"
=> "12345"
irb(main):006:0> puts "#{usuario1.nome} - #{usuario1.email}"
=>João da Silva – joao@silva.com
Métodos disponíveis no ActiveRecord
Quando uma classe estende ActiveRecord::Base muitos recursos ficam disponíveis, inclusive métodos para persistência, consulta e alterações de informações no banco de dados. Usaremos o rails console para testar alguns dos principais métodos disponíveis.
Save
Esse método salva ou persiste o objeto no banco de dados. Veja no bloco de código apresentado na Listagem 5 o preenchimento dos dados de um usuário e em seguida o uso do método save para armazenar o objeto no banco. Note que ao final o método retornou true, indicando que o objeto foi persistido com sucesso.
Listagem 5. Exemplo de uso do método save.
~/RailsProjects/testes_rails$ rails console
Loading development environment (Rails 4.2.4)
irb(main):001:0> usuario1 = Usuario.new
irb(main):002:0> usuario1.nome = "José da Silva Leite"
=> "José da Silva Leite"
irb(main):003:0> email = "jose@silva_leite.com"
=> "jose@silva_leite.com"
irb(main):004:0> usuario1.login = "jose.silva"
=> "jose.silva"
irb(main):005:0> usuario1.senha = "12345"
=> "12345"
irb(main):006:0> usuario1.save
=>true
Perceba que nenhuma linha de SQL foi necessária para inserir os dados do objeto no banco de dados, pois o método save faz esse trabalho pelo desenvolvedor. Veja na Listagem 6 o comando SQL que a chamada ao método save gerou.
Listagem 6. SQL gerado pela chamada ao método save.
(0.3ms) begin transaction
SQL (18.3ms) INSERT INTO "usuarios" ("nome", "email", "login", "senha") VALUES (?, ?, ?) [["nome", "José da Silva Leite"], ["email", "jose@silva_leite.com"], ["login", "jose.silva"], ["senha", "12345"]]
(75.1ms) commit transaction
Create
É possível instanciar um objeto e automaticamente persisti-lo no banco de dados com o método create. Ele recebe um hash com o nome do atributo seguido do valor correspondente e salva o objeto no banco. Veja a seguir a sintaxe de chamada do método:
NomeDaClasse.create(atributo1: “valor1”, atributo2: “valor2”, atributo3: “valor3”)
Em seguida note o exemplo de uso desse método na Listagem 7.
Listagem 7. Exemplo de uso do método create.
~/RailsProjects/testes_rails$ rails console
Loading development environment (Rails 4.2.4)
irb(main):001:0> Usuario.create(nome: "Silva Souza Oliveira", email: "silva@souza_oliveira.com", login: "silva.souza", senha: "12345")
(0.2ms) begin transaction
O código SQL equivalente é:
SQL (0.5ms) INSERT INTO "usuarios" ("nome", "email", "login", "senha") VALUES (?, ?, ?, ?) [["nome", "Silva Souza Oliveira"], ["email", "silva@souza_oliveira.com"], ["login", "silva.souza"], ["senha", "12345"]]
(104.6ms) commit transaction
All
Esse método recupera todos os registros de uma tabela. Veja na Listagem 8 o seu uso para mostrar o nome seguido do e-mail de cada um dos usuários que já estão armazenados na tabela.
Listagem 8. Uso do método all para mostrar o nome e o e-mail dos usuários cadastrados.
~/RailsProjects/testes_rails$ rails console
Loading development environment (Rails 4.2.4)
irb(main):001:0> Usuario.all.each do |u|
irb(main):002:1* puts "#{u.nome} - #{u.email}"
irb(main):003:1> end
O código SQL equivalente é:
Usuario Load (1.9ms) SELECT "usuarios".* FROM "usuarios"
José da Silva Leite - jose@silva_leite.com
Silva Souza Oliveira - silva@souza_oliveira.com
Soares da Silva Souza – soares@silva_souza.com
First e Last
Esses métodos quando chamados sem parâmetro retornam o primeiro e o último registro encontrado na tabela, respectivamente, conforme mostra a Listagem 9.
Listagem 9. Uso dos métodos first e last.
~/RailsProjects/testes_rails$ rails console
Loading development environment (Rails 4.2.4)
irb(main):001:0> Usuario.first
O código SQL equivalente é:
Usuario Load (0.2ms) SELECT "usuarios".* FROM "usuarios" ORDER BY "usuarios"."id" ASC LIMIT 1
=> #<Usuario id: 1, nome: "José da Silva Leite", email: nil, login: "jose.silva", senha: "12345">
irb(main):002:0> Usuario.last
Usuario Load (0.2ms) SELECT "usuarios".* FROM "usuarios" ORDER BY "usuarios"."id" DESC LIMIT 1
=> #<Usuario id: 3, nome: "Soares da Silva Souza", email: "soares@silva_souza.com", login: "soares.silva", senha: "12345">
Também é possível passar um parâmetro para esses métodos informando quantos registros devem ser recuperados. Por exemplo, Usuario.first(3) retornaria os três primeiros usuários e Usuario.last(3) os três últimos registros.
Find_by
Esse método retorna o primeiro registro em que os valores dos atributos são idênticos aos passados nos parâmetros. Por exemplo, a Listagem 10 procura por um usuário com login igual à “jose.silva”.
Listagem 10. Uso do método find_by para buscar um usuário pelo login.
~/RailsProjects/testes_rails$ rails console
Loading development environment (Rails 4.2.4)
irb(main):001:0> Usuario.find_by(login: "jose.silva")
O código SQL equivalente é:
Usuario Load (0.4ms) SELECT "usuarios".* FROM "usuarios" WHERE "usuarios"."login" = ? LIMIT 1 [["login", "jose.silva"]]
=> #<Usuario id: 1, nome: "José da Silva Leite", email: nil, login: "jose.silva", senha: "12345">
Update
Esse método atualiza um ou múltiplos objetos no banco de dados. Para atualizar um único registro basta passar como parâmetro o identificador, seguido dos atributos que se deseja atualizar, como mostra o exemplo da Listagem 11. Note que antes e depois da atualização os dados são mostrados para que se comprove a alteração.
Listagem 11. Exemplo de uso do método update para atualizar um único registro.
~/RailsProjects/testes_rails$ rails console
irb(main):001:0> usuario = Usuario.find_by(id: 1)
Usuario Load (0.3ms) SELECT "usuarios".* FROM "usuarios" WHERE "usuarios"."id" = ? LIMIT 1 [["id", 1]]
irb(main):002:0> puts "#{usuario.login} - #{usuario.senha}"
=>jose.silva - 12345
irb(main):003:0> Usuario.update(1, login: "jose.silva.leite", senha: "54321")
O código SQL equivalente é:
Usuario Load (0.3ms) SELECT "usuarios".* FROM "usuarios" WHERE "usuarios"."id" = ? LIMIT 1 [["id", 1]]
(0.3ms) begin transaction
SQL (0.6ms) UPDATE "usuarios" SET "login" = ?, "senha" = ? WHERE "usuarios"."id" = ? [["login", "jose.silva.leite"], ["senha", "54321"], ["id", 1]]
(357.3ms) commit transaction
irb(main):004:0> usuario = Usuario.find_by(id: 1)
Usuario Load (0.2ms) SELECT "usuarios".* FROM "usuarios" WHERE "usuarios"."id" = ? LIMIT 1 [["id", 1]]
irb(main):005:0> puts "#{usuario.login} - #{usuario.senha}"
jose.silva.leite – 54321
O método update também pode ser usado para atualizar múltiplos registros. Para isso é necessário passar dois hash's: o primeiro contendo os identificadores e o segundo contendo os atributos e seus respectivos valores para alteração, como mostra o exemplo da Listagem 12.
Listagem 12. Uso do método update para atualizar múltiplos registros.
~/RailsProjects/testes_rails$ rails console
irb(main):001:0> usuarios = {1 => {nome: "souza da silva"}, 2 => {nome: "antonio oliveira"}}
irb(main):002:0> Usuario.update(usuarios.keys, usuarios.values)
O código SQL equivalente é
Usuario Load (0.3ms) SELECT "usuarios".* FROM "usuarios" WHERE "usuarios"."id" = ? LIMIT 1 [["id", 1]]
(0.2ms) begin transaction
SQL (0.4ms) UPDATE "usuarios" SET "nome" = ? WHERE "usuarios"."id" = ? [["nome", "souza da silva"], ["id", 1]]
(372.0ms) commit transaction
Usuario Load (0.3ms) SELECT "usuarios".* FROM "usuarios" WHERE "usuarios"."id" = ? LIMIT 1 [["id", 2]]
(0.1ms) begin transaction
SQL (0.3ms) UPDATE "usuarios" SET "nome" = ? WHERE "usuarios"."id" = ? [["nome", "antonio oliveira"], ["id", 2]]
(62.0ms) commit transaction
Destroy
Esse método remove do banco de dados o objeto que foi chamado. Veja na Listagem 13 um exemplo de uso do mesmo.
Listagem 13. Exemplo de uso do método destroy.
~/RailsProjects/testes_rails$ rails console
Loading development environment (Rails 4.2.4)
irb(main):001:0> usuario = Usuario.find_by(id: 1)
O código SQL equivalente é:
Usuario Load (0.4ms) SELECT "usuarios".* FROM "usuarios" WHERE "usuarios"."id" = ? LIMIT 1 [["id", 1]]
=> #<Usuario id: 1, nome: "souza da silva", email: nil, login: "jose.silva.leite", senha: "54321">
irb(main):002:0> usuario.destroy
(0.3ms) begin transaction
SQL (0.6ms) DELETE FROM "usuarios" WHERE "usuarios"."id" = ? [["id", 1]]
(85.5ms) commit transaction
Viu como é fácil trabalhar com o Active Record no ruby? Ele auxiliou muito na rapidez da geração de código, pois foram poucos comandos para muito código SQL, que acompanhamos nas listagens.
Referências
RailsGuides
http://guides.rubyonrails.org/active_record_basics.html
API Dock
http://apidock.com/rails/ActiveRecord/Base
API
Ruby On Rails
http://api.rubyonrails.org/classes/ActiveRecord/QueryMethods.html