ActiveRecord Introduction
Tags: beginners, webdev, ruby, programming
Published: 2023-01-25 17:32:25

SQL itself is an intuitive language–much like Ruby. It is literal, making it easy to learn and read a relational database. However, SQL commands can be cumbersome when used for large databases with a high degree of interconnectedness, so it makes sense that something like Object-Relational Mapping exists to resolve the problem of repetition and disorganization when handling a large volume of data. 

Object-Relational Mapping (ORM) is exactly what it sounds like: it takes an object-oriented language and maps it over to a relational database. The object-oriented language will literally “wrap” itself around the other language used to manipulate the database. This mapping technique is a really pretty unique and interesting way of translating one language into another to communicate with a database. 

There are libraries of ORM code that have already been written out for this purpose. The ORM library has built-in ORM methods and the one that Flatiron taught me to use is the Ruby gem: ActiveRecord. Using ActiveRecord, I learned to build tables and interact with a database without writing a line of SQL and without having to build my own ORM. I took a lot of notes on the process and I will explain it in the context of creating and managing a table specifically with the use of Sinatra, ActiveRecord, and Rake.

The purpose of the ORM library ActiveRecord, is ultimately to manipulate the database we create. Once ActiveRecord is installed we should obviously connect it to our database, and then tell our Ruby objects to use ActiveRecord by allowing the objects to inherit those built-in methods. 

Of note, the naming conventions for working between this semi-translation of object-oriented language and database-relational languages is necessary to keep in mind. Ruby, in this case, should have its class objects named with capitalization and kept as a singular noun (e.g., Person, Cat). Our tables are written in all-lowercase and should be pluralized (e.g., people, cats). 

First we make sure we have the sinatra-activerecord gem. We connect to the database using the standard config/database.yml file, and then we “create a migration” for setting up a new table: $ bundle exec rake db:create_migration NAME=create_games. (Note that “migrations” are simply “version control” with a timestamp for ActiveRecord that lets the database outline/schema changes be independent so each version of the database is making changes independently.) The creation of a new “migration” will generate a new file that has a timestamp along with the name and the rake task will, if properly set up, will already have a task dependency to run the environment.rb file, which will contain referral to all necessary files we want to load for a given task or application. Otherwise, the new migration file for the table we want to create should include the code for creating that table. Here is an example:

# db/migrate/20210716095220_create_games.rb

class Game < ActiveRecord::Migration[6.1]
  def change
    create_table :games do |t|
      t.string :title
      t.string :developer
    end
  end
end

# ‘t’ is a symbol in ActiveRecord that is a special migration object
# Recall that the id column for the primary key is generated automatically for every table! no need to specify it here.
# Note that the Game class is inheriting from the ORM ActiveRecord library methods to allow us to automatically wrap our object-oriented Ruby code around SQL, so we can ultimately manipulate the database.
# Note the naming conventions used for the class object vs the database table name.




Once we have written the code in Ruby for creating the table, we run the migration ($ bundle exec rake db:migrate) which will return confirmation that can be further checked with the following command: $ bundle exec rake db:migrate:status, and/or we can check our updated table outline/schema.  This is ultimately all that is needed to create a table. 

Modification of that table using ActiveRecord and migrations via Rake simply requires an understanding of what rake tasks we have at our disposal which we can view in the command line with $ rake -T. Because we are using migrations (aka version control) in order to update our table, each modification of the table requires that we create a new migration $ bundle exec rake db:create_migration NAME=example_name_add_new_column_to_table, which creates a new file, where new changes are integrated for a given table. 


# db/migrate/20210716100800_example_name_add_new_column_to_table.rb

class ExampleNameAddNewColumnToTable < ActiveRecord::Migration[6.1]
  def change
    add_column :games, :year, :integer
  end
end




The ActiveRecord built-in methods are simple enough to use as they are intuitively written and can be found here. The changes themselves are then integrated through the migration ($ bundle exec rake db:migrate). 

This was confusing to me at first because there were times when I would create a table, wanted to add or delete a column of data, but didn’t know what to type in the field for the change method of the new class I was adding. I would use the new migration file to type out the re-creation of a table that already existed with modifications to the table that I wanted to include. This is an important concept to grasp and one I should probably try and drive home. Noting the built-in methods in ActiveRecord and how to use them is important for not making the mistake of re-writing the table from scratch.