DEV Community

pjparham
pjparham

Posted on

Quick Start guide to creating a table using Active Record

Object-Relational Mapping

Object-Relational Mapping(ORM) is a technique that allows you to query and change data in a database using an object-oriented approach. When using an ORM, your classes will be database tables and instances of those classes will exist as rows in those tables. Using an ORM allows a developer to cut down on repetitive code while also implementing conventional, organized patterns. These practices keep a code base clean and readable, which is important especially when many developers will be working on the code.

There are patterns that you will see when using an ORM that are worth taking note of. While classes are typically defined with a singular word, a class's corresponding table will be plural. If we have a Book class, the corresponding table will be books. Instances of the Book class will be stored in the books table as rows, and attributes for those instances will be stored in columns in the books table.

Introducing Active Record

Active Record is an ORM library that can be used with Ruby. Active Record comes with many built in methods that make it easier to manipulate our data. To use the Active Record gem in your code, you can simply run gem install activerecord in your terminal, or by including it in your code's Gemfile.

To make use of Active Record's built-in ORM methods, we need to make our Ruby class a subclass of ActiveRecord::Base.

class Book < ActiveRecord::Base
end 
Enter fullscreen mode Exit fullscreen mode

Now our Book class is able to talk to the books table in the database. Something important to keep in mind when using Active Record is that Active Record follows convention over configuration. This means that as long as you follow the conventions adopted by Active Record, you will need to write very little to no configuration for your models. It is very important that your class names are singular and table names are plural. As long as a developer follows this rule, Active Record can save developer's a lot of time and make their code much more readable.

Some useful methods from Active Record

Making our Ruby classes subclasses of Active Record gives them access many methods. One very useful method is that attr_accessors are usable with our code without having to explicitly write them in. I've defined some other useful methods from Active Record below, but I recommend any developer that is interested in using Active Record to read the Active Record docs to see all that it can really do.

.column_names

Retrieve a list of the columns in a table:

Book.column_names
#=> [:id, :name, :author, :genre]
Enter fullscreen mode Exit fullscreen mode
.create

Creates a new object for the class and saves the instance to the class's corresponding table

Book.create(name: 'The Stranger', author: 'Albert Campus', genre: 'Philosophical novel')
# INSERT INTO books (name, author, genre) VALUES ('The Stranger', 'Albert Campus', 'Philosophical Novel') 
#=> #<Book: 0x00009f785d0832b0 id: 1, name: "The Stranger", author: "Albert Campus", genre: "Philosophical novel">
Enter fullscreen mode Exit fullscreen mode
.all

Return all the records from a table as instances of its class

Book.all
# SELECT "books".* FROM "books"
# => [#<Book: 0x00009f785d0832b0 id: 1, name: "The Stranger", author: "Albert Campus", genre: "Philosophical novel">]
Enter fullscreen mode Exit fullscreen mode
.find

Retrieve an object from the database by its id:

Book.find(1)
# SELECT "books".* FROM "books" WHERE "books"."id" = 1 LIMIT 1
#=> #<Book: 0x00009f785d0832b0 id: 1, name: "The Stranger", author: "Albert Campus", genre: "Philosophical novel">
Enter fullscreen mode Exit fullscreen mode
.find_by

Find an object by any attribute, such as author

Book.find_by(author: 'Albert Campus')
# SELECT "books".* FROM "books" WHERE "books"."author" = 'Albert Campus' LIMIT 1
#=> #<Book: 0x00009f785d0832b0 id: 1, name: "The Stranger", author: "Albert Campus", genre: "Philosophical novel">
Enter fullscreen mode Exit fullscreen mode

Active Record Migrations

Active Record migrations are used to set up our database, and we use this format for many reasons. They provide a history of the changes made, providing version control for our database. Using Active Record migrations also allows us to forego writing SQL statements to create or change tables, as Active Record will do this for us under the hood.

To tell Active Record how we want it to connect to our database, we will use a config/database.yml file. This file is used by convention with Active Record to provide details about how to connect with our database. For this example, we will be using SQlite, but Active Record does support other database adaptors. This is what it looks like:

development:
  adapter: sqlite3
  database: db/development.sqlite3

test:
  adapter: sqlite3
  database: db/test.sqlite3
Enter fullscreen mode Exit fullscreen mode

Now let's set up our environment.rb file. This file requires the gems in our Gemfile to give our program access them them. ENV["RACK_ENV"] is our environment variable, which is set to development in this example. RACK_ENV is a specific environment variable used by the sinatra-activerecord gem to determine what database to connect to. Our environment.rb file contains the following:

ENV["RACK_ENV"] ||= "development"

require 'bundler/setup'
Bundler.require(:default, ENV["RACK_ENV"])
Enter fullscreen mode Exit fullscreen mode

Creating a migration

To create a migration to set up our books table, we will run the following command in our terminal:

bundle exec rake db:create_migration NAME=create_books
Enter fullscreen mode Exit fullscreen mode

We use bundle exec rake to access our rake file that gives us a multitude of commands that can be run in the terminal, and the above code is used to create a new migration. This command generates a new file in db/migrations called 20221116095220_create_books.rb. The timestamp at the beginning is crucial for Active Record as it tells your program which order to run the migrations. The following code will be in the newly created file:

class CreateBooks < ActiveRecord::Migration[6.1]
  def change
  end
end
Enter fullscreen mode Exit fullscreen mode

Since we are using this migration to create a new table, we will use the create_table command to do so. When we create our table, we will provide the attribute names for the columns as well as the datatype for each of those columns. The id column is dynamically generated, so there is no need to include it here!

class CreateBooks < ActiveRecord::Migration[6.1]
  def change
    create_table :books do |t|
      t.string :name
      t.string :genre
      t.string :author
    end
  end
end
Enter fullscreen mode Exit fullscreen mode

Now that the file is set up and you've defined how you want your table to look, we must run the migration! This will create a new database file based on the contents of your migration, and it will also create a db/schema.rb file which will give you a quick view of the set up of your database. We run our migration with the following command in the terminal:

bundle exec rake db:migrate
Enter fullscreen mode Exit fullscreen mode

At this stage, our db/schema.rb file will look like this:

ActiveRecord::Schema.define(version: 2022_11_16_095220) do
  create_table "books", force: :cascade do |t|
    t.string "name"
    t.string "author"
    t.string "genre"
  end
end
Enter fullscreen mode Exit fullscreen mode

That's it! The table now exists in the database with the columns that we have defined in our migration, as well as an id column. This is meant to serve as a brief guide to get started with Active Record migrations, but there is so much more that you can do using Active Record! Some of the most powerful use cases for Active Record involve creating associations between classes and tables. I encourage you to check out the resources below on Active Record Basics and Active Record associations to see all that Active Record can help you accomplish. Happy Coding!

Resources

Active Record Basics
Active Record Associations

Top comments (0)