Enhancing Projects From Flatiron School: Sinatra - Hole in the Wall
Tags: ruby, javascript, html, css
Published: 2020-09-16 03:49:24

Table of Contents
   * [The First Build](#the-first-build)
   * [The Project Now](#the-project-now)
   * [CSS & JavaScript](#css)
   * [Challenges](#challenges)
   * [Heroku Deployment & Establishing A Connection To The Database](#heroku-deployment)

## [Flatiron School](https://flatironschool.com/) Experience

I attended Flatiron School from November 2019 to May 2020. It was one of the most amazing experiences I've ever had. Students have to build an application in each of the program's five modules. I was in the fast-paced program, so each module lasted a month long. The first month was about learning Procedural and Object-Oriented Programming with [Ruby](https://www.ruby-lang.org/en/documentation/). 

In this blog, I will show you the difference from when I first created a Sinatra application with Flatiron, to what it looks like now after the Bootcamp.

## Flatiron Month 2

The second month of Flatiron began a new module with [Sinatra](http://sinatrarb.com/intro.html). It is a free and open-source software web application library and domain-specific language(DSL) written in Ruby. Sinatra is what Flatiron first introduces you to in order to learn web applications.

### Building a Sinatra Web Application

#### The first build

I wanted to build an application where users could spread awareness about "Hole in the Wall" types of stores. The first build did exactly that.

The *"home"* page:

![Imgur](https://i.imgur.com/GUzeif4.jpg)

The *reviews#new* form page:

![Imgur](https://i.imgur.com/8NXIPOq.jpg)

Nothing really special. It was a barebones build. The application would CRUD `reviews`, but wouldn't CRUD `stores` or `favorites`. Users could signup and login, but couldn't delete or edit their account.

## **The Project Now**

![Imgur](https://i.imgur.com/ezU0w5o.png)

The application could have way more features than it does right now. I don't know how to design the website better without feedback, and some very great friends took their time to tell me some things they wish were implemented. When I update the CSS, I will also update this blog on what features I added.

**You can view the live application here at:** https://hole--in-the--wall.herokuapp.com/

- **Users** can now signup and login. They can also edit or delete their account.

- **Stores** can now be created & linked to Google Maps as well as edited.

- **Reviews** can now be created, edited, and deleted.

- **Favorites** of stores can now be created and deleted.

- The application now features [semantic HTML](https://www.w3schools.com/html/html5_semantic_elements.asp).

#### Using ["Wave"](https://chrome.google.com/webstore/detail/wave-evaluation-tool/jbbplnpkjmmeebjpijfedlgcdilocofh?hl=en-US) Google Chrome extension

This awesome extension allows you to view the current status of accessibility on your web page.

### CSS

I used [*Flexbox*](https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Flexbox) on pages where the layout was more simple.

I used [Media Queries](https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries) to make sure breakpoints were set in place.

### JavaScript

I implemented Javascript into pages where I wanted forms to appear when a user clicked a certain button, instead of having to create more views with `erb`.

I didn't want to `fetch` information in this application. I just wanted to keep straight as Sinatra backend/frontend application using `erb` views. The only Javascript necessary was to shorten up how many views templates there were.

### Challenges

The challenges in upgrading this application involved: Heroku deployment, Sinatra gems, ActiveRecord Queries, Javascript, and CSS. 

For example, the Sinatra Contrib gem's Namespace feature wouldn't function with the application as it interferes with Rack's namespace. Sinatra just released their newest update, so I might update the namespace feature in the near future.

Flatiron teaches the basics of ActiveRecord but it's up to you to figure out how it really works. Updating this application let me review and deal with things like [ActiveRecord](https://guides.rubyonrails.org/active_record_querying.html) [method chaining](https://guides.rubyonrails.org/active_record_querying.html#understanding-the-method-chaining), [ActiveRecord::Relation](https://api.rubyonrails.org/classes/ActiveRecord/Relation.html), [ActiveRecord::Result](https://api.rubyonrails.org/classes/ActiveRecord/Result.html), grabbing or converting query return values, security, and eager loading.

Heroku won't allow SQLite3 when you deploy your website. I provisioned a PostgreSQL database for my application from Heroku instead.

SQLite3 and PostgreSQL won't allow some of the same types of queries. For example in SQLite3, this worked: 

```ruby
Store.select(
            "stores.id, 
            stores.name, 
            stores.state, 
            count(favorites.store_id) AS favorites_count"
).joins(:favorites).limit(5).group(:name).order(
"favorites_count DESC"
).as_json
```

But it wouldn't work in PostgreSQL, as you need to group the column names together outside of the aggregate in the `.group` method.

```ruby
Store.select(
            "stores.id, 
            stores.name, 
            stores.state, 
            count(favorites.store_id) AS favorites_count"
).joins(:favorites).limit(5).group(
"stores.id, 
stores.name, 
stores.state"
).order("favorites_count DESC").as_json
```

#### Heroku Deployment

When configuring my environment to establish a connection to the database, the only blogs and articles available for doing so with ActiveRecord featured establishing the connection directly to ActiveRecord itself, like this example:

```ruby
require 'bundler/setup'
Bundler.require

configure :development do
 ENV['SINATRA_ENV'] ||= "development"
 require 'bundler/setup'
 Bundler.require(:default, ENV['SINATRA_ENV'])

ActiveRecord::Base.establish_connection(
  :adapter => "sqlite3",
  :database => "db/#{ENV['SINATRA_ENV']}.sqlite"
)
end

configure :production do
 db = URI.parse(ENV['DATABASE_URL'] || 'postgres:///localhost/mydb')

 ActiveRecord::Base.establish_connection(
   :adapter  => db.scheme == 'postgres' ? 'postgresql' : db.scheme,
   :host     => db.host,
   :username => db.user,
   :password => db.password,
   :database => db.path[1..-1],
   :encoding => 'utf8'
 )
end
```

This was also taught at Flatiron. It's good to know, but for this application, there actually is a **much** simpler way of establishing a connection to your database.

If you go to the [sinatra-activerecord](https://github.com/sinatra-activerecord/sinatra-activerecord) github page, it will tell you that **all you need to do is this**:

"Require the 'sinatra/activerecord' gem in your Sinatra application, and establish the database connection:"
```ruby
# app.rb
require "sinatra/activerecord"

set :database, {adapter: "sqlite3", database: "foo.sqlite3"}
# or set :database_file, "path/to/database.yml"
```

"If you have a `config/database.yml` file, it will automatically be loaded, no need to specify it. Also, in production, the `$DATABASE_URL` environment variable will automatically be read as the database (if you haven't specified otherwise)."

So this is literally what my environment.rb looks like:

```ruby
require 'bundler/setup'
Bundler.require
require_all 'app'
```

Then in my `application_controller`:

```ruby
configure do
    set :public_folder, 'public'
    set :views, 'app/views'
    set :database_file, "config/database.yml"
    enable :sessions
end

configure :test, :development do
    set :session_secret, File.read("config/keys/session_secret.txt")
    set :google_api, File.read("config/keys/API_KEY.txt")
end

configure :production do
    set :session_secret, ENV['SESSION_KEY']
    set :google_api, ENV['GOOGLE_API_KEY']
end
```

All I had to do was specify where my `database.yml` file was, and it configured the connection to the database for me.

The [Sinatra Readme](http://sinatrarb.com/intro.html) also talks about configuration settings using the `configure` method above.

Heroku allows you to set environment variables for your application as well. You can find out [**here**](https://devcenter.heroku.com/articles/config-vars#set-a-config-var).

[Heroku also requires that you include a Procfile](https://devcenter.heroku.com/articles/procfile) in the root level of your application, that specifies what commands to run when starting the application. For this app I only included: 

```ruby
   web: bundle exec rackup config.ru -p $PORT
``` 

## Feedback

I greatly appreciate that you took the time to read this blog and viewed what my application can do. If you would like to take a look through the code and see if there are any improvements that could be made I would be very grateful. 

I will add features/fixes to the application when I can. If you have something you'd like to add, feel free to push it to Github. :)

- Reach out to me on [Twitter](https://twitter.com/ethanMGustafson)
- Contribute to the [hole-in-the-wall Github repo](https://github.com/GoodGuyGuf/hole-in-the-wall)

This is an application I love and would love to keep using. I will update this application using different frameworks and tools to run and develop it more smoothly.