Adding Associations

We’ve got our basic Task Model up and running. It’s in the database and we can add, remove, and view data associated with it through the API.

But that’s only half of an application. Imagine we want to add our task to a list? Or if we have multiple users in our application how can we associate it with them?

That’s where ActiveRecord associations come in. With it we can make links between our models.

Let’s add a list

We want to associate a Task with a list…great. Let’s create an association. But first we’ve got to create the table, right?

rake db:create_migration NAME=create_lists_table

Inside of your migration, you’ll find code similar to the following:

class CreateListsTable < ActiveRecord::Migration
		def change
		end
end

In this code, add a line to setup the table and have a name associated with it.


class CreateLists < ActiveRecord::Migration[5.0]
  def change
   create_table :lists do |t|
     t.string :name
   end
 end
end

and finally apply the migration with the following:

rake db:migrate

Create a model for it

In the models folder, create a new file called list.rb and add the following code inside of it:


class List < ActiveRecord::Base
  
 validates_presence_of :name

end

THen we need to include the model in our application by adding it to the main file. Add the following line to your app.rb

require_relative './models/list'

Setup a seed

Let’s open up the db/seed.rb and add some dummy data that we can test with. Add the following:

List.delete_all
List.reset_autoincrement

List.create!([{ name: "My First List" } ])
List.create!([{ name: "My Second List" } ])

To add this to the database, then type

rake db:seed

Adding associations

Wouldn’t it be great if it knew that tasks and lists were linked? Well activerecord let’s us do exactly this. We need to add one line of code to each model to tell it about the nature of these associations.

Commands:


has_many :table_name # this goes in the model that's the parent in the relationship - they have many children i.e lists

belongs_to :table_name # this goes in the model that we want to make the link from i.e. tasks

When we write this, ActiveRecord expects there to be a column named something like <table_name>_id. This stores the ID of the table we want to make the association with.

For example, if tasks belongs to lists, then tasks must have a column called list_id. Then when we want to find a list that’s associated with a task, ActiveRecord will look it up by this id. When we want to find the tasks associated with a list, it’ll do a search for all records/rows that contain the matching id in list_id.

So, let’s make those connections

Open lists.rb and add:

  has_many :tasks

This means that any list can have one or more tasks associated with it. This connection is made from the id of list that is added to the list_id column of tasks.

Now add the following to task.rb.

  belongs_to :list

This means it has one and belongs to. It can only have one. Now both have a list and a tasks object associated with them. Great!

Adding Endpoints

It’s pretty much the same as before. We can add the following RESTful methods to app.rb


get '/lists' do
  List.all.to_json(include: :tasks)
end


get '/lists/:id' do
  List.where(id: params['id']).first.to_json(include: :tasks)
end
 
post '/lists' do
  list = List.new(params)
 
  if list.save
    list.to_json(include: :tasks)
  else
    halt 422, list.errors.full_messages.to_json
  end
end
 
put '/lists/:id' do
  list = List.where(id: params['id']).first
 
  if list
    list.name = params['name'] if params.has_key?('name')
 
    if list.save
      list.to_json
    else
      halt 422, list.errors.full_messages.to_json
    end
  end
end
 
delete '/lists/:id' do
  list = List.where(id: params['id'])
 
  if list.destroy_all
    {success: "ok"}.to_json
  else
    halt 500
  end
end 

Spot the difference. Did you notice this to_json(include: :tasks). Yes. We can add a little bit extra to how JSON writes out our objects and tell it also to include our associations. Neat.

Try them out!!!

×

Subscribe

The latest tutorials sent straight to your inbox.