Recipe for Rails Backend
Tags: rails, beginners, tutorial
Published: 2020-04-06 20:02:16

Here's a cheatsheet for a basic Rails backend:

## 1. Create a new Rails app as an api
I choose the database to be Postgres because it's easier to deploy.
- `rails new <my_app_name> --database=postgresql --api`
- `cd` to the new folder

## 2. Gemfile
- navigate to your Gemfile and uncomment `gem 'rack-cors'`
- also, add these: `gem 'active_model_serializers'`, `gem 'jwt'` (if you're planning to do the auth) and `gem 'activerecord-reset-pk-sequence'`
- `bundle install`

## 3. CORS
Inside of `config/initializers/cors.rb` uncomment the following code:
```
Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins '*'

    resource '*',
      headers: :any,
      methods: [:get, :post, :put, :patch, :delete, :options, :head]
  end
end
```
## 4. Models and validations
- draw domain model
- create models: `rails g model User name:string age:integer account:belongs_to`
 - remember to first generate the ones with `has_many` macros on them; then only the ones with `belongs_to` — this will be helpful when running migrations because otherwise you may get this error: 
`ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR:  relation "<some table name>" does not exist`
- add appropriate associations on models (`has_many` and `belongs_to`, for instance) 
- create migration: `rails db:create`
- run migration: `rails db:migrate`
- create [validations](https://guides.rubyonrails.org/active_record_validations.html)
- in `rails c` try create a few instances, both correct and incorrect to test validations; then, test associations(e.g. `User.all.first.laptop` would check for the laptop of the first user and `User.all.first.laptop.gadgets.first` would check the first gadget that belongs to the laptop)

## 5. Routes 
- in `config/routes.rb` specify the routes you'll be using
- since this is API, your routes should be placed in a namespace:
```
Rails.application.routes.draw do
  namespace :api do
      resources :users
      resources :questions, only: [:index, :show]
      resources :seen_questions, only: [:index, :show, :create]
      resources :question_categories, only: [:index, :show]
  end
end
```
- if you want to add versioning, this is the syntax:
```
Rails.application.routes.draw do
  namespace :api do
    namespace :v1 do
      resources :users
      resources :questions, only: [:index, :show]
      resources :seen_questions, only: [:index, :show, :create]
      resources :question_categories, only: [:index, :show]
    end
  end
end
```

## 6. Controllers
- create controllers with `rails g controller api/v1/Users`
- add appropriate actions

## 7. Serializers
- create serializers with `rails g serializer post`
- **note:** serializers can take custom methods or a macro `has_many`

## 8. Seed data
- at the top write `SomeClassName.destroy_all` for each of the classes; start with the ones that `belongs_to` and only afterwards, add those that `has_many` — this will allow you to avoid multiplications in your database when you run `rails db:seed` again;
- afterwards, write in the same sequence `SomeClassName.reset_pk_sequence` —- this will allow you to always start fresh ids whenever you run `rails db:seed`;
- see if everything is showing well on your endpoints