Rafael Pereira Alonso
Computer Science student at the Federal University of São Carlos - Sorocaba and Ruby On Rails Teacher
A arquitetura MVC
Vamos fazer um Task Manager
require 'sqlite3' # precisamos disso para usar os comandos SQLite
require_relative 'router'
# inicializamos a constante que irá referenciar nosso BD
db_path = File.join(File.dirname(__FILE__), "db/tasks.sqlite")
DB = SQLite3::Database.new(db_path)
# inicia uma instacia de router e põe pra rodar
router = Router.new
router.run
class Router
# inicializamos o router colocando uma variável para controlar o loop
def initialize
@running = true
end
# método do loop, para mostrar as opções, pegar o input e delegar uma
# ação ao controller
def run
puts "============================"
puts "====== TASK MANAGER ======"
puts "============================"
while @running
show_options
opt = gets.chomp.to_i
print `clear`
run_option(opt)
end
end
# método para mostrar as opções (chamado pelo run)
def show_options
puts 'What would you like to do?'
puts '1 - ?????'
puts '2 - ?????'
puts '3 - ?????'
puts '4 - ?????'
puts '5 - ?????'
puts '0 - exit the task manager'
end
# método para delegar uma opção ao controller ou parar o app
def run_option(opt)
case opt
when 0
puts 'See you later!'
@running = false
else
puts 'Invalid option...'
end
end
end
# como faremos um TASK manager, um modelo interessante seria o próprio task
# Para simplicidade, teremos apenas seu Id, a descrição da task e um boolean
# indicando se a task foi realizada ou não
# lib/models/task.rb
class Task
# não queremos que ações externas alterem o id ou se foi feito
attr_reader :id, :done
# queremos poder alterar a descrição da task
attr_accessor :desc
def initialize(attrs = {})
@id = attrs['id']
@desc = attrs['desc']
@done = attrs['done'] || false
end
# queremos ter um método para marcar a task como feita
def mark_as_done!
@done = true
end
end
# precisamos de um controller para as ações em cima de uma task. Damos a esse
# o nome de TaskController.
# lib/controllers/task_controller.rb
# Como iremos utilizar o modelo, precisamos 'importá-lo'
require_relative '../models/task'
class TaskController
# ação para listar todas as tasks que já temos
def list_all
# 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
# 3. Mostre-o na tela para o usuário
???
end
end# precisamos de uma view para interagir com o usuário (dependendo da ação
# do controller)
# lib/views/task_view.rb
class TaskView
# ação para listar todas as tasks que já temos
# essa ação espera receber uma array de tasks (para mostrá-las na tela)
def show_all(tasks)
puts '====== Your tasks ======='
tasks.each do |task|
done = task.done ? '[X]' : '[ ]'
puts "#{task.id}: #{done} #{task.desc}"
end
puts '========================='
end
end# para chamarmos o método da view no controller, precisamos 'importá-lo'
# lib/controllers/task_controller.rb
require_relative '../models/task'
require_relative '../views/task_view' # importando a view
class TaskController
# para não termos que criar uma View toda vez que formos usar
# criamos uma variável de instância que utilizaremos toda hora
def initialize
@view = TaskView.new
end
# ação para listar todas as tasks que já temos
def list_all
# ...
# 3. Mostre-o na tela para o usuário (passando as tasks geradas para
# a view
@view.show_tasks(tasks)
end
end# para delegarmos ações ao controller, precisamos chamá-lo aqui no router
# para chamarmos o controller, precisamos 'importá-lo'
# lib/router.rb
require_relative 'controllers/task_controller'
class Router
# inicializamos o router colocando uma variável para controlar o loop
# e outra para guardar o controller o qual delegaremos ações baseados
# na ação do usuário
def initialize
@controller = TaskController.new # criando um controller pra usar
@running = true
end
# ...
# método para mostrar as opções (chamado pelo run)
def show_options
puts 'What would you like to do?'
puts '1 - List all my tasks' # nova opção liberada!!
puts '2 - ?????'
puts '3 - ?????'
puts '4 - ?????'
puts '5 - ?????'
puts '0 - exit the task manager'
end
# método para delegar uma opção ao controller ou parar o app
def run_option(opt)
case opt
when 0
puts 'See you later!'
@running = false
when 1
@controller.list_all # fala pro controller o que fazer
else
puts 'Invalid option...'
end
end
end
# Para refatoração, os controllers são criados no app.rb e então
# passados (como parâmetro) para o router
require 'sqlite3' # precisamos disso para usar os comandos SQLite
require_relative 'router'
require_relative 'controllers/task_controller' # precisamos 'importá-lo'
# inicializamos a constante que irá referenciar nosso BD
db_path = File.join(File.dirname(__FILE__), "db/tasks.sqlite")
DB = SQLite3::Database.new(db_path)
# inicia o controller
task_controller = TaskController.new
# inicia uma instacia de router e põe pra rodar
router = Router.new(task_controller) # passamos o task_controller pro router
router.run
# lib/router.rb
require_relative 'controllers/task_controller'
class Router
# inicializamos o router colocando uma variável para controlar o loop
# e outra para guardar o controller o qual delegaremos ações baseados
# na ação do usuário
def initialize(controller) # esperamos receber os controllers
@controller = controller # instanciamos o controller
@running = true
end
# ...
endComplete o Task Manager! Existem mais quatro coisas que podemos fazer na aplicação:
Pense em como saber interagir com o usuário (view), tanto para mostrar quanto para receber informação.
Pense em como interagir com o Banco de Dados (controller), manipulando modelos e salvando as alterações, inserções e remoções (dica: BD.execute() )
By Rafael Pereira Alonso
Quarta Aula (parte 2) da Atividade Complementar de Ruby On Rails, lecionada na Universidade Federal de São Carlos, campus Sorocaba, no primeiro semestre de 2019
Computer Science student at the Federal University of São Carlos - Sorocaba and Ruby On Rails Teacher