Sinatra Project: Book Club Application
Published: 2021-01-10 22:18:47

I built a CRUD app using Sinatra and MVC. My Book Club app is made for users to post a review on their latest read book. CRUD stands for create, read, update, delete. These are the functions my user has after making their account. I will explain how the code works and how everything connects.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/bk2p6pfz3wb7yzebj6hm.png)

Above is my file structure. I used the gem Corneal to generate a Sinatra template. After getting the files set up, I thought about what my MVC would need. MVC stand for Models, Views, and Controllers. The Models job is to represent data from the database. The Views job is to work through HTML to set up what the user sees and interacts with. The Controller's job is to accept requests, relay the data, communicate with models, alter/delete data and send documents to clients. 

What type of data do I need in my models? I knew I would need a User and a Post model. I then added the appropriate Active Record associations. A Post belongs_to at User and a User has_many Posts. A belongs_to association sets up a connection with another model, such that each instance of the declaring model "belongs to" one instance of the other model. For example, my application includes users and posts, and each post can be assigned to exactly one user. Below is the code showing this:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/7is2wwmgkk0vueddhdwq.png)

Next, a has_many association indicates a one-to-many connection with another model. It is most common to have this association on the other side of a belongs_to association like I do here. This association indicates that each instance of the model has zero or more instances of another model. In my application containing users and posts, the user model looks like this:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/sl1bykjc2es7ez1vb2gy.png)

You can see in both Models I used Active Record to validate certain data so that bad data would not be saved into the database. You can see that I checked for the presence in most attributes and uniqueness in the email, people might have the same name but different accounts should have different emails. Something else we get from Active Record is has_secure_password. It sets and authenticates against a BCrypt password. This method requires me to have a password_digest attribute in my users table, as seen below:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/1p09mkim2hec7qx7u8gg.png)

Now that you have seen my models, let's go back a could of steps. Before I had even set up my models I needed a database, you can see it in my file structure as the db folder. In db/migrate I created a users table and a posts table and added the data that my application needed to run. Using the Rake gem, I ran rake db:migrate to create a schema file which is a graphical depiction of my database. I also made a seeds file in my db/migrate so that I could test my program early on with the data I put in there against any issues. Below is my posts table. I had a little bit of trouble with the singular and plural rules for tables and models. Ultimately I saw that this language was made to mimic how you would say it in English. Not with every aspect of Ruby but for this part tables are plural, as well as the class. Normally a class is singular but if you are CreatingPosts it would not make sense to be CreatingPost. It was something I had to talk out with my fellow classmates to be sure.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/mw6ay4lht66xp7ra7b0a.png)

So now that my databases have been migrated and my model relationships set up. It's time to give my app some Controllers. This is where I can put my data to work and see if I can get my website working. The controllers can get kind of long since they are responsible for all of the routing. I realized they did not flow as well as my last project where one menu let to another but I kept them as organized as possible. Below is my Application Controller:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/3yo7ml635ezuwtflz6sj.png)

This code does exactly what the title says, you see the first HTTP get request is just a "/" so this is the first step, I have a conditional statement that gives the application options to send the user to either the current user's index page if they are logged in or the welcome page if they are not. I then have my helpers which I will be using all throughout my controllers to give structure to my requests. It makes sense to define these methods here then call on them as needed. Next is my Posts Controller which contains my implementation of CRUD:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/n3y5akblnplwh71loacw.png)

If you remember, CRUD stands for Create, Read, Update, Delete. The post request would be the create. The patch request is the update. The delete request towards the end is for deleting. The get request in the middle that sends you to erb:'posts/show' is for reading. Within this code I have the power of CRUD. Without CRUD we would have no way to hold on to our data. The third and last controller is the Users Controller:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/649to2p06av04b8f5v8h.png)

This is where my user can log in/out and sign up. I have perams set up to specify what I need for someone to log back in or to sign up. Without those perams, my unique emails and passwords would be useless. Throughout all of my controllers, you have seen erb. This leads the program to my HTML code which is what the browser understands. I used the action and method attributes in HTML to connects to the /signup and post routes in the controllers. In views folder I have my layout, welcome page, and every other page the user has access to:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/axhln6vtb2b0iya643mp.png)

As you can see I have pages that refer to posts or users, then I have my welcome and layout pages outside of those folders. This is very helpful when setting up routes and redirects in the controllers. It is good to have an organized path to send your program to the correct pages. Most of these erb files are filled with colorful buttons or organized input lines. I also have if statements that allow me to only show login/sign up on the navigation bar when there is no user signed in. Additionally if someone is signed in they navigation bar will show all posts/my posts/create post/logout.

I enjoyed learning all these new skills. Its especially rewarding when you can make a change and see it right away on the browser. I would like to expand on the functionality of this application by adding a feature to rate the books on a 1-10 scale and then look up highly rated books. Also would like to have a place to search for books that others have reviewed and add to a "read later" list in the users profile.