README
Project Description
This project is a fictional backend and partial frontend for an online grocery service. In future, I would like to finish the frontend views and ensure that a user could remove items from an order that has not yet been completed.
Installation Instructions
Version
This repo uses Ruby 2.3.1 and Rails 5.1.6. Two libraries were used. 1) RSpec, for testing, which Rails uses by default. 2) money-rails, which is a rails version of the Ruby money gem. It makes it easier to store currency values, and I felt that items and orders should have a price associated with them.
Mac users
If you have a Mac, Ruby is already installed on your machine, but if you have not already installed the Rails gem, you will need to install it. If you do not also have the bundler gem, which allows you to install all gems for a project at once, you will also need to install that. Here's how to do that:
- From your terminal, run
gem install rails
- Once that completes, run
gem install bundler
Windows users
Follow the instructions on RubyInstaller.org
Set up the project
You can either download the zipped project from the download link above, or clone the repo onto your own machine. If you are cloning, navigate to the directory where you would like the repo to live by using your terminal, and then copy the following command into your terminal: git clone https://github.com/cscov/store-no-8.git
Installing gems
Once the project has been downloaded, run the following command in your terminal: bundle install
Database creation and initialization
Once the project has downloaded to your machine and the gems have installed, run the following command in your terminal to set up the database and seed it:
rails db:setup
Server
Once the database has been created, you need to set up your local server to interact with the project in your browser.
- First, open a new tab in your terminal
- Run the following command:
rails s
- In your browser, copy the following URL into the browser bar:
localhost:3000/
Once there, you should be able to see the login screen and be able to click around as expected.
How to test
- Open a new tab in your terminal
- To execute all tests at once, run the following command:
bundle exec rspec
Project Details
Tables
users
Column Name | Data Type | Details |
---|---|---|
id |
integer | primary key, not null |
first_name |
string | not null |
password_digest |
string | not null |
session_token |
string | not null |
email_address |
string | not null, unique, indexed |
-
Index on
id
because primary keys are always indexed and onemail_address
for fast lookup of a common search term, and because it is also required to be unique. -
Additions:
password_digest
andsession_token
were added in order to facilitate backend user authentication. I wanted to do authentication because in the scenario of users and orders, users should only be able to see their own orders. For that to happen, they must be authenticated.
orders
Column Name | Data Type | Details |
---|---|---|
id |
integer | primary key, not null |
user_id |
integer | foreign key, not null, indexed |
order_status |
string |
-
Index on
id
. Index onuser_id
because it is convention to create an index on foreign keys, and because this way, a given user's orders can be pulled up more quickly. -
Additions:
order_status
was added to indicate whether an order was able to be updated or cancelled. The options for this attribute are "processing" and "completed". "Processing" indicates the order can be edited or cancelled, while "completed" indicates that it is too late to make any changes. Items will be covered under associations.
items
Column Name | Data Type | Details |
---|---|---|
id |
integer | primary key, not null |
name |
string | not null |
price |
decimal | precision: 8, scale: 2 |
price_cents |
integer | not null, default: 0, Ruby Money object |
price_currency |
string | not null, default: "USD" |
-
Index on
id
. -
Additions:
price
was added because in a real world scenario, every item in an order would have a price.price_cents
andprice_currency
are part of the money-rails library and help with currency conversion.
order_items
Column Name | Data Type | Details |
---|---|---|
id |
integer | primary key, not null |
order_id |
integer | foreign key, not null, indexed |
item_id |
integer | foreign key, not null, indexed |
-
Indexes on
id
,order_id
,item_id
-
This joins table was added to create a many-to-many association between orders and items.
Models
users
-
Associations: A
user
has manyorders
and has manyitems
throughorders
-
Other Validations: The user's password must be at least 6 characters
orders
- Associations: An
order
has manyorder-items
and has manyitems
throughorder-items
. Anorder
also belongs to auser
.
items
- Associations: An
item
has manyorder_items
and has manyorders
throughorder_items
order_items
- Associations: An
order_items
belongs to anorder
and belongs to anitem
Controllers and Routes
users
GET users/new
renders the sign up viewPOST users
adds a new user to the database and redirects to the user's orders page- Permitted params:
first_name
,email_address
,password
session
GET session/new
renders the log in viewPOST session
logs in the user and redirects to the user's orders pageDELETE session
logs the user out and redirects to the login view
orders
GET users/:user_id/orders
displays a list of all orders for the current userPOST users/:user_id/orders
adds a new order to the user's list of ordersGET users/:user_id/orders/:id
Displays a specific order for the current userGET users/:user_id/orders/:id/edit
Allows the current user to update a specific order if it has not yet been completedDELETE users/:user_id/orders/:id
Deletes the current order if it does not have an order status of "completed"
items
GET items
Displays a list of all available itemsGET items/:id
Displays a specific item
order_items
POST order_items
Adds an item to an orderDELETE order_items.id
Removes an item from an order
root
GET /
Displays a home screen with links to items and current user's orders
Views
Because this is a backend project, I decided to keep the route content rendered in html and embedded ruby templates rather than using JSON and a framework such as React to render the views.
global navigation
- When the user is not logged in, a 'log in' button and 'sign up' button appear at the top of the screen.
- When the user is logged in, a 'welcome, {user.first_name}' message appears at the top of the screen with a 'log out' button.
- The 'home' screen displays a link to the current user's orders and the item index. If no one is logged in, the order index link will redirect to the login view.
- A link to 'home' is always present
users
- New: Displays the sign up page
session
- New: Displays the login page
orders
-
Index: Displays the current user's orders. Order id links go to the 'order show' view
-
Show: Displays a specific order (items, item prices, order total, order status) for the current user. If the order status is "processing", there will be an 'edit order' button and a 'cancel order' button present.
-
Edit: Displays a particular order for the current user with the ability to add and remove items from the order, as well as cancel the order.
- An item will have an 'add to order' button next to it.
- Once it has been added to the order, it will appear in the order list with a 'remove from order' button next to it.
items
- Index: Displays a list of all items along with their prices.
- Show: Displays a page for a specific item. The page includes the item name and item price, as well as lorem ipsum nutrition facts.