Ricardo Ledesma

Dec 4, 2018

4 min read

Singing with Sinatra — Module 2 at Turing

Photo by Bogomil Mihaylov on Unsplash

The first project in Module 2 (Back-End) of Turing School of Software and Design is to build a simple web application using Sinatra and Active Record and testing with RSpec and Capybara.

The project was called Laugh Tracks and was meant as an introduction to Restful Routing and the MVC framework. This is my telling of the whole experience: my approach, challenges, and takeaways.

Approach

I approached the project with the intention to do as much TDD as possible (Test-Driven Development). I was successful for the most part but it was hard in the beginning to get started without having used RSpec or Sinatra before. Week 1 was a lot to learn all at once (HTTP request and response cycle, CRUD, RSpec, Sinatra, MVC, ActiveRecord, etc), all while working on the project

What I would recommend in these types of situations, where there are many interconnected concepts and techniques to learn that connect together, is to try and separate each component as much as possible and implement it sooner rather than later. To elaborate:

  • We went over the essential concepts using a very simple Sinatra server with ActiveRecord (migrations, associations, ORMs, Restful Routing)
  • During these simple exercises focus on the concepts, not the actual code. It can be difficult to understand what actually is a migration and a model and a controller while also trying to understand the intricacies of the ActiveRecord syntax

It really comes down to taking each component one step at a time and implementing it right away. Adding complexity as you go along and messing around with it to understand what is happening.

What is happening here??

class CreateSongs < ActiveRecord::Migration[5.1]
def change
create_table :songs do |t|
t.text :title
t.integer :length
t.integer :play_count

t.timestamps null: false
end
end
end

It’s easy to get hung up on the syntax here. Why is this a class? Why is the function called change and does (t) need to be called (t) in order for this to work?

  • I wouldn’t worry about that. Focus on what this actually is. It’s a way in which to alter the schema for a table in the database. A migration is used whenever you’re changing the schema (adding a column, creating the schema, changing a data type, etc)

My approach (once I had a better grasp on everything) was to understand enough to implement and then to implement. To do the thing.

  • The best way to learn, in most cases, is by doing.

Challenges

Something I always struggle with is to either attempt to refactor early or to do something in a way that I would consider to be the ideal before even having the core functionality started.

  • This came about as attempting to create a right join with the comedians and specials tables — so each comedian and their corresponding special (using a foreign key on specials) using ActiveRecord. I knew how to do this using raw SQL so I thought it would be simple using ActiveRecord. It was not.

I was attempting to optimize my queries to the database before even understanding ActiveRecord. Rather than doing what I did below.

<section class="comedians">
<% @comedians.each do |c| %>
<section class="comedian">
<div class='comedian-info'>
<p>Age:</span> <%= c.age %></p>
<p>Hometown:</span> <%= c.city %></p>
</div>
<div class='specials'>
<% c.specials.each do |s| %>
<div class='special'>
<p>Special Name: <%= s.name %></p>
<p>Length(minutes): <%= s.run_time_minutes %></p>
<img src="<%= s.image_url %>" alt="<%= s.name %>">
</div>
<% end %>
</div>
</section>
<% end %>
</section>

I was trying to create a table beforehand in the controller and pass that to the view. Rather than having all this logic in the view.

The point is to not attempt to create the ideal implementation before working through the basics.

Takeaways / Key Discoveries

Something that I would like to add in future projects like this is SASS and spend more time on the CSS, specifically on having different files but keeping the code DRY. I implemented a different stylesheet for the show route but there was some repeated code.

There are a few things I was excited to have implemented in this project. The following is using a different layout template. Normally Sinatra uses the default layout file in the views directory.

get '/comedians/:id' do
@comedian = Comedian.where('id = ?', params[:id])[0]
erb :show, :layout => :show_layout
end

Here I am specifying a different layout to use for the show page. Looks very similar to passing a variable.

Also, I implemented something called a Matcher in RSpec which is like a function. It takes arguments and performs some set actions using those arguments. This was used to make the test more concise. In future projects, I would like to implement this feature more.

RSpec::Matchers.define :appear_before do |later_content|
match do |earlier_content|
page.body.index(earlier_content) < page.body.index(later_content)
end
end

This was used inside of the sorting feature (sorting comedians by name, city, or age on the page). So rather than having to type out that entire page.body.index() every time placement of content on the page is being tested — this appear_before matcher is used.

Here it is in the test

expect("comedian-info-#{@bill.id}").to appear_before("comedian-info-#{@trevor.id}")

This expectation is to ensure that the appropriate id’s (that denote the comedian div) appear in the correct order. The appear_before matcher is using the index on the body for both contents. Neat!

This project was a lot of fun and I would like to thank the instructors for providing us such a thorough introduction to this firehouse of information. Thanks for reading! Happy coding.

Check out my Github here