Let’s Build a Sinatra App: Using MVC, CRUD and RESTful Routing

What is Sinatra, MVC, CRUD and RESTful routing?

According to Wikipedia, Sinatra is a free and open source software web application library and domain-specific language. It is a simple option to build a web application quickly using the Rack web server interface.

Model-View-Controller is a pattern used in popular programming languages to develop distinct, yet interconnected parts of an application. Simply put when a user interacts with a web application, it begins a cycle of the controller manipulating the model, updating the view and on until the user logs out of the current session.

Lastly, CRUD and RESTful routes round out how a user interacts with a web page. CRUD stands for Create, Read, Update and Delete; REST is Representational State Transfer.

Imagine going to Twitter.com for the first time and signing up as a new user; a new user is created. This is the “create” in CRUD and the signup page used a get HTTP request to render the sign up form and a post HTTP request to create the user, then direct the user to their page. The same for any tweets the user creates. Every time a user goes to their page to view their tweets, they are “reading” their page. When a user “updates” or “deletes” a tweet, a patch or a delete request is sent to the server. For more information on how CRUD and RESTful Routing works, check out the Ruby on Rails API guide.

Getting Started

Before I coding my application, I thought about what I wanted to build, the models to use (along with their attributes and associations), determine the minimum viable product to get the application working and finally stretch goals to make the application user-friendly, efficient and DRY.

I decided to build a web app for tech conferences because I’ve attended quite a few conferences since I’ve been on my coding journey and they all had a different focus/purpose. In the application, a user can sign up/log in and view other conferences added by other users as well as their own. Only a user can edit/delete a conference that they created. A user has many conferences and a conference belongs to a user.

I also used validations to confirm a user’s email/password and made sure they entered the requested information to sign up or log in. Conferences need a name, location, date, and category (women, diversity, coding, hackathon, open source, mixed, etc.)

Now I was ready to code. I installed the corneal gem that a former Flatiron School student built as a Sinatra application generator for future users who needed a simple Sinatra web application. Once I had the gem installed, I generated the app by running corneal new APP-NAME then bundle install. I ran shotgun in the terminal to make sure I installed everything correctly.

Once I had the app going, I initialized my repository on GitHub and connected the local repository on my computer to GitHub.

Note: commit early and often. When building a project, committing code that you want to keep is not only helpful for future debugging but also to memorialize any meaningful changes you want to keep.

I made 93 commits for this project!

Build ActiveRecord Migrations

The cool thing about the corneal gem is that you can run commands to generate a model or scaffold the entire MVC structure including a migration file. But I chose to go the local route and build the migrations, models, views, and controllers.

I created a migration each for the users and conferences tables. Each user has a name, email, and password digest. Each conference has a name, location, category, date, and a foreign key column for the user_id because a conference belongs to the user.

Then I built the user and conference models with the appropriate associations. The user model has_many :conferences and has_secure_password, which is the bcrypt macro to validate the password. The conference model belongs_to:user.

Then I created a seed file for the database so I had some users/conferences to work with. Finally, I migrated and seeded the database.

Note: if you need to clear out your database, delete development.sqlite file and re-run db:migrate and db:seed to start fresh.

Build controller actions and views one by one then view in shogun.

Always add dynamic routes like ‘/conferences/:id’ after ‘/conferences/new’ because the controller action will think that the ‘/conferences/new’ is a dynamic route and will not read that route first when you want to create a new conference.

As new routes are added, it’s good to exit and re-run shotgun to make sure changes take effect.

I think one interesting thing to building this app was making sure I iterated to show specific details in the show.erb file for the user. I had to go back and look at other code I created, to make sure I had the user who was logged in and then iterate over the user’s conferences collection to get the name of the conference and other details I wanted to display.

I added a few stretch goals added to this project:

  • ActiveRecord validations in the user model to validate the presence of name and email and that the email was unique.
  • Flash messages and errors logic were added to the layout.erbfile to display when a user correctly signed up or logged in or did not enter the correct information.
What a flash message and flash error looks like in the controller action.
  • I added the gem "sysrandom"for the session_secret to secure the session id. Read more here about using this gem as well as here about securring sessions.

The biggest challenge with this project

So, I wanted to have a date column in my table. When I first seeded my database, the first issue I ran into is that I had an Invalid octal digit (a leading zero: 07-11-2019). I then removed the leading zero for the dates that had one digit month or day.

date as an integer in the seeds file
date as a fixnum in the browser

After more googling and inquiring, I learned I needed to require the date gem. This gem runs on Ruby version 2.5.0 (I had to update the version on my project from 2.3.0 to 2.5.0); I then needed to change the bundler version to work with the updated ruby version in my project.

After all of this work, I still had some trouble getting the date to display the way I wanted. So I made a change to the conferences table. I created a new migration for change_column_date to change the date to a text datatype. I also changed the dates in my seed file to a string ‘1/10/2019′.

In the SQLite documentation, there is a list of accepted data types and date happens to be one of those that is not really supported, so you have to enter it as text, real, or integer.

Once I updated the column datatype to text, the app allowed the date to be entered as a string works in which the user can type the date as 1/10/2019 or 1-10-2019.

The last update I made to the date format was to change the input type in the views from text to date in the new.erb and edit.erb files so there’s consistency in entering and viewing dates.

Input type=”date” name=”date” in new.erb file

Stretch goals for updates to this project

Some of the stretch goals I thought of for my project are to:

  • Bootstrap CSS to make the website more user-friendly.
  • Google maps gem to show conference locations
  • Testing with Capybara and RSpec

Last thing to note, read the documentation for any programming language, framework, gems, etc., before coding your application. Had I read the SQLite3 docs, I would have known that the date datatype is not supported and to enter the date as text.

Like they say, “You live and you learn.”

Check out the GitHub repo: https://github.com/AlwinaO/conferences

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.