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.
gem install rails
"rails generate" is the same as "rails g"
Rails Generate
rails g
Running this command outputs all of the available generators.
- application_record
- assets
- benchmark
- channel
- controller
- generator
- helper
- integration_test
- jbuilder
- job
- mailbox
- migration
- model
- resource
- scaffold
- scaffold_controller
- system_test
- task
Models
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.
# 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
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
: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
- 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.
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
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.
# 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:
rails generate controller ControllerName index show new edit --no-helper
--no-assets --no-test-framework --skip-routes --skip
Resource
$ 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
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:
# 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
# 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
# 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
# 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)
# 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
# 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
# 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
# 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
# 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
# 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.
Top comments (4)
Thanks...
It would be interesting to bring us rollback commands.
@vitor0liveir4 what exactly do you mean?
You can "rollback" using
rails destroy ...
(orrails d ...
) just like usingrails generate ...
(orrails g ...
).E.g.
rails g model Product name description:text
can be removed withrails d model Product
.@fwolfst What I mean would be thinking about reversing the changes about using something wrong before, and you want to undo it or something like that… By the way, your answer makes sense! Tky!!