Ruby, Active Record, & Sinatra
Tags: ruby
Published: 2022-08-15 01:31:00

I built a web basic API with Sinatra and Active Record to support a React [frontend](https://github.com/JordanTaylorJ/phase-3-frontend). Here, I go over some key takeaways from building out the server side of this application.

#One to Many Relationship
The tables in this database have a one-to-many relationship. I built two tables, trails and athletes. One trail "belongs to" many athletes. Below, the entity relationship diagram shows the foreign key `trail_id` is in the athletes table connected to the `id` on trails.

###Entity-Relationship Diagram:
![Entity-Relationship Diagram](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aojbpf7j27y6g4rdbwjp.png)

#Active Record
I inherit from the Ruby gem Object Relational Mapper, Active Record in order to define the relationship between the two classes, athlete and trail in the app/models files: 

```
class Athlete < ActiveRecord::Base
    belongs_to :trail
end
```
```
class Trail < ActiveRecord::Base
    has_many :athletes
end
```
 
I use Rake commands to create my migration files:
`bundle exec rake db:create_migration NAME=create_athletes` 

I define the structure of the database tables in the db/migrate files:

```
class CreateAthletes < ActiveRecord::Migration[6.1]
  def change
    create_table :athletes do |t|
      t.string :name
      t.string :time
      t.integer :trail_id
      t.boolean :unsupported
      t.timestamps
    end
  end
end
```

It's important to remember to follow Active Record's naming conventions by using snake_case for the migration file names and CamelCase for the class names as well as keeping the migrate files' timestamp intact. 

It's also important to define **table names as plural** and **class names as singular**. When defining the table relationships, the **singular** trail `belongs_to` and **plural** athletes `has_many` when associating the tables. 

Active Record expects these naming conventions in order to recognize the associations between the data; "convention over configuration". The migration file timestamps allow Active Record to manage version control/schema.


In the app/controllers/application_controller file, I inherit from Sinatra(Controller) in order for the frontend (View) to connect to the database (Model). 

![Image](https://techterms.com/img/lg/mvc_1321.png)

The schema.rb file shows the current version of the database. The version number corresponds to the timestamps on the migration files which is how Active Record maintains version control. 

`ActiveRecord::Schema.define(version: 2022_07_20_184513) do`


I use dynamic routing to handle CRUD actions. For example, from the client side, a POST request would be as follows:

```
    const handleAddTrail = (newTrail) => {
      fetch("http://localhost:9292/trails", {
          method: 'POST',
          headers: { 
            "Content-Type": "application/json", 
          },
          body: JSON.stringify(newTrail),
        })
        .then(r => r.json())
        .then((newTrail) => handleAddTrailToTrails(newTrail))
  }
```
The server side:
```
  post '/trails' do
    trail = Trail.create(
      name: params[:name],
      location: params[:location],
      distance: params[:distance],
      elevation_gain: params[:elevation_gain]
    )
    trail.to_json(include: :athletes)
  end
```
In the POST request example above, it's important to remember to use `include:` to access associated data between tables. Otherwise, in this example, the returned `newTrail` object would not include an athletes array [].

#Overall Thoughts on Active Record and Sinatra
Learning the code and creating a database was not an overly complicated process with these tools. The issues I was getting hung up on were with the file structure of the backend and the specificity of naming conventions. 
I also started out with a lot of code in my application_controller file to handle requests before realizing that the associated data means I only needed an initial fetch from the trails table in order to also get all the data I needed from the athletes.