Object Relational Mapping (ORM) & ActiveRecord

Christine Tran
6 min readOct 12, 2017

--

Jumping off from SQL, databases and tables are still important towards learning about Object Relational Mapping. It also affects the outcome of ActiveRecord. More on that later.

ORMs connect objects to tables in a relational database by using Object Oriented Programming (OOP) languages like Ruby. It cuts down on repetition. The properties and relationships of the objects are stored and accessible without writing SQL statements directly, too.

OOPs can manage database data through “mapping.”

  • Classes are mapped to the inside of a database’s tables
  • Instances of the classes are mapped to the database’s table’s rows

Mapping Ruby Classes to Database Tables

Ruby deals with objects. Databases deal with raw data.

Ruby objects aren’t saved into a database. A Ruby’s object’s attributes are used to create new rows in the database table. Each row represents an instance of the Ruby object.

object   |id |      name     |    album     |
instance 1 | 1 | first aid kit | Lion's Roar |
instance 2 | 2 | Kylie Minogue | Abbey Road Session |

Mapping classes to a table means data is stored in an organized manner.

  • Create database
  • Create class table; there’s a convention to pluralize the name of the class to create the name of the table. class Song to a database creates the songs table
  • The class’ methods are written as column names that match the attr_accessors of the class.
class Song

attr_accessor :name, :album, :id

def initialize(name, album, id=nil)
@id = id
@name = name
@album = album
end

...

end

Mapping stores raw data describing a given Ruby object in a table row. To reconstruct a Ruby object from the stored data, that same row in the table is selected. When querying the database, methods are coded to access those data and convert into an instance of the appropriate class (Ruby objects).

SQLite converts the database into Ruby objects which then returns an array of data for each row [id, data_name, data_value].

def self.new_from_db(row)
instance_name = self.new
instance_name.id = row[0]
instance_name.name = row[1]
instance_name.length = row[2]
instance_name # return the newly created instance
end
#Database tableobj's instance name |id | data_name | data_value |
first_aid_kit | 1 | first aid kit | Lion's Roar |
kylie_minogue | 2 | Kylie Minogue | Abbey Road Session |
#the array[
id: 1, name: first aid kit, album: Lion's Roar,
id: 2, name: Kylie Minogue, album: Abbey Road Session
]

That array will then be queried to be matched and those instances (as rows) can be iterated upon.

Updating records in ORM via Dynamic ORMs:

  • Get/find attributes from the row in database table
  • Recreate them into a Ruby object
  • Make changes to that object using Ruby methods
  • Then save all updated attributes back into database

The goal of dynamic ORM is to define a series of methods that can be shared by any class. So, we need to avoid explicitly referencing table and column names. To accomplish this, we use metaprogramming (a set of code that writes code for us).

Dynamic ORMs

  • Create database table
  • Metaprogram based on that table
  • Set up database
  • Build attr_accessors from column names
  • Define table name

ActiveRecord

Something similar to Dynamic ORM is ActiveRecord. It maps database tables to Ruby classes as a framework. As noted by the rubyonrails guide, ActiveRecord:

  • Represents models and their data
  • Represents associations between those models
  • Represents inheritance hierarchies through related models
  • Validates models before they get persisted to the database
  • Performs database operations in an object-oriented fashion

Active Record is also a Ruby gem that provides us with a library of code that give us a lot of functionality.

The pattern begins by:

  • Connecting to a database
  • Create a table
  • Add ActiveRecord’s Base methods to our class by inheritance ActiveRecord::Base
class Student < ActiveRecord::Base
end

Types of base methods include

  • .column_names
  • .create
  • .find
  • .find_by
  • .save
  • attr_accessors

ActiveRecord automatically has methods that read and alters stored data from within its tables. These methods are called CRUD (Create, Read, Update, and Delete).

Create

  • ActiveRecord objects can be created from a hash, a block, or have their attributes manually set. This method returns the object and saves it to the database

Read

  • Accesses data

Update

  • When an Active Record object is received, its attributes can be altered and save to the database

Delete

  • Active Record objects can be deleted on the spot

Migration & Rake

A language called migrations manages a database. Migrations uses rake. Rake is a tool that automates certain jobs through rake tasks. A task is defined through the command line to execute those jobs. Rake is a part of Ruby and needs only be created in a file called Rakefile. In this file, the task is defined:

# Task + name of task as a symbol + block that has the code to be executed

task :hello do
# the code we want to be executed by this task
end

In Terminal, when entering rake hello the code is executed back.rake -T when run in the terminal gives a list of available Rake tasks and its descriptions. For these tasks to work, they need descriptions.

desc 'outputs hello to the terminal'
task :hello do
puts "hello from Rake!"
end

Rake tasks can be grouped through namespace

namespace :greeting do 
desc 'outputs hello to the terminal'
task :hello do
puts "hello from Rake!"
end

desc 'outputs hola to the terminal'
task :hola do
puts "hola de Rake!"
end
end

In terminal we can use either of those grouped Rake tasks by entering:

rake greeting:hello

rake greeting:hola

How Rake and Migration interact with each other is by rake db:migrate. Database tables are created and then migrated using a rake task. When we want to load a database, we can call on rake db:migrate.

Rake console

This starts up the Pry console for us to play with our code. rake db:migrate would need to be run before we entering rake console in terminal.

Setting up Migration

Migration helps alter the database schema over time without having to write SQL. It keeps records of the alteration so nothing is altered completely without history. ActiveRecord can reverse the migration by rolling it back to its previous state.

The class inherits ActiveRecord’s ActiveRecord::Migration module. This ActiveRecord::Migration module allows the class CreateArtists to generate the artists table.

# db/migrate/01_create_artists.rb

class CreateArtists < ActiveRecord::Migration
...some code
end
  • Typically the files within db/migrate generates the tables with its columns. The file …/01_create_artists.rb would usually have the class set up like so:
class CreateArtists < ActiveRecord::Migration
def change
create_table :artists do |t|
t.string :name
t.string :genre
t.integer :age
t.string :hometown
end
end
end
  • Each column will state the data type followed by its name as a symbol
  • By default, create_table creates a primary key called id.

Running migrations

  • Run rake db:migrate in terminal.
  • The table artists would have its own class and file called artist.rb that’s also called the Model where ActiveRecord::Base will connect to the artists database
# artist.rb

class Artist < ActiveRecord::Base
end

Using migrations to alter/update an existing table:

A few types of alteration methods:

* Add_column :table_name, :column_name, data type for the new column
* Remove_column :table_name, :column_name, data type for the new column
* change_column :table_name, :column_name, data type for the new column

A new migration file must be created to modify any existing tables then saved before running rake db:migrate again.

# db/migrate/02_add_favorite_food_to_artists.rb

class AddFavoriteFoodToArtists < ActiveRecord::Migration
def change
add_column :artists, :favorite_food, :string
end
end

Active Record Querying Methods

Finding information and datasets using Active Record can be done from a variety of methods that’s found in the ruby guild — http://guides.rubyonrails.org/active_record_querying.html

ActiveRecord Associations

Classes can be built to associate with one another but uses a lot of code to do it. ActiveRecord associations does this job with less code.

Types of relationships between models:

  • belongs_to
  • has_one
  • has_many
  • has_many :through
  • has_one :through
  • has_and_belongs_to_many

These associations is similar to how we dealt with venn diagram in SQL. Relationship matter and helps write less code.

Final Thoughts

Active Record is a really great tool. There’s much more to it that I’m not quite sure about yet. I hope to keep up with this topic and build my skills from it.

Originally published at christineiscoding.com

--

--