React | Redux | Ruby on Rails API Project - The Guitar Gallery
It all begins with an idea.
As my final portfolio project at Flatiron School I’ve created an alternate application of my previous projects, The Guitar Gallery, which is a continuation of the same concept but utilizing the React and Redux frameworks. What I enjoy about React/Redux is it’s easy integration as a frontend with a Rails API backend and Javascript as the programming language turning a static website into a dynamically functioning software with a user interface and a secure backend database.
Here is a demonstration of my application:
A user can either sign up by entering a username, password, as well as their city, state and country.
Once they hit the sign up button, They are brought to the homepage with a navigation bar and their username is displayed on the top right along with the ability to Log out.
The user can select from a multitude of pages to either view all of the auctions, or create a new auction, as well as view all of the guitars or create a new guitar.
An auction is created by entering a title, start date and end date, and a guitar is created by entering a guitar brand, model, year and price.
Once submitted the auctions and guitars will be displayed with the correct information from the user’s inputs.
App.js
App.js is the mainframe of the application. Here we have all of the components connected and we’ve imported react and router to create a switch in the DOM that will react based on events that occur when a user interacts with the page. I’ve created an object of App which extends the React component. Upon mounting the object, the current user will be retrieved based on the current session. We’ll render the loggedin, auctions and guitars functionality as properties of App, and establish the switch on the navigation bar, if the user has either signed up or logged in, the home navigation will appear along with an Indication of the current user by displaying the current user’s username. When logged in, there will be 4 paths available, to either view all the auctions, view guitars, create a new auction, or create a new guitar. I’ve included routes in the switch to finding guitars and users based on id, and edit functionality which I’ve included in the code but plan to expand on that functionality in the future. The mapstatetoprops will map the state of the current user, as well as auction and guitar form inputs based on the current state of the store. Finally, we will export the data to the current user of the app based on the state of the store.
Index.js
Index.js is where the entirety of the DOM is rendered. I’ve imported the essential tools such as the ReactDOM, Provider, Store and BrowserRouter. I’m also rendering the root document based on the element id and I’ve attached the provider, which is the store.
Components
In the components, the Home.js file is the page that opens at the startup of the app. Here is where a user will signup or login. In login.js, I’ve created the login object which will attach the login form and upon hitting submit the username and password will be rendered into the state.
Actions
The actions folder is where all the action takes place. In currentUser.js I’ve included the fetch requests for the login, logout and signup information of the user. Rails being hosted on localhost 3002 it’s using JSON to retrieve and send data to and from the backend. I’ve also created fetch requests for the guitar data in myGuitars.js and auction data from myAuctions.js. When a fetch request is triggered the store will dispatch a response of the data from the backend. In auctionForm as well as guitarForm and signupForm I’m getting, reseting, and deleting the information of the formData.
Reducers
In the reducers folder, we are declaring the initial state of the forms, which is typically an empty array of attributes. The reducers execute a switch response according to each case of entering the form data. Based on conditionals, the switch returns an action and the store will dispatch a response.
Store.js
The store is where the current state of all the components in the app are held. Using thunk as a middleware, redux is able to dispatch responses from the store to and from the frontend. Here we create a reducer which combines the components and then the store is exported to the application.
Building a Rails API
I’ve created a secure backend database with Rails so that we can store all of the information from the user’s inputs.
Models
The Users model is equipped with has_secure_password via the bcrypt gem to encrypt user’s private information. A user has many guitars and auctions. It validates a name, username to ensure that the user’s information exists in order to create a new instance of a user. A guitar belongs to a user and an auction. An auction belongs to a user, has many guitars, brands through guitars and models. An auction validates that a title and a user exists.
Controllers
I’ve included 4 controllers, sessions, users, auctions and guitars. In the sessions controller is where the user authentication logic takes place. This will ensure a user must be logged in and then it will store that session as the current user.
CORS
Cross-origin resource sharing (CORS) is a mechanism that allows restricted resources on a web page to be requested from another domain outside the server’s domain. Here I’ve stored my origins which include localhost servers 3000, 3001 and 3002.
Serializers
The Active Model Serializer is used to build the JSON objects. I’ve created 3 serializers, user, auction and guitar. This will allow the application to select only the information that the user is looking for.
Routes.rb
In my routes I’ve established the resources for all of the objects. I’ve specified post, delete and get requests for the signup, login, logout, and get current user functionality. This will connect the model to the controller.
Migrations
The notable migrations worth mentioned are add user id to auctions, add name to auctions, add auction id to guitars and add user id to guitars. This will establish the objects’ relationships in the database.
Gemfile
Some gems worth mentioning that are required in order to use rails with react are the web packer and react on rails gems, as well as fast jsonapi to connect the ruby data into javascript objects. Also the rack-cors gem which secures a server and prevents malicious hackers from entering the API.
Ruby on Rails Project - The Guitar Gallery
It all begins with an idea.
For my third project at Flatiron School I’ve created a continuation of the Sinatra project; a more in-depth version of the Guitar Gallery Auction app. The original app allows for a user to signup, log in, create an auction, create a guitar and then view all of the guitars available for the current auctions. This version allows for a user to create an auction in multiple locations nationwide. I’ve also added the functionality of signing up securely with a Facebook account, using the Omniauth gem. For usability, I’ve included some errors and checkers which will help the user enter in the correct information and prevent bad data from polluting the database of the app. Finally I’ve improved the user interface compared to the earlier version which is all text based. This application is an upgrade stylistically, in security and also in functionality.
I will now demonstrate a walkthrough of the app:
First, the user signs up, or if they already have an account they can simply login.
A user can create a new auction, enter a start and end date and hit submit.
They can then browse a list of all the current auctions.
A user can also add a new guitar to an existing auction, by selecting the respective auction title and then inputting the brand, model, year and price of that guitar.
By hitting submit they will add a guitar to an auction.
When viewing an auction, the user can see the list of guitars for that auction which they can also edit and delete.
A user can also edit the information of the auction.
Finally a user can view their personal account along with their own listings of auctions and guitars.
Creating The Models and Relationships
The models being Users, Auctions, and Guitars, it’s required that the relationships must be established. In this case, a Guitar belongs to a User and an Auction. A User has many auctions and guitars. I’ve also set some validations for the User to require a email, username and password and that the email and username are unique. The Auctions model validates that a title, start date and end date are present. A location has many auctions and an auction validates that a location exists, as well as a title, start date and end date. A guitar is validated with an auction_id, as well as a brand, model, year and price. Using a scope method, we can ensure that the guitars will be sorted alphabetically based on the guitar’s brand. In the user’s model I’ve created a method, “find or create from auth hash” which converts the information from a user’s Facebook profile to fill in the account information such as name, username, and email address.
Serializers
I’ve included 4 serializers, users, guitars, auctions, and locations which uses FastJSONapi to format the information in an organized manner via strings.
Setting Up The Views
The view is where we render and test the routes in the controller files. For each object, I’ve created a view for the index, create, edit and show pages. The forms were created using POST requests will allow us to grab the data from the user’s input. On the edit pages I’m using a PATCH request which will update the data from the user’s input. On the Users show page I’m using an ‘each’ loop to iterate over the indexes and for the user’s account they can view the guitars and auction’s they’ve personally created. In the objects’ ‘new’ pages I’m using a form_for to grab the user’s inputs and I’ve included error methods to improve the functionality of the app, informing users when they’ve entered incorrect information. In the layouts I’ve included a helper method for the errors. As for the layout, I’ve designed the navigation bar in application.html.erb. The nav links include the routes which communicates with the model via the controller. Sessions index contains the root page which displays the welcome header and if a user is not logged in they are prompted to login, and if they are logged in their username is displayed.
Building the Controllers
The controllers are responsible for handling the logic of the app. Here I’ve created controllers for the user, sessions, guitars and auctions objects. The controllers are equipped with methods such as index, show, create, new and destroy, along with strong params to narrow down the search in the database for precisely the information we’re requiring. This prevents errors or bad data being entered into the database. JSON objects are being used to render ruby into html formatting. The sessions controller is where the omniauth create method is stored. It converts third party user login info into user’s data which then gets stored in a session. The omniauth.rb file in the initializers folder is where my personal Facebook API key is located.
Routes
Here we can see the the routes for all of the objects. In the login routes, I have a session which is created via the omniauth provider, in this case Facebook, which will redirect to the index once logged in. There is a nested index route for joining users and auctions based on a combined id. I also have nested resources for joining users to their guitars.
Migrations
The migrations table is where we format the attribute columns in the database tables. I’ve created a table for all the objects, plus some tables to combine the auction_id to guitars, email to users, user_id to guitars and guitar_id to auctions. The schema also displays all of the objects and their attributes in the database tables.
Gemfile
Some interesting gems worth mentioning that were used to make this app are the omniauth gem to include all of the Facebook dependencies. The fast_jsonapi is used to build objects and convert them to information usable in web browser. Bcrypt is helpful to encrypt username and password data which ensures a secure login process for those signing up and logging in without using a third party app for login purposes.
Javascript | Rails API Project - The Guitar Gallery
It all begins with an idea.
For my fourth project I will be building The Guitar Gallery as a single page application using Ruby on Rails as a backend database. The guitar gallery is an online guitar auction and database that catalogs rare guitars that are currently up for auction. This app has 2 components, auction and guitar which we will combine so that we can see a list of current auctions and guitars available for those auctions. The “Create a New Auction” form will allow users to enter a title, start date and end date for their new auction. Once created, they can then add a guitar by entering the guitar brand, model, year, price and then they can select from a drop down list of current auctions.
index.html
This is the main page and navigation of the guitar gallery app. The style inherits it’s attributes from styles.css. The page has 3 containers, a Current Auctions container which displays the current auctions. We have the auction form, and the guitar form. At the bottom here is where the javascript scripts are rendered.
AJAX/Fetch
Asynchronous Javascript is a common technology that many websites use to dynamically present data. The frontend will use a multitude of Fetch requests to the backend in order to function properly. I’ve included 5 fetch requests to the API, to get auctions, create an auction, delete an auction, get guitars and delete a guitar. By accessing Rails via localhost 3000, we’re able to have the frontend and the backend communicating.
index.js
Here we have the point of contact of the class objects from the frontend to communicate to the backend using localhost 3000 with the API Host URL being auctions and guitars. We have an event listener with a DOMContentLoaded which loads the create auction form and the create guitar form as well as a fetch of the auctions as soon as the page loads. Once the user hits submit, it will trigger an event to create an auction or a guitar.
auction.js
Our get elements are listed at the top which are retrieving the data from the backend according to their ‘id’. Here we instantiate a class object of auction with the attributes of id, title, start date and end date. An auction retrieves the current array of guitars. The render auctions function fills in the auction select element in the guitar form with the auctions fetched from the backend. The renderAuctionsOptions function renders the auction select data and then clears that data once submitted to reset the form. The fetchAuctions function will retrieve the data for the auctions list and then executes the renderAuctions and renderAuctionOptions functions. The createAuction is an event. I’ve included an event.preventDefault which prevents the entire page from refreshing after submitting the auction form. The createAuction function is a Post method which sends the data form the user’s input to the database. We have our render function which will render instances of the auctions entered into each element and then functions to delete and reset the auctions. Finally, here is the fetch request to delete the auction from the database.
guitar.js
In the guitar.js component we have our get elements for all of the inputs in the guitar form correlating with the attributes of the guitar as well as an auction selection list to choose the auction which the guitar will belong to. I’ve created a class object of Guitar with attributes such as id, brand, model, year, and price. The createGuitar function will set an event that will fetch the user’s data for the guitar and send it to the database. The response will be that an auction is retrieved to attach the guitar and then the guitar form resets. We have a render method for the inner text of the guitar form inputs. Finally, here is the fetch request to delete a guitar from the database.
Ruby on Rails
In the Ruby on Rails backend we are creating a persisting database for the frontend. In the controllers we are creating auctions and guitars using a serializer with a JSON render to convert the ruby object into a javascript object. In the routes.rb I’ve stated the resources for the guitars and auctions objects. In the database I’ve added an auction_id column to a guitar so that we can apply a guitar to an auction.