Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
b902219
Set up file structure
ev-th Apr 28, 2023
26eff20
Copy in DatabaseConnection class from Makers music_library project
ev-th Apr 28, 2023
2a00d7e
Make connection to test database for all tests
ev-th Apr 28, 2023
c0966c6
Write seeds for setting up test database before running tests
ev-th Apr 28, 2023
43734da
Edit the spec/spec_seeds insertion values
ev-th Apr 28, 2023
1e53f8d
Write test and implementation for ItemRepository#all
ev-th Apr 28, 2023
85e3be3
Write test and implement ItemRepository#create
ev-th Apr 28, 2023
dd1c561
Write test for and implement OrderRepository#all
ev-th Apr 28, 2023
6b3ceaf
Write OrderRepository#create and write test
ev-th Apr 28, 2023
ed4c6bf
Refactor create method tests to use to include have attributes syntax
ev-th Apr 28, 2023
57d70c9
Remove OrderRepository#all_with_items
ev-th Apr 28, 2023
bb712b9
Refactor formatting and extract some logic to private methods
ev-th Apr 28, 2023
a66e09a
Add Application, implement first print and add test
ev-th Apr 28, 2023
ac7d4ed
Test drive Application#run to print out all items
ev-th Apr 29, 2023
a717865
Refactor Application#run method by moving functionality to private me…
ev-th Apr 29, 2023
2e033c8
Allow Application#run to get new item from the user
ev-th Apr 29, 2023
6595620
Allow Application#run to print all orders
ev-th Apr 29, 2023
c3e2921
Allow Application#run to get new orders from the user
ev-th Apr 29, 2023
4eb3394
Refactor application.rb and tests to follow rubocop formatting
ev-th Apr 29, 2023
46a90db
Further refactor for rubocop
ev-th Apr 29, 2023
60460e0
Move reset_tables from spec files to spec helper to remove duplication
ev-th Apr 29, 2023
0087cdb
Write app.rb
ev-th Apr 29, 2023
90d6d60
Add final trailing newlines to appease rubocop
ev-th Apr 29, 2023
0e063c5
Add ItemRepository#find
ev-th Apr 30, 2023
df7226b
Update Application#print_all_orders to print items associated with or…
ev-th Apr 30, 2023
2a1cc0f
Add integration tests
ev-th Apr 30, 2023
bdd04a9
Fix bugs to pass integration tests
ev-th Apr 30, 2023
fd01eb3
Update application spec to test new order print formatting
ev-th Apr 30, 2023
5fd8e03
Fix bug when printing orders that have no associated items
ev-th Apr 30, 2023
cb36844
Remove unused Item#find and test
ev-th Apr 30, 2023
e7f77cd
Refactor to comply with rubocop
ev-th Apr 30, 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
7 changes: 7 additions & 0 deletions app.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
require_relative "lib/application"

database = "shop_manager"

app = Application.new(database)

app.run
118 changes: 118 additions & 0 deletions lib/application.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
require_relative "./item_repository"
require_relative "./order_repository"

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

def run
print_welcome_options
choice = @io.gets.chomp
process_user_input(choice)
end

private

def process_user_input(choice)
case choice
when "1"
print_all_items
when "2"
add_new_item
when "3"
print_all_orders
when "4"
add_new_order
end
end

def add_new_order
add_order_to_database(*new_order_from_user)
end

def new_order_from_user
@io.print "What's the customer name of the new order: "
customer = @io.gets.chomp
@io.print "What's the date this order was placed: "
date = @io.gets.chomp
[customer, date]
end

def add_order_to_database(customer, date)
order = Order.new
order.customer_name = customer
order.date_placed = date
@order_repository.create(order)
end

def add_new_item
name, price, quantity = new_item_from_user
add_item_to_database(name, price, quantity)
end

def new_item_from_user
@io.print "What's the name of the new item: "
name = @io.gets.chomp
@io.print "What's the unit price of the new item: "
price = @io.gets.chomp
@io.print "What's the quantity of the new item: "
quantity = @io.gets.chomp
[name, price, quantity]
end

def add_item_to_database(name, price, quantity)
item = Item.new
item.name = name
item.unit_price = price
item.quantity = quantity
@item_repository.create(item)
end

def print_all_items
items = @item_repository.all
@io.puts("Here's a list of all shop items:\n")
items.each_with_index do |item, i|
@io.puts "##{i + 1} #{item.name} - " +
"Unit price: #{format_price(item.unit_price)} - " +
"Quantity: #{item.quantity}"
end
end

def format_price(price)
pounds = (price.to_i / 100).to_s
pence = (price.to_i % 100).to_s
pence = "0" + pence if pence.length == 1
"£#{pounds}.#{pence}"
end

def print_all_orders
orders = @order_repository.all_with_items
@io.puts "Here's a list of all orders:\n"
orders.each_with_index do |order, i|
@io.puts "##{i + 1} Customer: #{order.customer_name} - Date placed: #{order.date_placed}"
order.items.each do |item|
@io.puts " #{item.name} - Unit price: #{format_price(item.unit_price)}"
end
@io.puts ""
end
end

def print_welcome_options
@io.puts("Welcome to the shop management program!\n")
@io.puts("What do you want to do?")
@io.puts(" 1 = list all shop items")
@io.puts(" 2 = create a new item")
@io.puts(" 3 = list all orders")
@io.puts(" 4 = create a new order")
@io.puts("")
end
end
16 changes: 16 additions & 0 deletions lib/database_connection.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
require "pg"

class DatabaseConnection
def self.connect(database_name)
@connection = PG.connect({ host: "127.0.0.1", dbname: database_name })
end

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, :unit_price, :quantity
end
28 changes: 28 additions & 0 deletions lib/item_repository.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
require_relative "./database_connection"
require_relative "./item"

class ItemRepository
def all
sql = "SELECT * FROM items;"
records = DatabaseConnection.exec_params(sql, [])
records.map { |record| convert_record_to_item(record) }
end

def create(item)
sql = "INSERT INTO items (name, unit_price, quantity)
VALUES ($1, $2, $3);"
params = [item.name, item.unit_price, item.quantity]
DatabaseConnection.exec_params(sql, params)
end

private

def convert_record_to_item(record)
item = Item.new
item.id = record["id"]
item.name = record["name"]
item.unit_price = record["unit_price"]
item.quantity = record["quantity"]
item
end
end
7 changes: 7 additions & 0 deletions lib/order.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class Order
attr_accessor :id, :customer_name, :date_placed, :items

def initialize
@items = []
end
end
67 changes: 67 additions & 0 deletions lib/order_repository.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
require_relative "./order"

class OrderRepository
def all
sql = "SELECT * FROM orders;"
records = DatabaseConnection.exec_params(sql, [])
records.map { |record| record_to_order(record) }
end

def all_with_items
sql = "SELECT id FROM orders;"
records = DatabaseConnection.exec_params(sql, [])
orders = []
records.each do |record|
id = (record["id"]).to_i
order = find_with_items(id)
orders << order
end
orders
end

def find(id)
sql = "SELECT * FROM orders WHERE id = $1;"
records = DatabaseConnection.exec_params(sql, [id])
record_to_order(records.first)
end

def find_with_items(id)
sql = "SELECT orders.id AS id, customer_name, date_placed,
items.id AS items_id, name, unit_price, quantity
FROM orders JOIN items_orders ON orders.id = items_orders.order_id
JOIN items ON items.id = items_orders.item_id
WHERE orders.id = $1;"

records = DatabaseConnection.exec_params(sql, [id])
return find(id) if records.ntuples.zero?
order = record_to_order(records.first)
records.each { |record| order.items << record_to_item(record) }
order
end

def create(order)
sql = "INSERT INTO orders (customer_name, date_placed)
VALUES ($1, $2)"
params = [order.customer_name, order.date_placed]
DatabaseConnection.exec_params(sql, params)
end

private

def record_to_order(record)
order = Order.new
order.id = record["id"]
order.customer_name = record["customer_name"]
order.date_placed = record["date_placed"]
order
end

def record_to_item(record)
item = Item.new
item.id = record["items_id"]
item.name = record["name"]
item.unit_price = record["unit_price"]
item.quantity = record["quantity"]
item
end
end
20 changes: 20 additions & 0 deletions seeds.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
CREATE TABLE items (
id SERIAL PRIMARY KEY,
name text,
unit_price int,
quantity int
);

CREATE TABLE orders (
id SERIAL PRIMARY KEY,
customer_name text,
date_placed date
);

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