This repository contains the source code for the better-read application, a clone of GoodReads, hosted on Heroku. See x`xthe live app at the following link: better-read. The overall structure of the application has been written in a rails project. The back-routes are within config/routes.rb, the frontend routes are within frontend/components/app.jsx. Rather than utilizing the traditional model view controller system of Rails, this application reduces the view component to only a few lines of jbuilder. This jbuilder will serve up the data as a javascript object to the frontend. The frontend is written in JavaScript using a React to render components to the page, and Redux to serve the state to the React component.
This application runs in Rails 5.1.
- Schema
- Features
- Usage
- Issues
The database used for this application is Postgres.
The structure of the tables can be seen below, and while it is omitted in each table, each entry has timestamps as well.
id | password_digest | session_token | |
---|---|---|---|
primary-key | example@example.net | x | y |
id | title | description | genre | cover |
---|---|---|---|---|
primary-key | example book | brief synopsis | example Genre | image url hosted on amazon web services |
id | owner_id | category |
---|---|---|
primary-key | users-foreign-key | have-read, will-read etc. |
id | rating | body | author_id | book_id |
---|---|---|---|---|
primary-key | Number of stars | review literal | user-foreign-key | book-foreign-key |
id | book_id | bookshelf_id |
---|---|---|
primary-key | book-foreign-key | bookshelf-foreign-key |
id | author | category | content | portrait |
---|---|---|---|---|
primary-key | quote speaker | funny, life, etc. | quote literal | image hosted on AWS. |
-
Demo Login
-
Account Creation on either home page or session page
-
User is logged in automatically upon creating account.
-
Account persists through logouts, and user can log back in.
-
If account creation or login are done improperly, the appropriate error response is rendered as well as the proper redirect.
-
The backend utilizes the ruby gem BCrypt as well SecureRandom to encrypt user passwords, and store the hashed values to protect user passwords. The user's password is never directly stored in the database.
def is_password?(password)
BCrypt::Password.new(self.password_digest).is_password?(password)
end
This ruby method converts the stored password digest string into a BCrypt object, then checks whether the passed password matches utilizing the is_password instance method of BCrypt.
-
Contains reviews as well as the overall rating for the book. On the book show page the user can rate the book a certain number of stars out of 5. The description of the book, as well as the title author and book cover are visible as well.
-
Books can be created at the link books/new which can be found on the create a book link in the main header bar when a user is logged in. If the user is not logged in the link will not appear.
-
A great challenge to creating books was allowing users to upload pictures and to host them, using the ruby paperclip gem, on amazon web services. Beyond simply constructing the dataForm object in the react component, the ajax call had to be written in a totally different way in order to serve up the formData.
export const createBook = (formData) => {
return $.ajax({
url: `api/books`,
method: "POST",
contentType: false,
processData: false,
dataType: "json",
data: formData,
});
};
- The Authentication step renders the correct errors at the right time and will also clear the errors if the user navigates to another part of the application. The clearance of errors was difficult to implement.
export const login = user => dispatch => (
APIUtil.login(user).then(user => (
dispatch(receiveCurrentUser(user))
), error => {
return dispatch(receiveErrors(error.responseJSON))
})
);
Here the thunk error action will dispatch the receiveErrors action if the promise returns an error rather than a user. The reducer then takes this action and serves it up to the state. Once this state is mapped to the session component's props, the renderErrors function then yields each error as a list element within an unordered list:
{ this.props.errors.map((err, index) => (
<li key={index}>
{ err }
</li>
))}
The error reducer file is responsible for reducing all the particular errors into the root reducer so that when the errors are ultimately served up to the state, all the errors can be found in one slice.
- React components on the page will suggest books to the user that may interest them. The user can select the book itself to be redirected to the book show page and see more information on the book.
To run this on localhost:3000, do the following:
-
Clone this repository
-
delete the gemfile.lock
-
run bundle install in terminal
-
run npm run webpack in terminal
-
Open localhost:3000 in a google-chrome browser.
-
When using the back button in browser, the book show page will sometimes fail to load.
-
Link to pages under construction render a blank page.
-
Non-users can create books without being logged in.
-
Book Preview on book creation page does not render.
-
Creating a username that already exists in the database.
-
Incorrectly creating a book.
-
updating an existing book the user created themselves.
-
writing a review and having it persist to the database.
-
Editing or Deleting user created review.
-
Add books to user shelves, as well as create custom shelves.
-
Robust Profile page displaying users shelves.