rails new API with PostgreSQL w/rails g resource
Tags: rails, postgres, codenewbie
Published: 2021-04-05 20:47:25

At the beginning of my Flatiron journey, we were writing in Ruby. We were taught about models and associations. Soon enough we were learning the magic of Rails. I think the best part was learning how to use all of that and be able to create my own API. 

My first take-home challenge is to make an API. I decided to leave this here to remember the exact syntax when I create a new one in the future. In this example, we’re going to create a Books API

Open your terminal :

**Create a directory(folder)**
```ruby
mkdir book-app
```

mkdir command is used to make a new directory. It is followed by whatever you want to name that directory.

**Change directory**
```ruby
cd book-app
```

**Create API with PostgreSQL**
```ruby
rails new books-api --api --database=postgresql
```
rails new : creates a new Rails application
books-api : is whatever you want to name your Rails application
--api : this is the api flag. We use this flag to create a lightweight version of a Rails application. Since this project will only be used as an API, this will leave out modules that are used for a browser application. 
--database=postgresql : this flag tells our Rails application which database we are using

**Change directory to your Rails API**
```ruby
cd books-api
```
And type `code .` to open that project in your code editor

This is a good time to create a new repository in your GitHub if you haven't already :)
***
**_Bonus_**
I'm going to create 3 models. Author, Book, and Like.
The relationship will be the following :
<img src="https://i.imgur.com/vfRuTRy.png">

Looking at this diagram, you may spot a problem already. After creating all these models and you go on `rails c` or `rails console`, accessing `author.books` would be a problem. `author.books` could be author has many books OR author has many books through likes. Before we tackle this, let's generate our models first. 

**Generate models, controllers, migrations through Resource**
```ruby
rails g resource <model_name> <attribute>:<data_type> 
```
```ruby
rails g resource Author name age:integer
```
```ruby
rails g resource Book title author:references
```
```ruby
rails g resource Like author:references book:references
```

**rails g :** short term for `rails generate`
**resource :** this creates a number of files for us:
1. a model file
2. a controller file
3. resources call in the routes.rb.
4. a migration file that creates a new database table for the attributes we passed

**references :** this adds the line `belongs_to:<model>` and creates a foreign key column to that table. In our Like model if we didn't include those references it would look like this.
```ruby
rails g resource Like author_id:integer book_id:integer
```
However, doing so will require you to add the `belongs_to` relationship in your models.

You may have noticed `name` and `title` doesn't have a data type, this is because the default is `string`

_since we configured this app as an API with `--api` flag, it will skip generating views, helpers, and assets. Otherwise, `resource` will generate these as well._

**Establish associations**
If you used the references, you won't have to do anything in `like.rb`. It should look like this already.
```ruby
class Like < ApplicationRecord
    belongs_to :author
    belongs_to :book
end
```
In your `book.rb`, it will have the `belongs_to` macros there as well
```ruby
class Book < ApplicationRecord
    belongs_to : author
end
```

This is how to fix the problem I mentioned earlier.
In your `author.rb`
```ruby
class Author < ApplicationRecord
    has_many :books, dependent: :destroy
    has_many :likes, dependent: :destroy 
    has_many :liked_books, through: :likes, source: :book
end
```
We are using `source` to call the books liked by the author and call it `liked_books` instead. So if we run `author.liked_books` in our `console` --it is referring to the books that are liked by this author. 

`dependent: :destroy` this will automatically delete the books associated with the author when that author is deleted. If you don't have an author the book should not exist.

**Migrate**

```ruby
rails db:create
```

```ruby
rails db:migrate
```

And you're good to go!