An Overview of Object Relational Mapping && ActiveRecord

Dace
4 min readApr 24, 2015

--

Writing great software relies not only on well-structured, efficient code, but also how that code is able to manage and interact with key data. Building complex systems requires that both be organized and cooperative.

Objects in an object-oriented programming language like Ruby contain both data and logic behavior — an idea based in software engineering principles.

Meanwhile, the data that we hope to model that logic around is best stored within relational databases (rooted in mathematical principles) and sorted by columns and rows that rely on their own domain specific language (DSL) to query that information. The key differences between objects and data don’t stop there. Data in these tables reference other tables with the use of foreign keys (designated columns from one table that point towards a connection with another table), while Ruby references objects in memory.

In order to make it easier to access and use this information, we need a way to translate it from it’s relational database form into objects that Ruby is more familiar with. Object relational mapping — or ORM, is a design pattern for converting (wrapping) that data stored within a relational database into an object that can be used within an object oriented language. This is important because it allows Ruby to be able to call methods on and retrieve information from the object.

Introducing Active Record

Active record is the default design pattern used by the Ruby on Rails web framework. It allows you to easily translate and manipulate your information from a relational database table into an object in Ruby.

Think of a generic ORM as a recipe with 20 detailed steps on how to bake a regular cake — each written out, line by line. Every single step in that list of instructions would be responsible for one very important task. ActiveRecord contains all the same functionality as that detailed recipe, but instead of needing to list them out, by simply saying ‘bake a cake’ you now have access to every step from your ORM, coupled with the ability to further customize it if needed.

In Active Record, a modeled class relates to a table of information:

…and an instance of that class (your object) relates to an individual row in that table:

In Patterns of Enterprise Application Architecture’, author and programming expert Martin Fowler describes the principles that Active Record is responsible for:

  1. Construct an Active Record instance from a SQL result set row
  2. Construct a new instance for later insertion into the table
  3. Static finder methods to wrap commonly used SQL queries and return Active Record Objects
  4. Get and set the fields
  5. Implement some pieces of business logic

Take the following code for example — written in an ORM pattern that takes data from a database and gives us the ability to create a new Student instance, use finder methods to read other instances, update instances and finally save them to the database:

Building an ORM from scratch

class Student # students
@@db = SQLite3::Database.new('db/students_store.db')
@@db.results_as_hash = true

attr_accessor :id, :name, :super_power
def self.new_from_row(row)
s = new
s.id = row["id"]
s.name = row["name"]
s.super_power = row["super_power"]
s
end
def self.all
sql = <<-SQL
SELECT *
FROM students
SQL
@@db.execute(sql).map do |row|
new_from_row(row)
end
end

def self.find_by_name(name)
sql = <<-SQL
SELECT *
FROM students
-- WHERE name="#{name}"
WHERE name= ?
SQL

@@db.execute(sql, [name]).map do |row|
new_from_row(row)
end.first
end
def save
if persisted?
update
else
insert
end
end

def persisted?
!!id
end

def update
sql = <<-SQL
UPDATE students
SET name=?, super_power=?
WHERE id=?
SQL

@@db.execute(sql, [name, super_power, id])
end

def insert
sql = <<-SQL
INSERT INTO students (name, super_power)
VALUES (?,?)
SQL

@@db.execute(sql,[name, super_power])
self.id = Student.all.last.id
end
end

vs. Having ActiveRecord build it for you

ActiveRecord takes care of abstracting away the original ORM into only 2 lines of code.

When a class is able to take advantage of ActiveRecord (“inherits from ActiveRecord::Base”), ActiveRecord abstracts all of the CRUD functionality (Create/Read/Update/Delete) away from the original ORM. Based on your class’ name, ActiveRecord also matches that class with it’s corresponding table in that database. Magic. (but not really.)

In short, ActiveRecord makes your life a whole lot easier.

Be thankful :)

--

--