Creating My First Sinatra App
Tags: beginners, sql, ruby
Published: 2019-06-17 18:41:29

Beat Roaster is a Sinatra CRUD app that allows users to write reviews about their favorite music albums. Users are able to create accounts with a unique username, create albums to review, write reviews on albums in the database, edit their own reviews, and delete their own reviews.


# Creating the Foundation

I started out by using the Corneal gem to create the basic template for my app. This gem creates the basic file structure for the app as well as adding useful gems. Corneal also allows you to use generators to create models, controllers and more, however I didn't use this functionality.

Below you will see the basic file tree for my app:

![File Tree](https://thepracticaldev.s3.amazonaws.com/i/9s8hyo387qgi1pnaeyfe.png)

# Models

I decided on three models for my app: User, Album, and Review. The relationships are as follows:

- User has_many reviews and has_many albums, through reviews
- Album has_many reviews and has_many users, through reviews
- Review belongs_to user and belongs_to album

I could have just used has_many / belongs_to relationships, however I wanted to use the has_many through relationship to connect users to albums. I figured that in the real world, users have many albums that they listen to and albums are owned by many users, so this association made the most sense to me.

# Validations

I had a couple options on how to implement validations:

1. I could manually code the validations in the routes using if statements.

2. I could use ActiveRecord validations in my models.

I ended up using the ActiveRecord validations to cut down on unnecessary code and validated my attributes as follows:

- All data gathered from the user must be present. Blank strings won't be persisted to the database.

- Users must have unique usernames.

- Users can't create albums with the same name as another album that is already in the database.

I also used the bcrypt gem and the 'has_secure_password' macro to encrypt passwords in my database.

# Routes and Controllers

I utilized RESTful routes in my controllers in the following way:

- **ApplicationController** is set up as the parent controller in my app. It requires the necessary files and configures views and sessions. This is important because all of the other controllers inherit from ApplicationController. This controller only has one route: A GET request to the homepage. I also wrote two helper methods (to check if a user is logged in and to return the current user object) within this controller to use in my other controllers.

- **UsersController** has GET requests to render the user index page, signup form, login form, user page, and to log a user out. It has POST requests to create a user, and to login / authenticate a user.

- **AlbumsController** has GET requests to render the album index page, an individual album's page, and the form to create a new album. It has one POST request to create a new album.

- **ReviewsController** has GET requests to render the review index page, an individual review, the form to create a new review, and the form to edit a review. It has POST requests to create a new review and delete a review. This controller also has a PATCH request to edit a specific review.


# Styling and Yield in Layouts

One of the trickiest parts of building my app was figuring out how I wanted to style it. I ended up using a couple of CSS templates and tailoring them to my app. 

I integrated the first template directly in with my views for the homepage, login page, and show page. This template is pretty basic with just a background image and some font styling. In the routes for these pages, I had to specify not to render the views with the layout file like so:

    ```erb :'/users/new', :layout => false```


For the other pages, I used a layout.erb file with a CSS template and used `<%= yield %>` to render the view around the layout. This was pretty confusing at first to figure out the best spot to place yield and took some trial and error. 

# Wrapping it All Up

All in all this project was rewarding and fun to work on. I learned a lot about styling apps and how important it is to organize my to-dos prior to beginning to code. I found when I started my day without goals in mind, I jumped around a lot to implement different features and spent a lot of time on stretch goals before I had the basis of my app completed. I also struggled to remember to make regular github commits. In the future I would like to separate my work into specific features, each with their own commit. 

If I had more time, I would like to learn more about CSS to style my app further. Additionally, I would like to write more methods in my models to analyze user data, such as average ratings a certain user gives albums or average ratings of a specific album.


![Dog](https://media.giphy.com/media/3lxD1O74siiz5FvrJs/giphy.gif)

*If you would like to checkout my app, here is the [link](https://github.com/racheladaw/sinatra-music-review-app)!*