Skip to content

Instantly share code, notes, and snippets.

@samstephen
Last active August 29, 2015 14:23
Show Gist options
  • Save samstephen/3b81623018fdcdb6d5c1 to your computer and use it in GitHub Desktop.
Save samstephen/3b81623018fdcdb6d5c1 to your computer and use it in GitHub Desktop.
Shopping Cart
# empower my program with SQLite
require "sqlite3"
# load/create our database for this program
CONNECTION = SQLite3::Database.new("users.db")
# dropping tables to reset the database, can comment out if you'd like to keep history
CONNECTION.execute("DROP TABLE IF EXISTS customers;")
CONNECTION.execute("DROP TABLE IF EXISTS products;")
CONNECTION.execute("DROP TABLE IF EXISTS orders;")
CONNECTION.execute("DROP TABLE IF EXISTS order_items;")
# transforms sqlite tables(or rows/columns) to ruby hashes
CONNECTION.results_as_hash = true
# creating tables (no need for "IF NOT EXISTS" because tables will be deleted immediately when loading app.rb)
CONNECTION.execute("CREATE TABLE customers (id INTEGER PRIMARY KEY, name TEXT, card TEXT, phone TEXT, street TEXT, city TEXT, state TEXT, zip TEXT);")
CONNECTION.execute("CREATE TABLE products (id INTEGER PRIMARY KEY, product_name TEXT, current_cost REAL, category TEXT, brand TEXT, retailer TEXT);")
CONNECTION.execute("CREATE TABLE orders (id INTEGER PRIMARY KEY, customer_id INTEGER, purchased_on TEXT);")
CONNECTION.execute("CREATE TABLE order_items (id INTEGER PRIMARY KEY, order_id INTEGER, product_id INTEGER, quantity INTEGER, item_cost REAL);")
#-----------------------------------------------------------------------------------------------------------------------
require_relative 'customer.rb'
require_relative 'product.rb'
require_relative 'order.rb'
require_relative 'order_item.rb'
# require_relative 'menu.rb'
require_relative "database_class_methods.rb"
require_relative "database_instance_methods.rb"
#-----------------------------------------------------------------------------------------------------------------------
#define some customers
# Customer.add(name, card, phone, street, city, state, zip)
Customer.add({'name' => 'Sam Stephen', 'card' => '1234123412341234', 'phone' => '4024324292',
'street' => '221 N 6', 'city' => 'Elmwood', 'state' => 'NE', 'zip' => '68349'}) #1
Customer.add({'name' => 'Joe Poole', 'card' => '4567456745674567', 'phone' => '4022971421',
'street' => '1324 S 5', 'city' => 'Lincoln', 'state' => 'NE', 'zip' => '68501'}) #2
Customer.add({'name' => 'Daniel Mariscal', 'card' => '9876987698769876', 'phone' => '4025555555',
'street' => '134 Regency Court', 'city' => 'Omaha', 'state' => 'NE', 'zip' => '68234'}) #3
#define some products
# Product.add(product_name, 'current_cost', 'category', 'brand', 'retailer')
Product.add({'product_name' => 'KeyLab 61', 'current_cost' => 499.00,
'category' => 'Instrument', 'brand' => 'Arturia', 'retailer' => 'Guitar Center'}) #1
Product.add({'product_name' => 'Axiom Pro 25', 'current_cost' => 399.99,
'category' => 'Instrument', 'brand' => 'Avid', 'retailer' => 'Best Buy'}) #2
Product.add({'product_name' => 'Blue Yeti USB Microphone', 'current_cost' => 129.99,
'category' => 'Recording', 'brand' => 'Blue', 'retailer' => 'Best Buy'}) #3
Product.add({'product_name' => 'KRK KNS 8400 - headphones', 'current_cost' => 149.99,
'category' => 'Recording', 'brand' => 'KRK Systems', 'retailer' => 'Guitar Center'}) #4
Product.add({'product_name' => 'KRK VXT 8 Powered Studio Monitor', 'current_cost' => 599.00,
'category' => 'Recording', 'brand' => 'KRK Systems', 'retailer' => 'Guitar Center'}) #5
Product.add({'product_name' => 'Pro Tools 9', 'current_cost' => 399.00,
'category' => 'Software', 'brand' => 'Avid', 'retailer' => 'Best Buy'}) #6
Product.add({'product_name' => 'Logic Pro X', 'current_cost' => 199.00,
'category' => 'Software', 'brand' => 'Apple', 'retailer' => 'Guitar Center'}) #7
#define some orders
# Order.add(customer_id, date)
Order.add({'customer_id' => 1, 'purchased_on' => '12-20-2010'}) #1(primary key)
Order.add({'customer_id' => 1, 'purchased_on' => '05-16-2011'}) #2
Order.add({'customer_id' => 2, 'purchased_on' => '01-05-2012'}) #3
Order.add({'customer_id' => 1, 'purchased_on' => '07-20-2012'}) #4
Order.add({'customer_id' => 2, 'purchased_on' => '03-22-2014'}) #5
Order.add({'customer_id' => 2, 'purchased_on' => '06-01-2015'}) #6
Order.add({'customer_id' => 1, 'purchased_on' => '06-01-2015'}) #7
#define some order_items
# OrderItem.add(product_id, order_id, quantity)
OrderItem.add({'product_id' => 1, 'order_id' => 2, 'quantity' => 1}) #1(customer_id)
OrderItem.add({'product_id' => 2, 'order_id' => 1, 'quantity' => 1}) #1
OrderItem.add({'product_id' => 3, 'order_id' => 5, 'quantity' => 1}) #2
OrderItem.add({'product_id' => 4, 'order_id' => 4, 'quantity' => 1}) #1
OrderItem.add({'product_id' => 5, 'order_id' => 3, 'quantity' => 1}) #2
OrderItem.add({'product_id' => 6, 'order_id' => 6, 'quantity' => 2}) #2
OrderItem.add({'product_id' => 7, 'order_id' => 7, 'quantity' => 1}) #1
OrderItem.add({'product_id' => 7, 'order_id' => 5, 'quantity' => 1}) #1
#-----------------------------------------------------------------------------------------------------------------------
#menu.rb
# Log in / Sign up
puts "Welcome to Audio Friend! ^_^ "
puts "Please, (L)og In or (S)ign Up! "
puts "To (Q)uit Audio Friend, type 'q' "
print ">> "
answer = gets.chomp.downcase
while answer != "q"
if answer == "l"
puts "Select who you are. "
Customer.all.each do |customer|
puts "#{customer.id} - #{customer.name}"
end
print ">> "
customer_id = gets.chomp.to_i
Customer(customer_id).all.each do |customer|
puts "Welcome #{customer.name}"
end
elsif answer == "s"
puts "Enter your first and last name."
name = gets.chomp.to_s
print ">> "
puts "Enter your credit card #."
card = gets.chomp.to_s
print ">> "
puts "Enter your phone #."
phone = gets.chomp.to_s
print ">> "
puts "Enter your street address."
street = gets.chomp.to_s
print ">> "
puts "Enter your city."
city = gets.chomp.to_s
print ">> "
puts "Enter your state."
state = gets.chomp.to_s
print ">> "
puts "Enter your zip code."
zip = gets.chomp.to_s
print ">> "
new_customer = Customer.new(name, card, phone, street, city, state, zip)
new_customer.add
puts "Welcome to Audio-Friend, #{new_customer.name}"
else
puts "Sorry, incorrect choice."
end
end
require_relative "database_class_methods.rb"
require_relative "database_instance_methods.rb"
class Customer
extend DatabaseClassMethods
include DatabaseInstanceMethods
attr_reader :id
attr_accessor :name, :card, :phone, :street, :city, :state, :zip
# Initializes a new customer object.
#
#options
#id (optional) - Integer of a customer's record in the 'customers' table.
#name (optional) - String of a customer's name.
#card (optional) - String of a customer's credit card payment info.
#phone (optional) - String of a customer's phone number
#street (optional) - String of the customer's street.
#city (optional) - String of the customer's city.
#state (optional) - String of the customer's state (abbrv).
#zip (optional) - String of the customer's zip code.
#
# Examples:
# Customers.new({"name" => "Sam", "card" => "1234123412341234", "phone" => "4024324292", "street" => "221 N 6", "city" => "Elmwood", "state" => "NE", "zip" => "68349"})
#
# Returns a Customer object.
def initialize(options={})
@id = options["id"]
@name = options["name"]
@card = options["card"]
@phone = options["phone"]
@street = options["street"]
@city = options["city"]
@state = options["state"]
@zip = options["zip"]
end
# Find a customer name by id using find method from database_class_methods.rb
#
#customer_id - The customers table's Integer ID.
#
# Returns a Customer object
def self.find_as_object(customer_id)
@id = customer_id
results = Customer.find(customer_id).first
Customer.new(results)
end
end
require "active_support"
require "active_support/inflector"
# This module will be **extended** in all of my classes. It contains methods
# that will become **class** methods for the class.
module DatabaseClassMethods
# Get all of the rows for a table and convert hashes to objects
#
# Returns an Array containing Class objects.
def all
# Figure out the table's name from the class we're calling the method on.
table_name = self.to_s.pluralize.underscore
results = CONNECTION.execute("SELECT * FROM #{table_name}")
results_as_objects = []
results.each do |results_hash|
results_as_objects << self.new(results_hash)
end
return results_as_objects
end
# Add a new record to the database.
#
# options - hash
#
# Returns an Object.
def add(options)
table_name = self.to_s.pluralize.underscore
column_names = options.keys
values = options.values
individual_values = []
values.each do |value|
if value.is_a?(String)
individual_values << "'#{value}'"
else
individual_values << value
end
end
column_names_for_sql = column_names.join(", ")
individual_values_for_sql = individual_values.join ", "
CONNECTION.execute("INSERT INTO #{table_name} (#{column_names_for_sql}) VALUES (#{individual_values_for_sql});")
options["id"] = CONNECTION.last_insert_row_id
self.new(options)
end
# Get a single row.
#
# record_id - The record's Integer ID.
#
# Returns an Array containing the Hash of the row.
def find(record_id)
# Figure out the table's name from the class we're calling the method on.
table_name = self.to_s.pluralize.underscore
CONNECTION.execute("SELECT * FROM #{table_name} WHERE id = #{record_id}")
results_as_objects = []
results.each do |results_hash|
results_as_objects << self.new(results_hash)
end
return results_as_objects
end
# "Deletes" a row from a table
#
# record_id - The record's Integer ID.
#
# Returns an empty array
def delete(record_id)
table_name = self.to_s.pluralize.underscore
CONNECTION.execute("DELETE FROM #{table_name} WHERE id = #{record_id}")
end
end
require "active_support"
require "active_support/inflector"
# This module will be **included** in all of my classes. It contains methods
# that will become **instance** methods in the class.
module DatabaseInstanceMethods
# "Gets" the value of a field for a given row from a table.
#
# field - String of the column name.
#
# Returns the String value of the cell in the table.
def get(field)
# Figure out the table's name from the object we're calling the method on.
table_name = self.class.to_s.pluralize.underscore
# Get the first/only row as a Hash.
result = CONNECTION.execute("SELECT * FROM #{table_name} WHERE id = #{@id}").first
# Return only the value for the key of the field we're seeking.
result[field]
end
# Change a row's cell info by id
#
# table_name - table of the class
# column - String
# value - String
# id - Integer
#
# Update the name of a product
def update_cell(column, value)
table_name = self.class.to_s.pluralize.underscore
CONNECTION.execute("UPDATE #{table_name} SET #{column} = '#{value}' WHERE id = #{@id}")
end
end
require_relative "database_class_methods.rb"
require_relative "database_instance_methods.rb"
class Order
extend DatabaseClassMethods
include DatabaseInstanceMethods
attr_reader :id
attr_accessor :customer_id, :purchased_on
# Initializes a new Order object.
#
#id (optional) - Integer of a order's record in the 'orders' table.
#customer_id (optional) - Integer of a order's name.
#purchased_on (optional) - String of a order's credit card payment info.
#
# Returns a Order object.
def initialize(options={})
@id = options["id"]
@customer_id = options["customer_id"]
@purchased_on = options["purchased_on"]
end
# Lists all orders. Includes the total cost of an order
def self.list_all_orders
CONNECTION.execute('SELECT orders.id, orders.customer_id, orders.purchased_on, SUM(order_items.quantity * order_items.item_cost) FROM orders, order_items WHERE orders.id = order_items.order_id GROUP BY orders.id, orders.customer_id, orders.purchased_on;')
end
# Lists orders of a customer. Includes the total cost of an order
def self.list_orders_of_customer(customer_id)
CONNECTION.execute("SELECT orders.id, orders.customer_id, orders.purchased_on, SUM(order_items.quantity * order_items.item_cost) FROM orders, order_items WHERE orders.id = order_items.order_id AND orders.customer_id = #{customer_id} GROUP BY orders.id, orders.customer_id, orders.purchased_on;")
end
end
require_relative "database_class_methods.rb"
require_relative "database_instance_methods.rb"
class OrderItem
extend DatabaseClassMethods
include DatabaseInstanceMethods
attr_reader :id
attr_accessor :product_id, :order_id, :quantity
# Initializes a new OrderItem object.
#
#id (optional) - Integer of a order item's record in the 'order items' table.
#product_id (optional) - Integer of a order's product_id.
#order_id (optional) - Integer of a order's order_id.
#quantity (optional) - Integer of a order item's quantity.
#
# Returns a OrderItem object.
def initialize(options={})
@id = options["id"]
@product_id = options["product_id"]
@order_id = options["order_id"]
@quantity = options["quantity"]
end
# adds a new "item" to an existing order.
# ("item_cost" is figured by "product_cost" in "products table" when added to "order_items table")
def self.add_order_item(product_id, order_id, quantity)
item_cost = product_cost(product_id)
CONNECTION.execute("INSERT INTO order_items (product_id, order_id, quantity, item_cost) VALUES (#{product_id}, #{order_id}, #{quantity}, #{item_cost});")
end
# finds "current_cost" of product based on it's "product_id", returns value to "product_cost" method
# need to separate the two costs, because cost can change - order cost doesn't change.
def self.product_cost(product_id)
product = Product.new(product_id)
product.find_current_cost
end
# lists all order items and includes item_cost as item_total in order_items table
def self.list_all_order_items
CONNECTION.execute("SELECT *, quantity * item_cost as item_total FROM order_items;")
end
# Show all items purchased in an order by order_id
def self.list_items_in_an_order(order_id)
CONNECTION.execute("SELECT *, quantity * item_cost as item_total FROM order_items WHERE order_id = '#{order_id}';")
end
# Selects a row from the order_items table by id and includes the total of item_cost
def get_item
CONNECTION.execute("SELECT *, quantity * item_cost as item_total FROM order_items WHERE id = '#{@id}';")
end
end
require_relative "database_class_methods.rb"
require_relative "database_instance_methods.rb"
class Product
extend DatabaseClassMethods
include DatabaseInstanceMethods
attr_reader :id
attr_accessor :product_name, :current_cost, :category, :brand, :retailer
# Initializes a new product object.
#
#id (optional) - Integer of a product's record in the 'products' table.
#product_name (optional) - String of a product's name.
#current_cost (optional) - Real of a product's current cost in 'products' table
#category (optional) - String of a product's category.
#brand (optional) - String of a product's brand.
#retailer (optional) - String of a product's retailer.
#
# Returns a Product object.
def initialize(options={})
@id = options["id"]
@product_name = options["product_name"]
@current_cost = options["current_cost"]
@category = options["category"]
@brand = options["brand"]
@retailer = options["retailer"]
end
# Find a customer name by id using find method from database_class_methods.rb
#
# product_id - The products table's Integer ID.
#
# Returns a Customer object
def self.find_as_object(product_id)
@id = product_id
results = Product.find(product_id).first
temp_name = results["product_name"]
temp_cost = results["current_cost"]
temp_category = results["category"]
temp_brand = results["brand"]
temp_retailer = results["retailer"]
Product.new(product_id, temp_name, temp_cost, temp_category, temp_brand, temp_retailer)
end
#
# Update the current_cost of a product
def change_product_cost(current_cost)
CONNECTION.execute("UPDATE products SET cost = #{current_cost} WHERE id = #{@id}")
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment