Routes in Rails
A basic tutorial on how to use routes and controllers
Routes play a significant role in the creation of a website. It is how the user will be able to view and interact with the webpages of your site, which is why how you set up your routes page in your text editor is one of the most important features — if you can’t set up your routes, you won’t be able to properly have a functioning website. Luckily Ruby on Rails has helper methods built in to create routes. Although it’s convenient to use helper methods, it’s also important to be able to create customizable routes.
The paths that you have in your controllers is dependent on what your routes should be. As an example, I will be using two models (Owner and Pet) and two controllers (owners_controller and pets_controller) to display my routes. Ruby gives us generic and built-in routes when its given the following:
resources :owners
resources :pets
#You can also combine the two as such: resources :owners, :pets
This display is the same as such:
get 'owners/', to: 'owners/#index', as: 'owners'
get 'owners/new', to: 'owners#new', as: 'new_owner'
post 'owners/', to: 'owners#create'
get 'owners/:id', to: 'owners#show', as: 'owner'
get 'owners/:id/edit', to: 'owners#edit', as: 'edit_owner'
patch 'owners/:id', to: 'owners#update'
delete 'owners/:id', to: 'owners#destroy'get 'pets/', to: 'pets/#index', as: 'pets'
get 'pets/new', to: 'pets#new', as: 'new_pet'
post 'pets/', to: 'pets#create'
get 'pets/:id', to: 'pets#show', as: 'pet'
get 'pets/:id/edit', to: 'pets#edit', as: 'edit_pet'
patch 'pets/:id', to: 'pets#update'
delete 'pets/:id', to: 'pets#destroy'
You can also customize the resources to display only certain CRUD actions:
resources :owners, only: [:index, :new, :create, :show]#This will only give you routes to the listed actionsget 'owners/', to: 'owners#index', as: 'owners'
get 'owners/new', to: 'owners#new', as: 'new_owner'
post 'owners/', to: 'owners#create'
get 'owners/:id', to: 'owners#show', as: 'owner'
get
, post
, patch
, and delete
are the HTTP verbs.
It instructs the server to transmit the data identified by the URL to the client. Data should never be modified on the server side as a result of a GET request. In this sense, a GET request is read-only.
‘owners/’
is the URL path that will be displayed in the address bar.
In the ‘owners#index’
, the owners
points to the controller and index
is the action.
Finally, although as: ‘owners’
is not necessary, it is convenient to have, as you can use it instead of writing out the whole path when you write redirect_to
in your controllers. After creating resources, you can type rails routes
in your console to check your routes.
Let’s build out the controllers! I’ll only fill out the owners_controller
as it will look similar to the pets_controller
.
class OwnersController < ApplicationControllerdef index
@owners = Owner.all
enddef new
@owner = Owner.new
enddef create
@owner = Owner.new(owner_params)
if @owner.valid?
@owner.save
redirect_to owner_path(@owner)
else
render :new
end
enddef show
@owner = Owner.find(params[:id])
enddef edit
@owner = Owner.find(params[:id])
enddef update
@owner = Owner.find(params[:id])
if @owner.update(owner_params)
redirect_to owner_path(@owner)
else
render :edit
end
enddef destroy
@owner = Owner.find(params[:id])
@owner.destroy
redirect_to owners_path
endprivate
def owner_params
params.require(:owner).permit(:first_name, :last_name, :age, :email)
endend
This might look a bit intimidating, but once we go over each action, you will be able to understand the whole picture!
def index
@owners = Owner.all
enddef new
@owner = Owner.new
end
When writing your index.html.erb
file for your index page, you will typically want to iterate over all the owners to have a list of them in your index page. In order to do that, you will need the instance of owners
to follow through to your view page. The same concept will apply for the new.html.erb
file.
private
def owner_params
params.require(:owner).permit(:first_name, :last_name, :age, :email)
end
This private params method is added for best security practices. With strong params, the developer can control which attributes the user is permitted to create or update. In this case, the user will be able to create and update the aforementioned attributes.
def create
@owner = Owner.new(owner_params)
if @owner.valid?
@owner.save
redirect_to owner_path(@owner)
else
render :new
end
enddef update
@owner = Owner.find(params[:id])
if @owner.update(owner_params)
redirect_to owner_path(@owner)
else
render :edit
end
end
The create and update methods are similar methods, but the create
method will create a new user using the permitted strong params and check to see if there are any set validations. Validations can be written in your models as such:
validates :first_name, presence :true
The valid?
code will go back to the associated model, check to see if there are any restrictions the user must abide by (i.e. the first_name
field must contain something), and if the following validations are met, the owner will be saved and redirected to the owner_path(@owner)
, which is the show path. If you look back to your routes page, this is the shorthand way to write out the path without having to explicitly state “/owners/:id”
. In this case, we want to redirect the user to the specified :id
of the owner created at that instance, so we pass through an argument of that @owner
. If the @owner is not valid or saved/created, the user will be rendered the specific view file. The same applies to the update
method.
def destroy
@owner = Owner.find(params[:id])
@owner.destroy
redirect_to owners_path
end
Finally, the destroy method will find the owner with the params of :id
and destroy the instance. Because the owner no longer exists, the user should be redirected to a page in which the user does exist, which is the owners_path
, the index.
When to use redirect_to
and render
If you’ve gotten this far, the way models, controllers, and views work should be familiar to you. Most of the routes are primarily used within the controller to redirect_to
and render
pages. The difference between the two is that redirect_to will redirect the user to a certain URL by telling the browser to make a new request to a different location, whereas render will call the template named without the need to specifically redirect the user. For example, if a user wants to create a new username on a social media platform, the user should be directed to a URL looking something like this:
https://socialmedia.com/new
If the user enters information that is invalid, such as forgetting to put an e-mail address, the same form should be rendered so that the user can fill out his or her information again, not changing the URL. Otherwise, the user should be redirected to the next page, which would typically be the users personal account page, as such:
https://socialmedia.com/jennsaccount
This would, of course, be unique to each user.
Sources: