In this post, we will see how one model can be associated to another model. Associations are very helpful when you want to fetch child or parent records of an existing entity.

Here are the type of associations in Rails:

  1. has_one
    In this type of association, the parent object declares that it has at most one child object.
    For example:

    class Supplier < ActiveRecord::Base
       has_one :account                   # note singular name
    end

    By default, Rails assumes that foreign key column would be modelname_id. But, if you want to specify your own foreign key, then you can do:

    class Supplier < ActiveRecord::Base
       has_one :account, foreign_key: account_number
    end
  2. has_many
    In this type of association, the parent object declares that it has multiple child objects.
    For example:

    class Customer < ActiveRecord::Base
       has_many :orders                   # note plural name
    end
  3. belongs_to
    In this type of association, the child object declares that it has a parent object.
    For example:

    class Order < ActiveRecord::Base
       belongs_to :customer               # note singular name
    end
  4. has_many :through
    In this type of association, the parent object A declares that it has multiple C objects through object B.
    For example:

    class Physician < ActiveRecord::Base
        has_many :appointments
        has_many :patients, through: :appointments
    end
  5. has_one :through
    In this type of association, the parent object A declares that it has at-most one C through object B.
    For example:

    class Supplier < ActiveRecord::Base
        has_one :account
        has_one :account_history, through: :account
    end
  6. has_and_belongs_to_many (many to many)
    In this type of association, an object A declares that it has multiple objects B and the object B may belong to multiple A.
    For example:

    class Campaign < ActiveRecord::Base
        has_and_belongs_to_many :cars
    end
    class Car < ActiveRecord::Base
        has_and_belongs_to_many :campaigns
    end
  7. Polymorphic associations
    In this type of association, the child object belongs to either A or B.
    For example:

    class Picture < ActiveRecord::Base
       belongs_to :image_type, polymorphic: true
    end
    class Employee < ActiveRecord::Base
       has_many :pictures, as: :image_type
    end
    class Product < ActiveRecord::Base
       has_many :pictures, as: :image_type
    end

    Here we declared that a Picture is either of Employee or of a Product.

Let us create a project to understand the associations. I suggest you first read the post Understanding models in Rails

  1. Create a new rails project
     rails new assoc
  2. We will be using MySql database. Open your Gemfile and add the following line:
    gem 'mysql2', '~>0.3.1'

    Also, remove the line:

    gem 'sqlite3'
  3. Now execute:
    bundle install
  4. Next, create the following two models:
    rails generate model Employee
    rails generate model Sale
  5. Edit the file app/models/employee.rb and make it look like this:
    class Employee < ActiveRecord::Base
      has_many :sales
    end

    Now, edit the file app/models/sale.rb and make it look like this:

    class Sale < ActiveRecord::Base
      belongs_to :employee
    end
  6. Now, edit the migration file db/migrate/xxxxx_create_employees.rb and make it look like this:
    class CreateEmployees < ActiveRecord::Migration
      def change
        create_table :employees do |t|
          t.string :name, limit: 50
          t.string :gender, limit: 6
        end
      end
    end
  7. Now, edit the migration file db/migrate/xxxxx_create_sales.rb and make it look like this:
    class CreateSales < ActiveRecord::Migration
      def change
        create_table :sales do |t|
    
          t.integer :employee_id
          t.float :amount
          t.string  :item_name, limit: 100
          t.date :created_at
        end
      end
    end
  8. Next, execute the following command to create your tables:
    rake db:migrate
  9. Execute following queries on database to put dummy data in the table
    insert into employees(id, name, gender) values(1, 'a', 'male');
    insert into employees(id, name, gender) values(2, 'b', 'female');
    insert into employees(id, name, gender) values(3, 'c', 'male');
    insert into employees(id, name, gender) values(4, 'd', 'female');
    
    insert into sales(employee_id, amount, item_name, created_at) values(1, 5000, 'Adidas Shoe', '2015-3-10');
    insert into sales(employee_id, amount, item_name, created_at) values(1, 3000, 'Rayban Aviator', '2015-3-10');
    insert into sales(employee_id, amount, item_name, created_at) values(2, 1500, 'Sandisk Memory Card', '2015-3-10');
    insert into sales(employee_id, amount, item_name, created_at) values(1, 4000, 'Nike Shoe', '2015-3-10');
    insert into sales(employee_id, amount, item_name, created_at) values(3, 10000, 'Samsung LCD', '2015-3-10');
    insert into sales(employee_id, amount, item_name, created_at) values(4, 30000, 'Nexus 6', '2015-3-10');
    insert into sales(employee_id, amount, item_name, created_at) values(4, 32000, 'Samsung galaxy S5', '2015-3-10');
  10. Now, we will create a controller. We will create a method named list that will show all employees and their sales. Execute the command:
    rails generate controller Test list
  11. Modify the file app/controllers/test_controller.rb and make it look like this:
    class TestController < ApplicationController
      def list
        @employees = Employee.all
      end
    end
  12. Now modify the view file app/views/test/list.html.erb and make it look like this:
    <table style="border: 1px solid #ccc; padding: 20px; width: 800px; margin: auto">
      <tr>
      <% @employees.each do |employee| %>
    
        <tr>
          <td style="vertical-align: top"><%=employee.name%></td>
          <td style="vertical-align: top"><%=employee.gender%></td>
          <td style="width:50%; padding-bottom: 20px; vertical-align: top">
            <table style="border: 0">
            <% employee.sales.each do |sale| %>
              <tr>
                <td style="padding-bottom: 10px; width:50%"><%=sale.item_name%></td>
                <td style="width:25%"><%=sale.amount%></td>
                <td style="width:25%"><%=sale.created_at%></td>
              </tr>
              <% end %>
            </table>
          </td>
        </tr>
    
      <% end %>
      </tr>
    </table>
  13. Start your server now:
    rails server
  14. In the browser, navigate to the URL:
    http://localhost:3000/test/list