# inicialização PITA do BD
DB = SQLite3::Database.new("db/database.sqlite3")
# Inserção de um objeto (em Ruby) no BD
cart = Cart.new(owner: 'Jon Snow')
DB.execute("INSERT INTO 'cart' (owner) VALUES ('#{cart.owner}')")
# Recuperação de um objeto (no BD) para ruby
# 1. pegue as tasks do BD
rows = DB.execute('SELECT * FROM tasks')
# 2. para cada linha recuperada, crie um novo Task. Guarde todos os
# tasks numa array
tasks = rows.map do |row|
# 'done' será 0 ou 1 (no BD). Para transformá-lo em boolean...
row['done'] = !row['done'].zero?
Task.new(row)
end
# BD já configurado (sem ter que inicializar)
# ========== Inserção de um objeto (em Ruby) no BD ===========
cart = Cart.new(owner: 'Jon Snow')
cart.save # => salva no BD e fim
# ======== Recuperação de objetos (no BD) para ruby ==========
# pega todas as linhas do BD, transforma tudo em Task e guarda
# em uma Array
tasks = Task.all
Precisamos configurar umas coisas antes
$ gem install activerecordClonem o repositório abaixo. Algumas configurações já estão prontas (não é preciso se preocupar com as mesmas)
Rake -T
Mostra todos os comandos que o rake pode fazer (com uma pequena desc do que fazem)
Gemfile e Gemfile.lock
Todas as gems que o projeto irá utilizar. As mesmas são 'instaladas' localmente ao rodar '$ bundle install' no terminal
config/application.rb
nosso app.rb!
config/database.yml
YAML é similar ao JSON, exceto pela sintaxe. database.yml guarda as informações sobre o Banco de Dados que iremos utilizar (nesse caso, o tipo do Banco [Sqlite3] e o arquivo do mesmo)
db/migrate/
É onde colocaremos as modificações feitas na estrutura do nosso BD (novas tabelas ou colunas, alteração de nomes/tipos, remoção, etc.)
db/seed.rb
Código para a população inicial do BD
Veremos os dois melhor daqui a pouco!
rake tem uma task para isso!
$ rake db:create # cria o banco de dados no local especificado em db/database.yml
$ rake db:drop # deleta o banco de dados no local especificado em db/database.ymlAlgo mudou na pasta db/
O mundo mágico das migrações
# para criar uma migração, precisamos de um 'timestamp'.
# Felizmente, o rake tem uma task para isso.
$ TS = `rake db:timestamp`
$ touch db/migrate/${TS}_create_tasks.rb
# db/migrate/???????_create_tasks.rb
# estrutura básica de uma migração
# note como o nome da classe bate com o nome do arquivo
class CreateTasks < ActiveRecord::Migration[5.1]
def change
# nosso código aqui
end
endComo criar uma tabela
# db/migrate/???????_create_tasks.rb
# estrutura básica de uma migração
# note como o nome da classe bate com o nome do arquivo
class CreateTasks < ActiveRecord::Migration[5.1]
def change
create_table :tasks do |t|
t.string :desc
t.boolean :done, default: false
t.timestamps # não é obrigatório.
# Guarda quando o objeto foi criado e atualizado
end
end
endPorque a migração ainda não foi executada
# deixe uma task do rake cuidar disso
$ rake db:migrate # roda todas as migrações posteriores à última executada
# db/migrate/???????_add_deadline_to_tasks.rb
# note como o nome da classe bate com o nome do arquivo
class AddDeadlineToTasks < ActiveRecord::Migration[5.1]
def change
add_column :tasks, :deadline, :timestamp, default: Time.now + 2.hours
end
end
# db/migrate/???????_remove_deadline_from_tasks.rb
# note como o nome da classe bate com o nome do arquivo
class RemoveDeadlineFromTasks < ActiveRecord::Migration[5.1]
def change
remove_column :tasks, :deadline
end
end(Contém spoilers de Rails)
class Task
attr_reader :id,:desc,:done
attr_writer :desc
def initialize(args)
@id = args['id']
@desc = args['desc']
@done = args['done']
end
endclass Task < ActiveRecord::Base
endPor meio dele, podemos programar como se estivéssemos no irb, mas com o projeto carregado
$ rake console
task = Task.new
# => #<Task:0x00007feb74ef47c0
# id: nil,
# desc: nil,
# done: false, # nosso default
# created_at: nil,
# updated_at: nil>
task.desc = 'Manjar de AR'
# => #<Task:0x00007feb74ef47c0
# id: nil,
# desc: 'Manjar de AR',
# done: false,
# created_at: nil,
# updated_at: nil>
task.save # Salva o modelo no banco de dados, tabela de mesmo nome do objeto
task
# => #<Task:0x00007feb74ef47c0
# id: 1, gerado pelo BD (NÃO MEXE NISSO)
# desc: 'Manjar de AR',
# done: false,
# created_at: ?????, gerado pelo BD
# updated_at: ?????> gerado pelo BD
# => SELECT * FROM tasks WHERE id = 1;
task = Task.find(1)
task
# => #<Task:???? id: 1, desc: 'Manjar de AR', done: false, ... >
# => SELECT * FROM tasks;
tasks = Task.all
tasks.first
# => #<Task:???? id: 1, desc: 'Manjar de AR', done: false, ... >
# => SELECT desc FROM tasks;
tasks = Task.all.pluck(:desc)
# => SELECT * FROM tasks WHERE done = true;
tasks = Task.where(done: true)
Task.new.saveclass Task < ActiveRecord::Base
valida a presença da descrição
validates :desc, presence: true
end
Task.new.save # => erro
# presence
# uniqueness
# inclusion
# length
# numericalityComo conectar tabelas / modelos
# db/migrate/???????_create_owners.rb
class CreateOwners < ActiveRecord::Migration[5.1]
def change
create_table :tasks do |t|
t.string :nome
t.timestamps
end
end
end
# app/models/owner.rb
class Owner < ActiveRecord::Base
endO task vai referenciar o owner
Uma nova migration
# db/migrate/???????_add_owner_to_tasks.rb
# note como o nome da classe bate com o nome do arquivo
class AddDeadlineToTasks < ActiveRecord::Migration[5.1]
def change
# add_reference, não add_column
add_reference :tasks, :owner, foreing_key: true
end
end