Table of Content
Chapter 6 – Introducing Ruby on Rails (Part B)
Let’s continue the CRM system
In last section, we created a Customer resource management with Rails. We are able to create customer record. Edit existing record or list all the customers.
In this section, we continue on the project to create Note resource, which is associated to Customer in one-to-many relationship.
One customer has many notes. One note belongs to one customer.
Scaffolding the Note resource
We execute the following command to create a new Note resource.
1$ rails generate scaffold Note content:text customer_id:integer
We use customer_id
to represent the relationship of note belongs to customer.
As usual, we migrate the database.
1$ rake db:migrate
The console should have output likes the following.
Updating the routes
In config/routes.rb
, we nest the resources notes inside customers.
In addition, we can point the root path to our customers’ index page instead of using the default home screen.
1root 'customers#index'
This creates the following routing table.
Verb | URI Pattern | Controller#Action |
GET | / | customers#index |
GET | /customers/:customer_id/notes(.:format) | notes#index |
POST | /customers/:customer_id/notes(.:format) | notes#create |
GET | /customers/:customer_id/notes/new(.:format) | notes#new |
GET | /customers/:customer_id/notes/:id/edit(.:format) | notes#edit |
GET | /customers/:customer_id/notes/:id(.:format) | notes#show |
PATCH | /customers/:customer_id/notes/:id(.:format) | notes#update |
PUT | /customers/:customer_id/notes/:id(.:format) | notes#update |
DELETE | /customers/:customer_id/notes/:id(.:format) | notes#destroy |
GET | /customers(.:format) | customers#index |
POST | /customers(.:format) | customers#create |
GET | /customers/new(.:format) | customers#new |
GET | /customers/:id/edit(.:format) | customers#edit |
GET | /customers/:id(.:format) | customers#show |
PATCH | /customers/:id(.:format) | customers#update |
PUT | /customers/:id(.:format) | customers#update |
DELETE | /customers/:id(.:format) | customers#destroy |
You can get the above information by running rake routes
in console.
Define the association in model
Updating note controller
In app/controllers/notes_controllers.rb
1class NotesController < ApplicationController 2 before_action :set_customer 3 before_action :set_note, only: [:show, :edit, :update, :destroy] 4 5 # GET /notes 6 # GET /notes.json 7 def index 8 @notes = @customer.notes.all 9 end 10 11 # GET /notes/1 12 # GET /notes/1.json 13 def show 14 end 15 16 # GET /notes/new 17 def new 18 @note = @customer.notes.new 19 end 20 21 # GET /notes/1/edit 22 def edit 23 end 24 25 # POST /notes 26 # POST /notes.json 27 def create 28 @note = @customer.notes.new(note_params) 29 30 respond_to do |format| 31 if @note.save 32 format.html { redirect_to [@customer,@note], notice: 'Note was successfully created.' } 33 format.json { render :show, status: :created, location: @note } 34 else 35 format.html { render :new } 36 format.json { render json: @note.errors, status: :unprocessable_entity } 37 end 38 end 39 end 40 41 # PATCH/PUT /notes/1 42 # PATCH/PUT /notes/1.json 43 def update 44 respond_to do |format| 45 if @note.update(note_params) 46 format.html { redirect_to [@customer,@note], notice: 'Note was successfully updated.' } 47 format.json { render :show, status: :ok, location: @note } 48 else 49 format.html { render :edit } 50 format.json { render json: @note.errors, status: :unprocessable_entity } 51 end 52 end 53 end 54 55 # DELETE /notes/1 56 # DELETE /notes/1.json 57 def destroy 58 @note.destroy 59 respond_to do |format| 60 format.html { redirect_to customer_notes_url, notice: 'Note was successfully destroyed.' } 61 format.json { head :no_content } 62 end 63 end 64 65 private 66 # Use callbacks to share common setup or constraints between actions. 67 def set_customer 68 @customer = Customer.find(params[:customer_id]) 69 end 70 def set_note 71 @note = @customer.notes.find(params[:id]) 72 end 73 74 # Never trust parameters from the scary internet, only allow the white list through. 75 def note_params 76 params.require(:note).permit(:content, :customer_id) 77 end 78end
Updating all the links in view
In app/views/notes/index.html.erb
1<h1> 2 Listing notes for 3 <%= link_to @customer.name, @customer %> 4</h1> 5 6<table> 7 <thead> 8 <tr> 9 <th>Content</th> 10 <th>Customer</th> 11 <th colspan="3"></th> 12 </tr> 13 </thead> 14 15 <tbody> 16 <% @notes.each do |note| %> 17 <tr> 18 <td><%= note.content %></td> 19 <td><%= note.customer_id %></td> 20 <td><%= link_to 'Show', [@customer, note] %></td> 21 <td><%= link_to 'Edit', edit_customer_note_path(@customer, note) %></td> 22 <td><%= link_to 'Destroy', [@customer, note], method: :delete, data: { confirm: 'Are you sure?' } %></td> 23 </tr> 24 <% end %> 25 </tbody> 26</table> 27 28<br> 29 30<%= link_to 'New Note', new_customer_note_path %>
In app/views/notes/show.html.erb
In app/views/notes/new.html.erb
In app/views/notes/edit.html.erb
In app/views/notes/_form.html.erb
Almost done. In app/views/customers/show.html.erb
add:
in app/views/notes/index.html.erb
Add global navigation
Now we want to add a link back to “All Customers” page on all pages. We can add the link in the layout template. Add the following code in app/layouts/application.html.erb
.
1<%= link_to 'All Customers', customers_path %>
So the body of the layout file becomes:
This is the rusult we get after these steps.