Rails – Adding the ability to log notes in our CRM (Active Record Associations)

So for the CRM my company is using I started off with the ability to just create companies and plug in the company name, phone number, topic, and website address.  This is perfect for a majority of the users but a few want to be able to create notes for each call they make to a company.  So today we’re going to review how I set this up in my rails application for my beta (read: awesome) users.

We’ll start by creating the notes object.  So each company will have many notes (since you may want to leave a note for every call) but each note will only belong to one company.  To really get comprehensive you can go read the RubyOnRails.org guide to Active Record Associations – or just follow along here.

Since notes will belong to a company, each note will have to have a company_id assigned to it.  This is called a reference.  We’ll keep this in mind when we generate our scaffolding. We’ll want to include a comment section to store the actual note as well.

command line
$ rails g scaffold Note comment:text company:references

This will create the following migration file (I’ve added the line t.references :user... so that each note also belongs to a user):

class CreateNotes < ActiveRecord::Migration
  def change
    create_table :notes do |t|
      t.text :comment, null: false
      t.references :company, index: true, foreign_key: true
      t.references :user, index: true, foreign_key: true

      t.timestamps null: false

We should also double check our User and Company models to make sure that has_many has been added:

class Company < ActiveRecord::Base
  has_many :notes
class User < ActiveRecord::Base
  has_many :companies
  has_many :notes, through: :companies

We’ll go ahead and execute our migration and then check out the note model and make sure it looks like this:

class Note < ActiveRecord::Base
  belongs_to :company

Now we’re ready to actually do that thing where users actually see that we’ve actually been working this whole time – set up our views!

Sad but true

Sad but true

We’ll want to show our notes for each company after we click on that company so we’ll also need to add methods to display notes in our Companies Controller.  Not front end work yet like I promised but give it a sec.

def show
    @notes = @company.notes.all

And now onto our Companies Show view file! Told ya we’d get here shortly. So I just want my beta users to be able to access this feature so let’s show a partial if the current user is a beta user, as well as include a button that allows the user to create a new note:

<% if current_user.try(:beta?) %>
  <div class="container center">
    <li class='btn btn-success btn-md'><%= link_to("Add Note", new_note_path(:company_id => @company.id)) %></li>
  <% if @company.notes.any? %>
    <%= render 'companynotes' %>
  <% end %>
<% end %>

And then we’ll create our partial. In it we’ll want to show each note previously created for this company, as well as when it was created, and we want the newest note to be nearest the top:

<h2 align="center">Notes for <strong><%= @company.name %></strong> </h2>
<div class="container-fluid">
  <% @notes.reverse_each do |t| %>
     <div class="col-xs-8 col-xs-offset-2">
        <div class="panel panel-default">
          <div class="panel-heading">
            <strong>Note Created: </strong> <%= t.created_at.strftime('%H:%M:%S %B, %d, %Y') %>
          <div class="panel-body">
            <%= t.comment %>
            <% if t.user_id? %>
              <div class="company-user">
                <%= User.find(t.user_id).username %>
            <% else %>
            <% end %>
          <div class="panel-footer">
            <% if current_user.try(:admin?) %>
              <%= link_to("Edit", edit_note_path(t), class: "btn btn-xs btn-primary") %>
              <%= link_to("Delete", note_path(t), method: :delete, data: { confirm: "Are you sure?"}, class: "btn btn-xs btn-danger") %>
            <% end %>
  <% end %>

Now, when a beta user creates a note, the default behavior is to send them to that note’s show page. But we’d obviously rather that they are sent back to the company show page. We’ll fix this by altering some the code in the Notes Controller:

def create
  @note = Note.new(note_params)
  respond_to do |format|
    if @note.save
      format.html { redirect_to @note.company, notice: 'Note was successfully created.' }
      format.json { render :show, status: :created, location: @note.company }
      format.html { render :new }
      format.json { render json: @note.errors, status: :unprocessable_entity }

And there you have it! Simple as 1, 2, however many steps that was.

Loading Facebook Comments ...

Leave a Reply

Your email address will not be published. Required fields are marked *