Skip to content

Instantly share code, notes, and snippets.

@Martin-Alexander
Last active April 29, 2019 02:43
Show Gist options
  • Save Martin-Alexander/ea107e78e7b29716d5a116058d5a7b1f to your computer and use it in GitHub Desktop.
Save Martin-Alexander/ea107e78e7b29716d5a116058d5a7b1f to your computer and use it in GitHub Desktop.
Food Delivery App
require "csv"
require_relative "router"
require_relative "app/models/meal"
require_relative "app/controllers/meals_controller"
require_relative "app/repositories/meal_repository"
require_relative "app/views/meal_view"
require_relative "app/models/customer"
require_relative "app/controllers/customers_controller"
require_relative "app/repositories/customer_repository"
require_relative "app/views/customer_view"
require_relative "app/models/employee"
require_relative "app/controllers/sessions_controller"
require_relative "app/repositories/employee_repository"
require_relative "app/views/session_view"
require_relative "app/models/order"
require_relative "app/controllers/orders_controller"
require_relative "app/repositories/order_repository"
require_relative "app/views/order_view"
meals_csv_path = "data/meals.csv"
meals_repo = MealRepository.new(meals_csv_path)
meals_controller = MealsController.new(meals_repo)
customers_csv_path = "data/customers.csv"
customers_repo = CustomerRepository.new(customers_csv_path)
customers_controller = CustomersController.new(customers_repo)
employee_csv_path = "data/employees.csv"
employee_repo = EmployeeRepository.new(employee_csv_path)
sessions_controller = SessionsController.new(employee_repo)
orders_csv_path = "data/orders.csv"
orders_repo = OrderRepository.new(orders_csv_path, meals_repo, employee_repo, customers_repo)
orders_controller = OrdersController.new(meals_repo, employee_repo, customers_repo, orders_repo)
router = Router.new(
meals_controller,
customers_controller,
sessions_controller,
orders_controller
)
router.run
class Customer
attr_reader :name, :address
attr_accessor :id
def initialize(attributes = {})
@id = attributes[:id]
@name = attributes[:name]
@address = attributes[:address]
end
end
class CustomerRepository
def initialize(csv_file_path)
@csv_file_path = csv_file_path
@customers = [] # An array of customer objects
csv_options = { headers: true, header_converters: :symbol }
if File.exist?(@csv_file_path)
CSV.foreach(@csv_file_path, csv_options) do |row|
# row = { id: "1", name: "Paul McCartney", address: "Liverpool" }
row[:id] = row[:id].to_i
@customers << Customer.new(row)
end
end
end
def all
@customers
end
def add(new_customer)
# set the id of the new customer
if @customers.empty?
new_id = 1
else
new_id = @customers.last.id + 1
end
new_customer.id = new_id
# push it into the array `@customers`
@customers << new_customer
# write to the csv
CSV.open(@csv_file_path, "w") do |csv_file|
csv_file << ["id", "name", "address"]
@customers.each do |customer|
csv_file << [customer.id, customer.name, customer.address]
end
end
end
def find(customer_id)
@customers.find do |customer|
customer.id == customer_id
end
end
end
class CustomerView
def display_customers(customers)
customers.each do |customer|
puts "#{customer.id} - #{customer.name} #{customer.address}"
end
end
def ask_for(message)
puts message
print "> "
user_input = gets.chomp
user_input
end
end
id name address
1 Paul McCartney Liverpool
2 John Bonham Redditch
3 John Entwistle Chiswick
4 tina 5333 ave cagrain
require_relative "../views/customer_view"
class CustomersController
def initialize(repository)
@repository = repository
@view = CustomerView.new
end
def list
customers = @repository.all
@view.display_customers(customers)
end
def add
customer_name = @view.ask_for("Name:")
customer_address = @view.ask_for("Address:")
customer_hash = {
name: customer_name,
address: customer_address
}
new_customer = Customer.new(customer_hash)
@repository.add(new_customer)
end
end
class Employee
attr_reader :username, :role, :password
attr_accessor :id
def initialize(attributes = {})
@id = attributes[:id]
@username = attributes[:username]
@password = attributes[:password]
@role = attributes[:role]
end
def manager?
@role == "manager"
end
def delivery_guy?
@role == "delivery_guy"
end
end
class EmployeeRepository
def initialize(csv_file_path)
@employees = [] # Stores employee objects
if File.exist?(csv_file_path)
options = { headers: true, header_converters: :symbol }
CSV.foreach(csv_file_path, options) do |row|
row[:id] = row[:id].to_i
@employees << Employee.new(row)
end
end
end
def all_delivery_guys
@employees.select { |employee| employee.delivery_guy? }
end
def find(id)
@employees.find { |employee| employee.id == id }
end
def find_by_username(username)
@employees.find { |employee| employee.username == username }
end
end
id username password role
1 simon secret manager
2 robert password delivery_guy
3 fito fito delivery_guy
class Meal
attr_reader :name, :price
attr_accessor :id
def initialize(attributes = {})
@id = attributes[:id]
@name = attributes[:name]
@price = attributes[:price]
end
end
class MealRepository
def initialize(csv_file_path)
@csv_file_path = csv_file_path
@meals = [] # An array of Meal objects
csv_options = { headers: true, header_converters: :symbol }
if File.exist?(@csv_file_path)
CSV.foreach(@csv_file_path, csv_options) do |row|
# row = { id: "1", name: "Margherita", price: "8" }
row[:id] = row[:id].to_i
row[:price] = row[:price].to_i
@meals << Meal.new(row)
end
end
end
def all
@meals
end
def add(new_meal)
# set the id of the new meal
if @meals.empty?
new_id = 1
else
new_id = @meals.last.id + 1
end
new_meal.id = new_id
# push it into the array `@meals`
@meals << new_meal
# write to the csv
CSV.open(@csv_file_path, "w") do |csv_file|
csv_file << ["id", "name", "price"]
@meals.each do |meal|
csv_file << [meal.id, meal.name, meal.price]
end
end
end
def find(meal_id)
@meals.find do |meal|
meal.id == meal_id
end
end
end
class MealView
def display_meals(meals)
meals.each do |meal|
puts "#{meal.id} - $#{meal.price} #{meal.name}"
end
end
def ask_for(message)
puts message
print "> "
user_input = gets.chomp
user_input
end
end
id name price
1 Margherita 8
2 Capricciosa 11
3 Napolitana 9
4 Funghi 12
5 Calzone 10
6 Pizza 10
require_relative "../views/meal_view"
class MealsController
def initialize(repository)
@repository = repository
@view = MealView.new
end
def list
meals = @repository.all
@view.display_meals(meals)
end
def add
meal_name = @view.ask_for("Name:")
meal_price = @view.ask_for("Price:").to_i
meal_hash = {
name: meal_name,
price: meal_price
}
new_meal = Meal.new(meal_hash)
@repository.add(new_meal)
end
end
class Order
attr_reader :delivered, :meal, :customer, :employee
attr_accessor :id
def initialize(attributes = {})
@id = attributes[:id]
@delivered = attributes[:delivered] || false
@meal = attributes[:meal]
@customer = attributes[:customer]
@employee = attributes[:employee]
end
def delivered?
@delivered
end
def deliver!
@delivered = true
end
end
class OrderRepository
def initialize(orders_csv_path, meal_repository, employee_repository, customer_repository)
@orders_csv_path = orders_csv_path
@meal_repository = meal_repository
@employee_repository = employee_repository
@customer_repository = customer_repository
@orders = []
load_from_csv
end
def load_from_csv
if File.exist?(@orders_csv_path)
csv_options = { headers: true, header_converters: :symbol }
CSV.foreach(@orders_csv_path, csv_options) do |row|
# row = { id: "1" ,delivered: "true" , meal_id: "1", employee_id: "2", customer_id: "1" }
meal_object = @meal_repository.find(row[:meal_id].to_i)
customer_object = @customer_repository.find(row[:customer_id].to_i)
employee_object = @employee_repository.find(row[:employee_id].to_i)
@orders << Order.new(
id: row[:id].to_i,
delivered: row[:delivered] == "true",
meal: meal_object,
customer: customer_object,
employee: employee_object
)
end
end
end
def undelivered_orders
@orders.select do |order|
order.delivered? == false
end
end
def find(id)
@orders.find { |order| order.id == id }
end
def add(new_order)
if @orders.empty?
new_id = 1
else
new_id = @orders.last.id + 1
end
new_order.id = new_id
@orders << new_order
save_to_csv
end
def save_to_csv
CSV.open(@orders_csv_path, "w") do |csv_file|
csv_file << ["id", "delivered", "meal_id", "employee_id", "customer_id"]
@orders.each do |order|
csv_file << [order.id, order.delivered?, order.meal.id, order.employee.id, order.customer.id]
end
end
end
end
class OrderView
def display_orders(orders)
orders.each do |order|
puts "#{order.id} - #{order.customer.name} #{order.meal.name}. Delivered by: #{order.employee.username}"
end
end
def display_delivery_guys(employees)
employees.each do |employee|
puts "#{employee.id} - #{employee.username}"
end
end
def ask_for_id
puts "Enter id:"
print "> "
user_input = gets.chomp.to_i
user_input
end
end
id delivered meal_id employee_id customer_id
1 true 1 2 1
2 false 1 2 2
3 false 2 2 3
4 false 5 3 1
5 true 1 3 4
require_relative "../views/order_view"
class OrdersController
def initialize(meal_repository, employee_repository, customer_repository, order_repository)
@meal_repository = meal_repository
@employee_repository = employee_repository
@customer_repository = customer_repository
@order_repository = order_repository
@view = OrderView.new
end
def list_undelivered_orders
# ORDER REPO: get all undelivered orders
orders = @order_repository.undelivered_orders
# VIEW: give it the orders to be displayed
@view.display_orders(orders)
end
def add
MealsController.new(@meal_repository).list
meal_id = @view.ask_for_id
meal = @meal_repository.find(meal_id)
CustomersController.new(@customer_repository).list
customer_id = @view.ask_for_id
customer = @customer_repository.find(customer_id)
employees = @employee_repository.all_delivery_guys
@view.display_delivery_guys(employees)
employee_id = @view.ask_for_id
employee = @employee_repository.find(employee_id)
new_order = Order.new(meal: meal, customer: customer, employee: employee)
@order_repository.add(new_order)
end
def list_my_orders(employee)
orders = @order_repository.undelivered_orders
employees_orders = orders.select { |order| order.employee == employee }
@view.display_orders(employees_orders)
end
def mark_as_delivered(employee)
list_my_orders(employee)
order_id = @view.ask_for_id
order = @order_repository.find(order_id)
order.deliver!
@order_repository.save_to_csv
end
end
class Router
def initialize(meals_controller, customers_controller, sessions_controller, orders_controller)
@meals_controller = meals_controller
@customers_controller = customers_controller
@sessions_controller = sessions_controller
@orders_controller = orders_controller
end
def run
@employee = @sessions_controller.login
if @employee.manager?
start_manager_menu_loop
else
start_delivery_guy_menu_loop
end
end
private
def start_manager_menu_loop
loop do
puts "=== MAIN MENU ==="
puts "1 - All Meals"
puts "2 - New Meal"
puts "3 - All Customers"
puts "4 - New Customer"
puts "5 - Undelivered Orders"
puts "6 - New Order"
puts "7 - Quit"
puts "Input"
print "> "
user_choice = gets.chomp.to_i
print `clear`
case user_choice
when 1 then @meals_controller.list
when 2 then @meals_controller.add
when 3 then @customers_controller.list
when 4 then @customers_controller.add
when 5 then @orders_controller.list_undelivered_orders
when 6 then @orders_controller.add
when 7 then break
end
end
end
def start_delivery_guy_menu_loop
loop do
puts "=== MAIN MENU ==="
puts "1 - My Undelivered Orders"
puts "2 - Mark Order as Delivered"
puts "3 - Quit"
puts "Input"
print "> "
user_choice = gets.chomp.to_i
print `clear`
case user_choice
when 1 then @orders_controller.list_my_orders(@employee)
when 2 then @orders_controller.mark_as_delivered(@employee)
when 3 then break
end
end
end
end
class SessionView
def ask_for(message)
puts message
user_input = gets.chomp
user_input
end
end
class SessionsController
def initialize(employee_repository)
@employee_repository = employee_repository
@view = SessionView.new
end
def login
username = @view.ask_for("Enter username:")
password = @view.ask_for("Enter password:")
employee = @employee_repository.find_by_username(username)
if !employee.nil? && employee.password == password
return employee
else
login
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment