Chapter 6 – Introducing Ruby on Rails (Part B)

Let’s continue the CRM system

Customer list

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.

Customer note relationshop

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.

1== 20140705052047 CreateNotes: migrating ======================================
2-- create_table(:notes)
3   -> 0.0056s
4== 20140705052047 CreateNotes: migrated (0.0058s) =============================

Updating the routes

In config/routes.rb, we nest the resources notes inside customers.

1resources :customers do
2  resources :notes
3end

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

Customer note relationshop

In app/models/customer.rb

1class Customer < ActiveRecord::Base
2  has_many :notes
3end

In app/models/note.rb

1class Note < ActiveRecord::Base
2  belongs_to :customer
3end

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

1...
2
3<%= link_to 'Edit', edit_customer_note_path(@customer, @note) %> |
4<%= link_to 'Back', customer_notes_path %>

In app/views/notes/new.html.erb

1<h1>New note</h1>
2
3<%= render 'form' %>
4
5<%= link_to 'Back', customer_notes_path %>

In app/views/notes/edit.html.erb

1<h1>Editing note</h1>
2
3<%= render 'form' %>
4
5<%= link_to 'Show', @note %> |
6<%= link_to 'Back', customer_notes_path %>

In app/views/notes/_form.html.erb

1<%= form_for([@customer,@note]) do |f| %>
2...

Almost done. In app/views/customers/show.html.erb

add:

1<%= link_to 'Create Note', new_customer_note_path(@customer) %>
2<%= link_to 'Show Notes', customer_notes_path(@customer) %>

in app/views/notes/index.html.erb

1<h1>
2  Listing notes for
3  <%= link_to @customer.name, @customer %>
4</h1>
5...

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:

1<body>
2
3<%= link_to 'All Customers', customers_path %>
4<%= yield %>
5
6</body>

This is the rusult we get after these steps.

Result after part b

overlaied image when clicked on thumbnail

Makzan | Introducing web design | Table of Content