Sinatra Project Build

Loren Cipriano
8 min readMar 6, 2021

Here we are again, project time! The second project for Flatiron School, using Sinatra and Active Record. It is required to create an application that utilizes the CRUD, and MVC logic. Let me explain, the following will cover the project requirements, I will be attaching links of things to consider at the end of this walkthrough.

Corneal Gem

Started by using the corneal app to build the structure (all files required) for my app. Clearly, you are more than welcome to create it from scratch. This gem allows us to create the directory structure as follows. Spec file was deleted, I didn’t include tests in my application.

Build an MVC Sinatra App

  • Models: The ‘logic’ of a web application. This is where data is manipulated and/or saved — will have the files such as User, Post, Comment. This represents data and logic by writing/creating a ruby Class that interacts with SQLite (database) through Active Record.
  • Views: The ‘front-end’, user-facing part of a web application — this is the only part of the app that the user interacts with directly. Views generally consist of HTML, CSS, and Javascript. This is where you apply what user can see on the browser
  • Controllers: The go-between for models and views. The controller relays data from the browser to the application, and from the application to the browser. Treat it as a messenger/translator.

Using ActiveRecord

is an ORM (object-relational mapping) library. This maps objects to the database tables, allowing to store and retrieves data.

  • Represent models and their data.
  • Represent associations between these models.
  • Represent inheritance hierarchies through related models.
  • Validate models before they get persisted to the database.
  • Perform database operations in an object-oriented fashion.

There are base classes from this ORM that we can then inherit to our classes so we do not have to write them ourselves, in my project’s case I’ve inherited into ApplicationController, then inherited from ApplicationController onto my classes with additional methods.

class ApplicationController < Sinatra::Base
(additional methods)
end
class SkatersController < ApplicationController
end
(Some base classes available)
initialize
save
all
update
destroy
etc etc.

Rake Migration and Database

We use the rake gem along with activerecord so we no longer have to create and organize our database ourselves as well by utilizing rake actions through the console and checking the schema to see if our database table has been created. Run ```rake -T``` to see the commands available.

db (database) folder will be created soon after “migrate-ing”check schema once finished. For more sources and clarification check out the sources at the end of this article.

Config.ru

(Based on my own application)

  • require application file
  • run to start application represented by ruby class Application (in app.rb)
require './config/environment'
use Rack::MethodOverrideuse SkatersControlleruse PostsControllerrun ApplicationController

Other required files and folders that needs to be finished before starting MVC and get your application to run:

-Gemfile
-Rakefile
-Config/environment.rb

The rest of the required action are:

-have multiple models 
-has_many and belongs_to associations
-User ablility to Sign Up, Sign In, Log Out
-perform CRUD actions ONCE user is logged in only
-Validates user
-Does not perists "bad data" == empty strings / empty contents in post
-BONUS: to have error messeges

Once everything was set up I started in Models of my MVC.

Models

  • Skater — has_many: posts
  • attributes: check shema
  • Post — belongs_to: skater
  • attributes: check schema

I was able to associate the two models due to the power of implementing a foreign_key. Foreign keys are implemented in the model in which belongs_to another, in this case my Post model. Did you notice it in my schema where I created a column for the foreign key? If not feel free to go back and skim through it.

Controllers and Views

Is where I start up next, this is where it gets a little tricky and quite honestly took me sometime to get used to — how to navigate through and test my application. I find it most useful to create a controller(singular) and constantly going back and forth between the view file and controller file for a specific model. All the while I had my shotgun running in the background, then make sure the routes are completely done for that view page, and then move on to the next controller action. (Check out “Live Server” in VSCode so you don’t constantly have to run shotgun each time you make a change in your code, you can simply refresh the page to see the changes).

This diagram below helped me a lot, understanding the HTTP routes and how controller action correlates to each routes.

Find sinatra link below for more detailed information.

Skater Controller

Consist of my routes:

  • Sign Up → get and post routes → Where we create a new instance of a Skater, CHECK if its an invalid entry such as; empty strings, and user already exist, if so render error msg. If not invalid, save it in the database and store it in session, THEN redirect to ‘/posts’ (I’ll get to it in post controllers in a sec)
  • Log In → get and post routes → where we FIND the user by its username, authenticate password and again set up session with the found username, redirect once again to my ‘/posts’ route.
  • Log Out → get → where we clear the session.

Post Controller

  • get ‘/posts’ → where my user gets redirected to after sign up or log in. Where I show all my posts, in descending order and render index page (consists of all posts) IF logged in, if not user gets an error message of “Let’s get you logged in or sign up first! :)”.
  • get ‘/posts/new’ → again if logged in, render new.erb page which consists of my attributes to be filled out by user.
  • post ‘/posts’ → is what creates the data to be sent to the server. Here I made sure that the user is not inputting “BAD data” like empty strings, the user will get an error message stating that the content must be filled out before posting. If its “good data” we create a new instance of a post, match it with the skater's session, then persist it into our database. Lastly, redirect the user to ‘/posts/#{@post.id}”
  • get ‘/posts/:id’ → finds the post by its id(see code below), and then renders ‘/posts/show’ → show.erb consists of regular text, and is an ERB file (embedded Ruby) allows us to write ruby code as well. My show page consists of the same form that was just filled out but this time, it was persisted. I gave the option to my user to either delete, or edit the post they just created here.
@post = Post.find_by(id:params[:id])
  • get ‘/posts/:id/edit’ → if my user ever clicks on an edit button which they can only do so with their own posts, this get route will GET that post, and render my edit page. → edit.erb allows the user to edit the desired post and still have the previous contents along with it. In here I gave the user the option to also delete the post.
  • patch ‘/posts/:id’ → this allows the edited posts to be updated in the database. AGAIN finds the posts, if content fields are empty stay on this page and render an error message, if it is NOT empty UPDATE (see code below) .
@post.update(trick_to_learn: params[:trick_to_learn], description: params[:description], link: params[:link], accomplished: params[:accomplished])redirect "/posts/#{@post.id}"
  • delete ‘/posts/:id’ → Lastly we need to make it available for users to be able to delete their post, we’re all just humans, after all. We change our minds or make mistakes constantly. We find the post again with the code stated above then use the method made available to us through Sinatra::Base .destroy. Redirect back to ‘/posts’

Extra:

I wanted my application to be able to have their own page where they only see their own posts in that designated link. I created another route and called it ‘/mypage’.

get '/mypage' do
if current_user
@posts = Post.all
erb :"/posts/mypage"
end
end

If the current_user is logged in, show all the post from that user, render the mypage.erb.

Do you see why it can be confusing, and took me a while to get used to the back and forth switching between files and browser? I sure do hope this guide helped a little bit, and if not I hope you find what works best for you.

Links:

--

--