Ruby on Rails (part 2)
Models and ActiveRecord
ActiveRecord and ActiveRelation
ActiveRecord is the rails implementation of active record design pattern. Instead of database row, it retrieves and manipulates data as objects.
It also understands the structure of the table, knows how to create, read, update and delete rows as objects.
user = User.new
user.first_name = "John"
user.save # SQL INSERT
user.last_name = "Doe"
user.save # SQL UPDATE since it knows there is already row exists
user.destroy # SQL DELETE
ActiveRelation is also known as “Arel”. It simplifies the generation of complex database queries. It is chainable and do not execute until needed.
users = User.where(first_name: "John") # SQL not yet execute
users = users.order("last_name ASC").limit(5) # chain it to previous query
users.each {|user|
... # SQL is now executed because it is needed by now
}
Rails console
We could use rails console to interact with rails.
rails console -e development
rails console # default environment is development
rails c #shorthand
Note: rails comes with irb
(interactive ruby), but irb
command alone will not load with your project.
Create records using ActiveRecord
There are 2 ways that you could create record.
- instantiate -> set values -> save
- create
Using approach 1,
$ rails console
> subject = Subject.new(:name => 'First Subject')
> subject.position = 1
> subject.save
Using approach 2,
$ rails console
> subject = Subject.create(:name => 'Second Subject', :position = 2)
Update records using ActiveRecord
There are 2 ways that you could update record.
- find -> set values -> save
- find -> update
Using approach 1,
$ rails console
> subject = Subject.find(1) # find by id or primary key
> subject.name = "New Subject"
> subject.save
Using approach 2,
$ rails console
> subject = Subject.find(2) # find by id or primary key
> subject.update(:name => "New Subject", :position => 2)
Delete records using ActiveRecord
- find -> destroy
$ rails console
> subject = Subject.find(2) # find by id or primary key
> subject.destroy
Find records using ActiveRecord
Primary Key Finder: Subject.find(2)
will return an object or an error.
Condition: Subject.where(:visible => true)
will help to filter.
Note: for dynamic data (eg. user’s input), be careful.
User.where("first_name LIKE #{@query}") # SQL Injection can happen
User.where(["first_name LIKE ?", @query]) # SQL sanitization
If you want to find first, Subject.where(:visible => true).first
It will return an object or nil
Other conditions would be
Subject.order('position ASC')
Subject.limit(20)
Subject.offset(100) # skip 100 results
One-to-many assocations
class Subject
has_many :pages
end
class Page
belongs_to :subject
end
After linking between two tables, we can then use it:
subject.pages
subject.pages << page
subject.pages.delete(page)
subject.pages.empty?
subject.pages.size
CRUD
For most web application, we will have Create, Read, Update and Delete operations.
To create a controller,
rails generate controller Subjects
This will create the controller under app/controllers/subjects_controller.rb
.
class SubjectsController < ApplicationController
def index
# list of records
end
def show
# a single record
end
def new
# display new form
end
def create
# process new form
end
def edit
# display edit form
end
def update
# process edit form
end
def delete
# display delete form
end
def destroy
# process delete form
end
end
These methods will be linked to the routes.rb
under config
.
Rails.application.routes.draw do
get 'subjects/index'
get 'subjects/show'
get 'subjects/new'
get 'subjects/edit'
get 'subjects/delete'
end
REST
REST stands for Representational state transfer. Using REST, we are going to perform state transformations upon resources.
Here are some REST HTTP verbs.
GET
- Retrieve items from resource
POST
- Create new item in resource
PATCH
- Update existing item in resource
DELETE
- Delete existing item in resource
Resourceful routes
In part 1, we discussed about 3 other routes and now, we are going to look at resourceful routes. It is the combination of RESTful and CRUD and it is Rails default.
It is used by most professional Rails developers and optimized for REST.
HTTP Verb | URL | Action | Description |
---|---|---|---|
GET | /subjects | index | show all items |
GET | /subjects/:id | show | show item with :id |
GET | /subjects/new | new | show new form |
POST | /subjects | create | create an item |
GET | /subjects/:id/edit | edit | show edit form for item with :id |
PATCH | /subjects/:id | update | update item with :id |
GET | /subjects | delete | show delete form for item with :id |
DELETE | /subjects | destroy | delete item with :id |
To enable this behavior, rails make it easy. To get it,
# config/routes.rb
resources :subjects
Omitting resourceful routes
If you don’t want to use the default, you could also modify:
# config/routes.rb
# all except show action
resources :subjects, :except => [:show]
# only these
resources :users, :only => [:index, :show]
# additional route
resources :subjects do
member do
get :delete # GET /subjects/:id/delete
end
collection do
get :export # GET /subjects/export
end
end
Using resourceful URL helper
<%= link_to('All Subjects', subjects_path) %>
<%= link_to('Show Subject', subjects_path(@subject.id) ) %>
<%= link_to('Edit Subject', edit_subjects_path(@subject) ) %>
This will help to shorten in format.
{ :controller => `subjects`, :action => `show`, :id => 5 }
# can be shorten as
subject_path(5)
HTTP Verb | URL | Action | Helper |
---|---|---|---|
GET | /subjects | index | subjects_path |
GET | /subjects/:id | show | subject_path(:id) |
GET | /subjects/new | new | new_subject_path |
POST | /subjects | create | subjects_path |
GET | /subjects/:id/edit | edit | edit_subject_path(:id) |
PATCH | /subjects/:id | update | subject_path(:id) |
GET | /subjects/:id/delete | delete | delete_subject_path(:id) |
DELETE | /subjects/id | destroy | subject_path(:id) |