Rails Generator Cheat Sheet
Tags: beginners, rails, ruby, flatiron
Published: 2022-12-13 23:27:33


In this article is for newer developers looking to learn strategy and commands on Rails. When I started to learn ruby on rails; I kept going back and looking up how to use certain generators. 

Rails is a web application development framework written in the Ruby programming language and was designed to make programming web applications easier. It allows you to write less code while accomplishing more than any frameworks. 

First, install the Rails gem if you haven't done so.
```javascript
gem install rails
```
"rails generate" is the same as "rails g"

_**Rails Generate**_ 

```javascript
rails g
```
Running this command outputs all of the available generators.
```javascript
- application_record
- assets
- benchmark
- channel
- controller
- generator
- helper
- integration_test
- jbuilder
- job
- mailbox
- migration
- model
- resource
- scaffold
- scaffold_controller
- system_test
- task
```

_**Models**_ 

```javascript
rails g model
```
"rails g model NameOfYourModel field1:data_type field2:date_type"
A model is a Ruby class that is used to represent data and can interact with application's database through a feature of Rails called Active Record. It creates both the model and the migration. 

Model names are singular, because an instantiated model represents a single data record.

The generator adds timestamps by default(`created_at` and `updated_at`). Also the default type of an attribute is string so you don't have to include it. If I put `name` in field; it will be treated as `name:string`.

A generator will include the `:password_digest` field in the migration and the `has_secure_password` method in the model; if you include `password:digest` when generating a model.

Another neat thing rails does for us is when adding reference to a field generates an id column, which does a belongs_to associations for us.

```javascript
# generates the Product migration with a foreign id for Seller

rails g model Product name description:text seller:references 
```
It will create a migration that looks like this
```javascript
class CreateProducts < ActiveRecord::Migration
  def change
    create_table :products do |t|
      t.string :name
      t.text :description
      t.references :seller, null: false, foreign_key: true
 
      t.timestamps
    end
  end

# and the Seller model, with the association

class Product < ApplicationRecord
  belongs_to :seller
end
```
When making any adjustments you need to run `rails db:migrate` after the changes.

_**Migrations**_ 

A Rails migration is a tool for changing and modifying an application's database schema.
Migration Data Types 
```javascript

:primary_key - translates into whatever the primary key datatype your database of choice requires

:string - use for short strings such as names and emails

:text - use for long strings, normally captured by textarea

:integer - it’s a whole number, eg. 0,12,12532

:float - decimal numbers stored with fixed floating point precision

:decimal - stored precision varies; good for exact math calculations

:datetime - both date and time

:timestamp - same as datetime; usually used for created_at/updated_at

:time - hours, minutes, seconds

:date - year, month, day

:binary - store images, videos and other files in their original format in chunks of data called blobs

:blob - similar to binary, contains the metadata about a file. Blobs are intended to be immutable

:boolean - self explanatory - true/false

:json - from Rails 5 onwards, you can natively store JSON values thanks to this Pull Request. A lot of people still use Postgres’ jsonb datatype though.
```
Active Record provides methods that perform common data definition tasks
```javascript

- add_column
- add_index 
- change_column
- change_table
- create_table
- drop_table
- remove_column
- remove_index
- rename_column 
```

If the migration name is of the form AddXToY or RemoveXFromY and is followed by a list of column names and types then a migration containing the appropriate `add_column` and `remove_column` statements will be created.
```javascript
rails g migration AddPriceToProduct price:integer

# generates the following migration

class AddPriceToProduct < ActiveRecord::Migration[6.1]
  def change
    add_column :products, :price, :integer
  end
end

```

**_Controller_** 
```javascript
rails g controller
```
"rails g controller NameOfController action1 action2 ..."

Action Controller is the C in MVC. The controller is responsible for making sense of the request and producing the appropriate output which, does most of the groundwork for you. You can think of the controller being the middleman between models and views. It makes the model data available to the view, so it can display that data to the user and saves/updates user data to the model.

The naming convention of controllers in Rails favors pluralization of the last work in the controller's name, although it is not strictly required.

```javascript
# generates a controller and actions...

rails g controller Products index show update destroy

class ProductsController < ApplicationController
  def index
  end
  def show
  end
  
  def update
  end
  def destroy
  end
ene 

# and routes in the routes.rb file

Rails.application.routes.draw do
  get ‘products/index’
  get ‘products/show’
  get ‘products/new’
  get ‘products/edit’
end
```

A good to know, to generate just the controller file, without all the extra files and folders use the following:
```javascript 
rails generate controller ControllerName index show new edit --no-helper 
--no-assets --no-test-framework --skip-routes --skip
```

_**Resource**_ 

```javascript
$ rails g resource --no-test-framework

# --no-test-framework will not install the test files
```
"rails g resource NameOfResource field:data_type field:data_type"

Each of the previous generators, resource does it in one command. It will create a model, does the migration, have an empty controller(for your actions), and have full CRUD routes in your routes.rb
```javascript 
rails g resource Product name description:text price:integer 
--no-test-framework

invoke  active_record
      create    db/migrate/20200326023754_create_products.rb
      create    app/models/product.rb
      invoke  controller
      create    app/controllers/products_controller.rb
      invoke    erb
      create      app/views/products
      invoke    helper
      create      app/helpers/products_helper.rb
      invoke    assets
      invoke      scss
      create        app/assets/stylesheets/products.scss
      invoke  resource_route
       route    resources :products
```
This will create the following: 
```javascript 
# creates a migration...
in db/migrate/20190714193807_products.rb

class CreateProducts < ActiveRecord::Migration[6.1]
  def change
    create_table :products do |t|
      t.string :name
      t.string :capital
      t.timestamps
    end
  end 
end
# a model...
class CreateProducts < ActiveRecord::Migration
  def change
    create_table :products do |t|
      t.string :name
      t.text :description
      t.integer :price

      t.timestamps
    end
  end
# a controller...
class TerritoriesController < ApplicationController
end

#config/routes.rb
Rails.application.routes.draw do
  resources :products
end
```

As you can see this tool saves you time when you're doing a code challenge or want to do all the action in one command.

Scaffold would set up everything for you as well just as, routes, controller, views, models, and migrations.
`rails g scaffold`

_**More Info**_ 

```javascript 
# Run migration
$ rails db:migrate

# Rollback last migration
$ rails db:rollback

# Run database seed code
$ rails db:seed

# Delete and re-create db and run migrations
$ rails db:reset
```

Routes
```javascript

# Route maps to controller#action
get 'welcome', to: 'products#home'

# Root page (root_path name helper)
root 'products#home' 

# Named route 
get 'exit', to: 'sessions#destroy', as: :logout

# Create all the routes for a RESTful resource
resources :items
```

HTTP Verb Path
```javascript 
# HTTP    Verb Path    Controller#Action  Named Helper
# GET     /items           items#index    items_path
# GET     /items/new       items#new      new_item_path
# POST    /items           items#create   items_path
# GET     /items/:id       items#show     item_path(:id)
# GET     /items/:id/edit  items#edit     edit_item_path(:id)
# PUT     /items/:id       items#update   item_path(:id)
# DELETE  /items/:id       items#destroy  item_path(:id)
```

```javascript
# Only for certain actions
resources :items, only: :index

# Resource with exceptions 
resources :items, except: [:new, :create]

# Nested resources
resources :items do
  resources :reviews
end

# Dynamic segment: params['id']
get 'products/:id', to: 'products#show'
# Query String: url /products/1?user_id=2
# params will be {'id' 'user_id'}
```

Model Validation examples
```javascript
# Model validation
validates :title, :description, :image_url, presence: true
validates :email, presence: true, format: { with: /\A[^@\s]+@[^@\s]+\z/, message: 'Must be a valid email address'}
validates :price, numericality: { greater_than_equal_to: 0.01 }
validates :title, uniqueness:  true
validates :title, length: { minimum: 3, maximum: 100 }
validates :type, inclusion: types.keys

# Model relationship
belongs_to :customer

# Relation with cascade delete
has_many :invoices, dependent: :destroy

#One to one
has_one :profile

# Hook methods 
before_destroy :ensure_not_reference_by_any_invoices 
before_save :downcase_email 
```

Active Record
```javascript 
# Active record common methods
Article.all
# Throw error if not found
Article.find(params[:id])
# Do not throw error if not found
Article.find_by(product_id: product_id)
@category = Category.find_by!(slug: params['slug']) # Return Not Found Error (404 page in production)
Article.group(:product_id).sum(:quantity)
Article.where('quantity > 1')
Article.where(cat_id: cat_id, model: model)
Article.where(model: model).or(Article.where(cat_id: cat_id))
Article.join(:categories).where(categories: { id: 2 } )
Article.where("title LIKE ?", "%" + params[:q] + "%")
Article.count
Article.first
Article.last
Article.column_names # ['id', 'name', 'price']
Category.delete_all # delete all rows in Category table
product.category = Category.all.sample # random for Faker data
@products = Product.offset(5).limit(10).all # skip 5, take 10
```

```javascript 
# Create flash (reset every new request)
flash[:success] = 'User created with success!'

# Create flash.now (reset every new view render)
flash.now[:error] = 'Please select s user!'

# Create session (reset every browser close)
session[:user_id] = user.id

# Check if session exist
session[:user_id].nil?

# Remove
session.delete(:user_id)

# Remove all
reset_session      

# Create cookie (reset at expiration date)
cookies.permanent[:remember_token] = remember_token

# Encrypted cookie
cookies.permanent.encrypted[:user_id] = user.id

# Delete cookie
cookies.delete(:user_id)
```

Deployment with Heroku
```javascript 
# Create git and push to Heroku
$ heroku create
$ git remote
$ bundle install --without production
$ git status
$ git add -A
$ git commit -m 'heroku deployment'
$ git push origin master
$ git push heroku master
$ heroku run rails db:migrate
$ heroku run rails db:seed

# launch the upload site
$ heroku open 
```

Rails CLI

 ```javascript 
# Create a new rails app
$ rails new project_name 

# Start the Rails server
$ rails s

# Rails console
$ rails c

# Install dependencies
$ bundle install

# View all routes
$ rails routes
```

Files 

`--no-test-framework` — prevents generator from creating standard tests

`--skip` — skips files that already exist

`--no-assets` — prevents generator from creating assets

`--no-helper` — prevents generator from creating helper

`--skip-routes` — prevents generator from adding routes to routes.rb


I hope you can take some info and apply into your code. Thank you for reading and best wishes.