Quick Start guide to creating a table using Active Record
Tags: ruby, activerecord
Published: 2022-11-20 23:52:36

#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 
```
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](https://guides.rubyonrails.org/active_record_basics.html#convention-over-configuration-in-active-record) 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]
```
######`.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">
```
######`.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">]
```
######`.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">
```
######`.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">
```
#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
```
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"])
```
###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
```
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
```
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
```
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
```
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
```
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](https://guides.rubyonrails.org/association_basics.html) 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](https://guides.rubyonrails.org/active_record_basics.html)
[Active Record Associations](https://guides.rubyonrails.org/association_basics.html)