CRUD in Rails 7
In this article, we are going to create a CRUD application in rails 7.
We are going to use Rails 7.0.4.2 and Ruby 3.1.0 for this project.
Points To be Discussed
What is CRUD?
Create a new rails application
Create Model
Create Controller
Create CRUD
Screenshots
References
What is CRUD?
The CRUD operation is a fundamental and extremely basic operation for any programming language. It stands for Create
, Read
, Update
, and Delete
. Most often, it is used to create the data, alter the data, and delete the data from the database.
Rails by default use SQLite database
Create a new rails application
to create a new rails application type,
rails new Employee_CRUD
Create Model
rails g model Employee employee_name gender hobbies
it will create and invoke these kinds of files
We are using the rails generator to generate the model and passing employee_name, gender, and hobbies as database fields. Moreover, It will create a migration file in db/migrate folder and it looks like
class CreateEmployees < ActiveRecord::Migration[7.0]
def change
create_table :employees do |t|
t.string :employee_name
t.string :gender
t.string :hobbies
t.timestamps
end
end
end
Run rails db:migrate
. it will run the above migration file.
Create Controller
Now, run
rails g controller employees index new create show edit update destroy
It will generate a controller, namely, employees_controller.rb.
Apart from this controller, this command also generates view files inside the views folder and defines some routes in the routes.rb file.
It will create 7 views of the file as we type index
, new
, create
, show
, edit
, update
, and destroy
in the command.
→ index.html.erb
→ new.html.erb
→ create.html.erb
→ show.html.erb
→ edit.html.erb
→ update.html.erb
→ destroy.html.erb
And in config/routes.rb it looks like
Rails.application.routes.draw do
get 'employees/index'
get 'employees/new'
get 'employees/create'
get 'employees/show'
get 'employees/edit'
get 'employees/update'
get 'employees/destroy'
end
Start the rails server by rails s
and goes to http://localhost:3000/ in your browser. it will look like,
type http://localhost:3000/employees/index in your URL bar to visit the index page. it will look like
CREATE CRUD
So now that our model, view, and controller have been generated, we can write the code for CRUD inside these files.
Before writing controller actions, we need to modify routes first, hence change the individual get routes into one single resource and add index page as a root page.
config/routes.rb
Rails.application.routes.draw do
resources :employees
root "employees#index"
end
Let us now move to the controller and write the following code:
employees_controller.rb
class EmployeesController < ApplicationController
before_action :set_employee_params, only: %i[show edit update destroy]
def index
@employees = Employee.all
end
def new
@employee = Employee.new
end
def create
@employee = Employee.create(employee_params)
if @employee.valid?
flash[:errors] = 'Employee Created Successfully'
redirect_to employees_path
else
flash[:errors] = @employee.errors.full_messages
render :new
end
end
def show; end
def edit; end
def update
if @employee.update(employee_params)
flash[:errors] = 'Employee Updated Successfully'
redirect_to employee_path(@employee)
else
flash[:errors] = @employee.errors.full_messages
redirect_to edit_employee_path
end
end
def destroy
if @employee.delete
flash[:errors] = 'Employee Deleted Successfully'
redirect_to root_path(@employee)
else
flash[:errors] = @employee.errors.full_messages
redirect_to destroy_employee_path
end
end
private
def set_employee_params
@employee = Employee.find(params[:id])
end
def employee_params
params.require(:employee).permit(:employee_name, :gender, { hobbies: [] })
end
end
Now let’s modify the view files.
I am going to create a CRUD with some styling, and I will be using Bootstrap for that.
Add Bootstrap 5’s following CDN to application.html.erb
<!--Bootstrap CDN -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<!-- JavaScript Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
application.html.erb
<!DOCTYPE html>
<html>
<head>
<title>EmployeeCrud</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
<%= javascript_importmap_tags %>
</head>
<!--Bootstrap CDN -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<!-- JavaScript Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
<body>
<%= yield %>
</body>
</html>
NOTE: We do not need the create, update, or destroy erb files. Because create is as same as new, an update is as same as edit, and destroy is directly run with the method defined in the controller. So, you can delete it.
index.html.erb
<div class="flex-column" style = "height: auto;">
<h1> Employees </h1>
<!--Error Message-->
<% if flash[:errors] %>
<% flash.each do |name,message| %>
<p class="text-danger"><%= message%></p>
<% end %>
<% end %>
<!-- Employee Table -->
<div>
<table class="table table-info table-striped">
<ol class="fs-2">
<thead class="table-secondary">
<td class="text-center"> Id </td>
<td class="text-center"> Name </td>
<td class="text-center"> Hobbies </td>
<td colspan=3 class="text-center"> Action </td>
</thead>
<% @employees.each do |e| %>
<tr>
<td class="text-center"> <%= e.id %> </td>
<td class="text-center"> <%= link_to e.employee_name, employee_path(e) %> </td>
<td class="text-center"> <%= e.hobbies %> </td>
<td class="text-center"><%= button_to "Show",employee_path(e),method: :get, class:"btn-success border-0 rounded-pill shadow px-3 py-2" %></td>
<td class="text-center"><%= button_to "Edit",edit_employee_path(e),method: :get, class:"btn-primary border-0 rounded-pill shadow px-3 py-2" %></td>
<td class="text-center"><%= button_to "Delete",employee_path(e),method: :delete, class:"btn-danger border-0 rounded-pill shadow px-3 py-2" %></td>
</tr>
<% end %>
</ol>
</table>
</div>
<div class="d-flex">
<%= button_to "Add New Employee", new_employee_path, method: :get ,class:"btn-warning border-0 rounded-pill shadow p-3 m-3" %>
</div>
</div>
new.html.erb
<div class="flex-column">
<div class="card shadow" style="width: 36rem;">
<div class="card-header">
<h2 class="text-center">Employee Form</h2>
</div>
<div class="card-body">
<!--Error Message-->
<% if flash[:errors] %>
<% flash[:errors].each do |error| %>
<p class="text-danger"><%= error %></p>
<% end %>
<% end %>
<!-- Form Started Here -->
<%= form_with model: @employee do |f| %>
<%= f.label :employee_name, "Employee Name :", class:"mt-3" %>
<%= f.text_field :employee_name ,placeholder: "Enter Employee's Name",class:"mb-2 form-control" %>
<br>
<!-- Radio Button For Gender -->
<div class="form-group">
<%= f.label "Gender :" %>
<%= f.radio_button :gender, "male" %>
<%= f.label :gender, "Male" %>
<%= f.radio_button :gender, "female" %>
<%= f.label :gender, "Female" %>
</div>
<br>
<!-- Checkbox For Hobbies -->
<div class="form-group">
<%= f.label "Hobbies :" %>
<%= f.check_box :hobbies, { multiple: true },"Reading", false %>
<%= f.label :hobbies, "Reading" %>
<%= f.check_box :hobbies, { multiple: true },"Photography", false %>
<%= f.label :hobbies, "Photography" %>
<%= f.check_box :hobbies, { multiple: true },"Travelling", false %>
<%= f.label :hobbies, "Travelling" %>
</div>
<br>
<%= f.submit "Save Employee", class:"btn-primary border-0 rounded-pill shadow p-3" %>
<% end %>
</div>
</div>
</div>
edit.html.erb
<div class="flex-column">
<div class="card shadow" style="width: 36rem;">
<div class="card-header">
<h2 class="text-center">Employee Form</h2>
</div>
<div class="card-body">
<!--Error Message-->
<% if flash[:errors] %>
<% flash[:errors].each do |error| %>
<p class="text-danger"><%= error %></p>
<% end %>
<% end %>
<!-- Form Started Here -->
<%= form_with model: @employee do |f| %>
<%= f.label :employee_name, "Employee Name :", class:"mt-3" %>
<%= f.text_field :employee_name ,placeholder: "Enter Employee's Name",class:"mb-2 form-control" %>
<br>
<!-- Radio Button For Gender -->
<div class="form-group">
<%= f.label "Gender :" %>
<%= f.radio_button :gender, "male" %>
<%= f.label :gender, "Male" %>
<%= f.radio_button :gender, "female" %>
<%= f.label :gender, "Female" %>
</div>
<br>
<!-- Checkbox For Hobbies -->
<div class="form-group">
<%= f.label "Hobbies :" %>
<%= f.check_box :hobbies, { multiple: true },"Reading", false %>
<%= f.label :hobbies, "Reading" %>
<%= f.check_box :hobbies, { multiple: true },"Photography", false %>
<%= f.label :hobbies, "Photography" %>
<%= f.check_box :hobbies, { multiple: true },"Travelling", false %>
<%= f.label :hobbies, "Travelling" %>
</div>
<br>
<%= f.submit "Save Employee", class:"btn-primary border-0 rounded-pill shadow p-3" %>
<% end %>
</div>
</div>
</div>
Note : We have the same code in new.html.erb and edit.html.erb, so we will use the _form.html.erb partial for that and just render that partial in our files. We will do this after learning about “Rails Partials” in our upcoming articles.
show.html.erb
<!-- Employee Details Showing -->
<div class="flex-column" style="height:100vh;">
<!--Error Message-->
<% if flash[:errors] %>
<% flash.each do |name,message| %>
<p class="text-danger"><%= message%></p>
<% end %>
<% end %>
<div class="d-flex">
<div class="m-5" >
<div class="card bg-light border-warning shadow">
<div class="card-body">
<div class="card-header">
<h2 class="text-center">Employee's Details</h2>
</div>
<div>
<h2> ➡ ID: <%= @employee.id %> </h2>
<h2> ➡ Name: <%= @employee.employee_name %> </h2>
<h2> ➡ Gender: <%= @employee.gender %> </h2>
<h2> ➡ Hobbies: <%= @employee.hobbies %> </h2>
</div>
<div class="d-flex">
<%= button_to "Edit Employee" , edit_employee_path, method: :get ,class:"btn-success border-0 rounded-pill shadow p-2 m-2" %>
<%= button_to "Delete Employee", employee_path, method: :delete ,class:"btn-danger border-0 rounded-pill shadow p-2 m-2" %>
<%= button_to "View all Employee", employees_path,method: :get ,class:"btn-primary border-0 rounded-pill shadow p-2 m-2" %>
</div>
</div>
</div>
</div>
</div>
</div>
That’s it. Our CRUD has been done. 🎉 🎉
Now just go to http://localhost:3000/. and enjoy your CRUD application.
Screenshots:
Index Page
New Page
Show Page
Edit Page
In addition, if you want to change some styling in your application, you can do it.
You just need to create a custom.css file under the app/assets/stylesheets folder and write your own style. I create the same and add styling for centering a div.
custom.css
.set-center {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
References :
GitHub Repository : https://github.com/rutikkpatel/Employee-CRUD-Rails-7
Top comments (2)
small remark:
create
,update
,delete
are not get requestsFirst and foremost, thank you so much @superails for taking the time to read my article. Your youtube tutorials are extremely beneficial to my learning.
And, yes, you are correct.
create
,update
,delete
are not get requests.A
POST
request is to "create."The
PATCH
request is "update".A
DESTROY
orDELETE
request is to "delete".But when we generate the controller with
rails g controller employees index new create show edit update destroy
. The routes will be automatically added asget 'employees/create'
get 'employees/update'
get 'employees/destroy'