Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
ed25512
project setup
natashabuckham Apr 1, 2023
a2e992a
tables designed and created
natashabuckham Apr 1, 2023
e581877
seed data added to databases
natashabuckham Apr 1, 2023
fe4f8ad
define repository interface for items
natashabuckham Apr 1, 2023
37bcba1
define repository interface for orders
natashabuckham Apr 1, 2023
e671929
test examples for items repo
natashabuckham Apr 1, 2023
01c867b
item repository spec set up
natashabuckham Apr 1, 2023
0bcd890
items all method tested
natashabuckham Apr 1, 2023
03a725d
items find method tested
natashabuckham Apr 1, 2023
2e5595d
item find_by_order method tested
natashabuckham Apr 1, 2023
520f6d2
items create method tested
natashabuckham Apr 1, 2023
e62f000
items update method tested
natashabuckham Apr 1, 2023
afa53f6
items delete method tested
natashabuckham Apr 1, 2023
3e0419b
order test examples written
natashabuckham Apr 1, 2023
5cd5ae1
order repo spec set up
natashabuckham Apr 1, 2023
9c8cb1c
orders all method tested
natashabuckham Apr 1, 2023
56d87cd
orders find method tested
natashabuckham Apr 1, 2023
256240b
order create method tested, order add_item method in progress
natashabuckham Apr 1, 2023
2be2f8f
add items to order tested
natashabuckham Apr 1, 2023
efcca3b
application interface started
natashabuckham Apr 1, 2023
a261bbf
app class written and tested with io double
natashabuckham Apr 2, 2023
0af0265
Added comments for things I would do if I had more time
natashabuckham Apr 2, 2023
5561a59
test coverage html file created
natashabuckham Apr 2, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added .rdbgrc.breakpoints
Empty file.
98 changes: 98 additions & 0 deletions app.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
require_relative 'lib/database_connection'
require_relative './lib/item_repository'
require_relative './lib/order_repository'

# Could refactor run method so the logic for each step is pulled out into separate methods

class Application
def initialize(database_name, io, item_repository, order_repository)
DatabaseConnection.connect(database_name)
@io = io
@item_repository = item_repository
@order_repository = order_repository
end

def run
action_list = "1 = list all shop items\n2 = create a new item\n3 = list all orders\n4 = create a new order\n5 = quit program\n\n"
action = nil
@io.puts "\nWelcome to the shop management program!\n"

until action == "exit"
@io.puts "\nWhat do you want to do?\n#{action_list}"
action = @io.gets.chomp

case action
when "1"
items = @item_repository.all
items.each do |item|
@io.puts "\n#{item.id}. #{item.name} - unit price: #{item.price} - quantity: #{item.quantity}"
end

when "2"
item = Item.new
@io.puts "What is the name of the item?"
item.name = @io.gets.chomp
@io.puts "What is the price of the item?"
item.price = @io.gets.chomp
@io.puts "How many of the item will be in stock?"
item.quantity = @io.gets.chomp

@item_repository.create(item)

@io.puts "#{item.name} added to the database."

when "3"
orders = @order_repository.all

orders.each do |order|
@io.puts "\n#{order.id}. customer name: #{order.customer} - order date: #{order.date}\nOrder contents:\n"
items = @item_repository.find_by_order(order.id)
items.each do |item|
@io.puts "#{item.name} - unit price: #{item.price}\n"
end
end

when "4"
order = Order.new
@io.puts "What is the customer's name?"
order.customer = @io.gets.chomp
@io.puts "What date was the order made?"
order.date = @io.gets.chomp
@order_repository.create(order)
last_id = @order_repository.all.last.id
@created_order = @order_repository.find(last_id)
@io.puts "How many items do you want to add to the order?"
number = @io.gets.chomp.to_i
number.times() do
@io.puts "What is the id of the item you want to add?"
item_id = @io.gets.chomp
item = @item_repository.find(item_id)
if item.quantity == '0'
@io.puts "That item is out of stock. Item could not be added. Please start again."
@order_repository.delete(@created_order.id)
else
@created_order.add_item(item)
item.quantity = item.quantity.to_i - 1
@item_repository.update(item)
@io.puts "#{item.name} added to order."
end
end

when "5"
break

else
@io.puts "Invalid input. Please input a number from 1 to 5."
end
end
end
end

if __FILE__ == $0
app = Application.new(
'shop_manager',
Kernel,
ItemRepository.new,
OrderRepository.new)
app.run
end
28 changes: 28 additions & 0 deletions lib/database_connection.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# file: lib/database_connection.rb

require 'pg'

# This class is a thin "wrapper" around the
# PG library. We'll use it in our project to interact
# with the database using SQL.

class DatabaseConnection
# This method connects to PostgreSQL using the
# PG gem. We connect to 127.0.0.1, and select
# the database name given in argument.
def self.connect(database_name)
@connection = PG.connect({ host: '127.0.0.1', dbname: database_name })
end

# This method executes an SQL query
# on the database, providing some optional parameters
# (you will learn a bit later about when to provide these parameters).
def self.exec_params(query, params)
if @connection.nil?
raise 'DatabaseConnection.exec_params: Cannot run a SQL query as the connection to'\
'the database was never opened. Did you make sure to call first the method '\
'`DatabaseConnection.connect` in your app.rb file (or in your tests spec_helper.rb)?'
end
@connection.exec_params(query, params)
end
end
3 changes: 3 additions & 0 deletions lib/item.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class Item
attr_accessor :id, :name, :price, :quantity
end
85 changes: 85 additions & 0 deletions lib/item_repository.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
require_relative './item'

class ItemRepository
def all
sql = 'SELECT id, name, price, quantity FROM items;'
result_set = DatabaseConnection.exec_params(sql, [])

items = []

result_set.each do |record|
item = Item.new
item.id = record['id']
item.name = record['name']
item.price = record['price']
item.quantity = record['quantity']

items << item
end

items
end

def find(id)
sql = 'SELECT id, name, price, quantity FROM items WHERE id = $1;'
params = [id]

result = DatabaseConnection.exec_params(sql, params)

result.each do |record|
item = Item.new
item.id = record['id']
item.name = record['name']
item.price = record['price']
item.quantity = record['quantity']

return item
end
end

def find_by_order(order_id)
sql = 'SELECT items.id, items.name, items.price, items.quantity
FROM items
JOIN items_orders ON items_orders.item_id = items.id
JOIN orders ON items_orders.order_id = orders.id
WHERE orders.id = $1;'
params = [order_id]

result_set = DatabaseConnection.exec_params(sql, params)

items = []

result_set.each do |record|
item = Item.new
item.id = record['id']
item.name = record['name']
item.price = record['price']
item.quantity = record['quantity']

items << item
end

items
end

def create(item)
sql = 'INSERT INTO items (name, price, quantity) VALUES ($1, $2, $3);'
params = [item.name, item.price, item.quantity]

DatabaseConnection.exec_params(sql, params)
end

def update(item) # need to update quantity when an item is added to an order
sql = 'UPDATE items SET quantity = $1 WHERE id = $2;'
params = [item.quantity, item.id]

DatabaseConnection.exec_params(sql, params)
end

def delete(id) # when quantity reaches zero, need to delete item from stock
sql = 'DELETE FROM items WHERE id = $1;'
params = [id]

DatabaseConnection.exec_params(sql, params)
end
end
13 changes: 13 additions & 0 deletions lib/order.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class Order
attr_accessor :id, :customer, :date

def add_item(item)
order_id = self.id
item_id = item.id

join_sql = 'INSERT INTO items_orders (item_id, order_id) VALUES ($1, $2);'
join_params = [item_id, order_id]

DatabaseConnection.exec_params(join_sql, join_params)
end
end
51 changes: 51 additions & 0 deletions lib/order_repository.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
require_relative './order'

class OrderRepository
def all
sql = 'SELECT id, customer, date FROM orders;'
result_set = DatabaseConnection.exec_params(sql, [])

orders = []

result_set.each do |record|
order = Order.new
order.id = record['id']
order.customer = record['customer']
order.date = record['date']

orders << order
end

orders
end

def find(id)
sql = 'SELECT id, customer, date FROM orders WHERE id = $1;'
params = [id]

result = DatabaseConnection.exec_params(sql, params)

result.each do |record|
order = Order.new
order.id = record['id']
order.customer = record['customer']
order.date = record['date']

return order
end
end

def create(order)
sql = 'INSERT INTO orders (customer, date) VALUES ($1, $2);'
params = [order.customer, order.date]

DatabaseConnection.exec_params(sql, params)
end

def delete(id)
sql = 'DELETE FROM orders WHERE id = $1;'
params = [id]

DatabaseConnection.exec_params(sql, params)
end
end
22 changes: 22 additions & 0 deletions recipes/items_orders.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
CREATE TABLE items (
id SERIAL PRIMARY KEY,
name text,
price int,
quantity int
);

-- Create the second table.
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
customer text,
date date
);

-- Create the join table.
CREATE TABLE items_orders (
item_id int,
order_id int,
constraint fk_item foreign key(item_id) references items(id) on delete cascade,
constraint fk_order foreign key(order_id) references orders(id) on delete cascade,
PRIMARY KEY (item_id, order_id)
);
Loading