Making a  Many-to-Many Association with Sinatra and Active Record
Published: 2020-11-23 01:45:35

![Screen Shot 2020-11-22 at 5.53.50 PM](https://dev-to-uploads.s3.amazonaws.com/i/wx350xxpt36vvy8pirrp.png)
 
With Flatiron’s phase two project, an MVC app using Sinatra and Active Record databases, I finally got a long awaited sense of look at me - I made a website 😎 Now, it's not *quite* up to snuff with the heavy hitters out there but it really feels like progress in the right direction to me. Especially considering my [first project](https://dev.to/madelinemc/adding-a-little-pretty-to-my-first-cli-project-43gg) made just 4 weeks ago. It doesn’t always feel like I am progressing that much while going through the daily lessons and labs but this time around the prospect of a project felt more manageable so I decided to challenge myself to make a many-to-many relationship among my models instead of the required has-many and belongs-to relationship. 

The biggest challenge came right off the bat when setting up my three models (User, Appointment, Service) and creating the corresponding tables in the database. In a many-to-many relationship, two models are associated through another model. This is the relationship in my app: 
![Screen Shot 2020-11-22 at 5.54.26 PM](https://dev-to-uploads.s3.amazonaws.com/i/1y3zwp20hukhbniua9ko.png)


ActiveRecord assigns unique identifiers called primary keys to each table and auto-increments as a new record is persisted to the database. In order to associate records on two different tables with each other, the primary key of the has many table needs to be added to the table which holds the belongs-to relationship - this is referred to as a foreign key and noted in the table as `tablename_id` In my table schema, appointments belongs-to users and belongs-to services therefore it holds the foreign keys of the other models. 
```
  create_table "users", force: :cascade do |t|
    t.string  "username"
    t.string  "password_digest"
    t.string  "first_name"
    t.string  "last_name"
  end

 create_table "appointments", force: :cascade do |t|
    t.string  "time"
    t.date    "date"
    t.integer "user_id"
    t.integer "service_id"
  end

  create_table "services", force: :cascade do |t|
    t.string  "name"
    t.text    "description"
    t.integer "price"
  end
``` 

Sinatra gives us meta programming capabilities to associate models by building methods that create the association:
```
class User < ActiveRecord::Base
    has_many :appointments
    has_many :services, through: :appointments
end
```
```
class Appointment < ActiveRecord::Base
    belongs_to :user
    belongs_to :service
end
```
```
class Service < ActiveRecord::Base
    has_many :appointments
    has_many :users, through: :appointments
end
```
Through meta programming and foreign kets my models are associated with a many-to-many relationship and I can call on them to find instances of other models that they are associated with. I used this in many of my controller routes to create instance variables in order to render all of the record's info for the user to see in my views: 
```
  get '/appointments/:id' do
        validate
        @appointment = Appointment.all.find_by_id(params[:id])
        @user = User.find_by_id(@appointment.user_id)
        @service = Service.find_by_id(@appointment.service_id)
        erb :'/appointments/show'
    end
```
et voila ! This many-to-many association helped me create a fun app where users can make, edit, view and delete pretend nail salon appointments at a not so fun time when we can't make real appointments at actual nail salons 💅. 

To make some appointments yourself - please check it out! And always open to suggestions on improving my code. https://github.com/madelinemc/sinatra-salon-appointment-app