Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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 README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
Note:
-------
I did not get to TDD this project as I wished for due to lack of time, it just seemed more important to me at this time to imagine and put in practice a whole shop_manager with the relevant classes, methods and DB access. I will definetly do a lot more on the testing next time. What a lovely jouney it has been to see it work in the end so close to what a real app would do.




Shop Manager Project
=================

Expand Down
24 changes: 24 additions & 0 deletions lib/item.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
class Item
def initialize(name, unit_price, quantity, item_id = 0)
@name = name
@unit_price = unit_price
@quantity = quantity
@item_id = item_id
end

def name
@name
end

def unit_price
@unit_price
end

def quantity
@quantity
end

def item_id
@item_id
end
end
19 changes: 19 additions & 0 deletions lib/order.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
class Order
def initialize(customer_name, item, order_id = 0)
@customer_name = customer_name
@item = item
@order_id = order_id
end

def customer_name
@customer_name
end

def item
@item
end

def order_id
@order_id
end
end
149 changes: 149 additions & 0 deletions lib/shop_manager.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
require_relative './item'
require_relative './order'
require 'pg'

class ShopManager
WHAT_TO_DO = 'What do you want to do?
1 = list all shop items
2 = create a new item
3 = list all orders
4 = create a new order'

def initialize
db_connect
initiate_menu
end

def initiate_menu(initial = true)
puts "
Welcome to the shop management program!
" if initial == true
puts "
#{WHAT_TO_DO}
"
answer = gets.chomp
case answer
when '1'
print_all_items(all_items)
when '2'
new_item_collect_data
when '3'
all_orders
when '4'
new_order_collect_data
else
initiate_menu(false)
end
end

def new_item_collect_data
while true do
puts 'Enter the name for the new Item'
name = gets.chomp
break if name.count("a-zA-Z") > 0
end
while true do
puts "Enter the price for the #{name}"
unit_price = gets.chomp
break if unit_price.to_i.is_a? Integer
end
while true do
puts "Enter the quantity for the #{name}"
quantity = gets.chomp
break if quantity.to_i.is_a? Integer
end
item = Item.new(name, unit_price, quantity)
new_item(item)
end

def new_item(item)
# add item to items table
query = "INSERT INTO items(name, unit_price, quantity)
VALUES('#{item.name}', #{item.unit_price.to_i}, #{item.quantity.to_i});"
result = @conn_db.exec(query)
puts "Your item has been added succesfully"
end

def db_connect()
@conn_db = PG.connect({ host: '127.0.0.1', dbname: 'shop_manager' })
end

def new_order_collect_data
while true do
puts 'New Order, please enter your name'
customer_name = gets.chomp
break if customer_name.count("a-zA-Z") > 4 && customer_name.split(' ').count >= 2
end
items = all_items
while true do
puts "Please select you item's id"
item_id = gets.chomp
if item_id.to_i.is_a? Integer
return_item = items.find { |curr_item| curr_item.item_id == item_id }
if !return_item.nil?
item = Item.new(return_item.name, return_item.unit_price, return_item.quantity, return_item.item_id)
order = Order.new(customer_name, item)
new_order(order)
end
end
break unless return_item.nil?
end
end

def new_order(order)
# add order to orders table
query = "INSERT INTO orders(customer_name, item_id)
VALUES('#{order.customer_name}', '#{order.item.item_id}') RETURNING *;"
@conn_db.exec(query)
puts "Your order has been placed succesfully, thank you!"
end

private
def get_select_query(table)
"SELECT * FROM #{table};"
end

def all_items
query = get_select_query('items')
items = @conn_db.exec(query)
items = items.map do |item|
Item.new(item['name'], item['unit_price'], item['quantity'], item['item_id'])
end

items
end

def orders_all
query = get_select_query('orders')
@conn_db.exec(query)
end

def all_orders
items = all_items
orders = orders_all
orders = orders.map do |order|
item = items.find { |curr_item| curr_item.item_id == order['item_id'] }
Order.new(order["customer_name"], item, order["order_id"])
end
print_all_orders(orders)
end

def print_all_items(items)
puts "Here's a list of all shop items:"
#1 Super Shark Vacuum Cleaner - Unit price: 99 - Quantity: 30
items.each do |item|
puts "Item id: #{item.item_id} - #{item.name} - Unit price: £#{item.unit_price}.00 - Quantity: #{item.quantity}"
end
end

def print_all_orders(orders)
puts "Here's a list of all shop orders:"
#1 Super Shark Vacuum Cleaner - Unit price: 99 - Quantity: 30
orders.each do |order|
puts "Order id: #{order.order_id} - #{order.customer_name} - Item: #{order.item.name} - Price: £#{order.item.unit_price}.00"
end
end
end

ShopManager.new

149 changes: 149 additions & 0 deletions recipe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
# Two Tables (Many-to-Many) Design Recipe Template

_Copy this recipe template to design and create two related database tables having a Many-to-Many relationship._

## 1. Extract nouns from the user stories or specification

```ruby
As a shop manager
So I can know which items I have in stock
I want to keep a list of my shop items with their name and unit price.

As a shop manager
So I can know which items I have in stock
I want to know which quantity (a number) I have for each item.

As a shop manager
So I can manage items
I want to be able to create a new item.

As a shop manager
So I can know which orders were made
I want to keep a list of orders with their customer name.

As a shop manager
So I can know which orders were made
I want to assign each order to their corresponding item.

As a shop manager
So I can know which orders were made
I want to know on which date an order was placed.

As a shop manager
So I can manage orders
I want to be able to create a new order.

```
Nouns:

items, item_name, unit_price
```

## 2. Infer the Table Name and Columns

Put the different nouns in this table. Replace the example with your own nouns.

| Record | Properties |
| --------------------- | ------------------ |
| posts | title, content
| tags | name

1. Name of the first table (always plural): `posts`

Column names: `title`, `content`

2. Name of the second table (always plural): `tags`

Column names: `name`

## 3. Decide the column types.

[Here's a full documentation of PostgreSQL data types](https://www.postgresql.org/docs/current/datatype.html).

Most of the time, you'll need either `text`, `int`, `bigint`, `numeric`, or `boolean`. If you're in doubt, do some research or ask your peers.

Remember to **always** have the primary key `id` as a first column. Its type will always be `SERIAL`.

```
# EXAMPLE:

Table: posts
id: SERIAL
title: text
content: text

Table: tags
id: SERIAL
name: text
```

## 4. Design the Many-to-Many relationship

Make sure you can answer YES to these two questions:

1. Can one [TABLE ONE] have many [TABLE TWO]? (Yes/No)
2. Can one [TABLE TWO] have many [TABLE ONE]? (Yes/No)

```
# EXAMPLE

1. Can one tag have many posts? YES
2. Can one post have many tags? YES
```

_If you would answer "No" to one of these questions, you'll probably have to implement a One-to-Many relationship, which is simpler. Use the relevant design recipe in that case._

## 5. Design the Join Table

The join table usually contains two columns, which are two foreign keys, each one linking to a record in the two other tables.

The naming convention is `table1_table2`.

```
# EXAMPLE

Join table for tables: posts and tags
Join table name: posts_tags
Columns: post_id, tag_id
```

## 4. Write the SQL.

```sql
-- EXAMPLE
-- file: posts_tags.sql

-- Replace the table name, columm names and types.

-- Create the first table.
CREATE TABLE items (
item_id SERIAL PRIMARY KEY,
name text,
unit_price int,
quantity int
);

-- Create the second table.
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
custumer_name text,
date TIMESTAMP not null defaul now(),
item_id int
);

-- 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)
);

```

## 5. Create the tables.

```bash
psql -h 127.0.0.1 database_name < posts_tags.sql
```