ActiveRecord & Migration in Ruby for Beginners

Image for post
Image for post

So began my friendship with ActiveRecord…

ActiveRecord was created to make coding easier, but it can feel like a new language. We’ll start with a guide to ActiveRecord and migration and end with a list of methods ActiveRecord gives us in Ruby. This information can be useful to understand the concepts and as a reference.

Image for post
Image for post
ActiveRecord for Ruby

What is ActiveRecord and Why Do We Use It?

Image for post
Image for post
The classes (below) each have their own tables (above)

ActiveRecord gives coders a quicker way to make tables that correspond to classes. It also comes with many great methods for creating, reading, updating, and deleting information in our tables. Even more, some people love ActiveRecord because it eliminates our need for coding in SQL.

It’s wonderful, but it is confusing and difficult to start.

Standard practice says each class in our code should be its own table in our database, and each attribute in that class should be a column in that table. ActiveRecord does most of the work for us, but first it requires migration. This guide has three distinct phases.

1. Write the code that will create the database, tables, and columns
2. Run “rake db:migrate” to tell the computer to run the code in step 1
3. Create classes, which can already interact with the database

Let’s take a closer look.

Image for post
Image for post

First, we write code that will create the database and tables. From the project’s main folder in the Command Line Interface (“CLI”, Terminal on MacOS), we can make the appropriate files and folders by typing

rake db:create_migration NAME=create_xyz_table

This creates the folder “db,” the “migrate” folder inside “db,” and our file inside “migrate.” It’s the easiest way and also the least likely to cause issues with ActiveRecord. The table names will be like 20190305195340_create_xyz_table.rb; The number is the year, month, day, hour, minute, and second in 24-hour Greenwich Mean Time (GMT) when we made the file. Our version of “create_xyz_table” should be similar to create_songs_table, create_artists_table, add_genre_to_songs. Be descriptive.

Repeat the steps above to make files for each table, and the migration (in step 2) will run them in the order they were created (which is why they have the long time stamps at the front).

IMPORTANT: The class names inside those tables should have the same names as the descriptive file names, but each word is capitalized without spaces nor underscores. Also note that the table name is always plural (“songs,” “artists”). This will help everything run smoothly.

Here is an example for file 20190305200530_create_songs_table.rb.

This code will create a table named “songs”

In line 1, Migration[4.2] specifies the version, which is required. If we try step 2 without a number and brackets there, it could work. If it doesn’t work, the error message should tell us the proper number to put there.

The code above will create a table called “songs” in the database (which it also created for us — db/development.db), and the table’s columns are name, track_number, and good_song. The values in name are strings, track_number stores integers, and good_song has booleans (true or false).

Punctuation and capitalization are important. One of the trickiest things about using ActiveRecord in Ruby is the different syntax. We can copy examples until we feel comfortable using ActiveRecord on our own.

Image for post
Image for post

When the code in db/migrate is finished and saved, return to CLI (in the project’s main folder) and run

rake db:migrate

Only now is the code from part 1 executed. Hopefully we have a nice message validating our efforts.

// ☆ rake db:migrate
== 1 CreateSongsTable: migrating ===========================================
— create_table(:songs, {})
-> 0.0009s
== 1 CreateSongsTable: migrated (0.0011s) ==================================

If not, follow the error message or paste it into a search engine. Sometimes rake prefers “bundle exec rake db:migrate” instead.

Migration was one of the most difficult things for both me and my computer. If we run into problems, our “undo” button is

rake db:rollback

Type it into CLI, and this undoes the most recent migrations, allowing us to fix things in the db/migrate folder.

We can also add to our tables and modify them without “rake db:rollback.” This is standard practice and easier if the database was created successfully. Follow step 1 again to make another file (or files). This time, we can add another table or do things like rename_table, rename_column, add_column, and change_table. See the examples below.

rename_table

The table “songs” will be renamed “records”

rename_column

In the table “records,” the column “good_song” will be renamed “user_has_starred”

add_column

The table “records” will get a new column named “album,” and the datatype is string

change_table

change_table changes all the columns in a table

Standard practice is to create different files (each with its own class) for each change or addition. If we wanted to make each of the changes above, we would make four files, just like these examples, instead of doing them in one.

After adding files that add or change the tables (or their columns), run “rake db:migrate” again — files that are already migrated are automatically ignored.

Image for post
Image for post

Now we can make our classes! We can put our files in the “lib” folder, in “app/models,” or in the main folder. Standard practice is to have each class in its own file. Following the example above, the “record” class will be in “record.rb,” and an “artist” class would be in “artist.rb.”

Again, notice the naming conventions so our ActiveRecord will run smoothly — the table is “records” (plural and lowercase), so the file name is “record.rb” (singular and lowercase), and the class in the file is “Record,” (singular and capitalized).

The class must be “Record” (singular, capitalized) because the table is “records” (plural, lowercase)

We might have noticed that our migrations in steps 1 and 2 “inherit” (<) from ActiveRecord::Migration[4.2], but this class is not in db/migrate, so it inherits from ActiveRecord::Base instead. Remember, inherit Migration in the migrate folder, and inherit Base outside of that folder, and both start with ActiveRecord::.

Now we tell the tables how they relate to each other. To extend the current theme, below is an example of the relationships of ‘song’ to ‘artist,’ ‘album,’ and ‘manager.’

Image for post
Image for post
An example of has_many, belongs_to, and has_many through:

We use “has_many,” “belongs_to,” and “has_many through:” to tell ActiveRecord how our tables/classes are related. Again, the punctuation and grammar are important. Even has_many :song (singular) or belongs_to :artists (plural) will prevent ActiveRecord from recognizing the associations, and then we can’t use some of the functionality ActiveRecord was designed to give us. It is so smart that we can even link the Manager class to the Album class, as seen in lines 5 and 7 in the top left and bottom right. The name after “through:” should also be plural.

So what do we get for all of that work? We get a ton of useful methods built in!

A list of common and useful methods we can use with ActiveRecord in Ruby. See the table in Google Spreadsheet.

Even while completing this list, I looked back on it for reference many, many times to help me understand ActiveRecord more. These are the most common methods that I have found. See more at rubyonrails.org here.

RAKE

Last, what is rake? We used it for migration (and rollback, if necessary). In ActiveRecord, rake is like IRB (Interactive Ruby Shell). It allows us to run code in Ruby, get immediate feedback, AND it includes our database and the methods we’ve written (and the ones we inherited from ActiveRecord::Base). In CLI in the program’s main folder, type “rake console” to get started like IRB, or “rake -T” to get a list of all the commands we can use.

In conclusion, the benefits of ActiveRecord definitely outweigh the learning curve. Taking the steps in the right order, using correct syntax, observing convention, and avoiding potentially problematic code can help us get the most out of ActiveRecord. Happy coding!

NOTES & POTENTIAL PROBLEMS

  1. A joiner table is required if you have a many-to-many relationship so that you only have one-to-many relationships. Here, if we wanted to show that one song can be on multiple albums, we would use a joiner table/class. That joiner table would be named “songs_albums” (or albums_songs, just pluralize both and be consistent), the class would be “SongAlbum” (both singular), and the has_many and through: would only accept “song_albums” (with only the last word pluralized).
  2. Pluralization in ActiveRecord uses a complex method that understands regular and irregular English words. Use plural and singular nouns as you would in academic English — child/children, sheep/sheep, etc.
  3. If we create files (especially files outside of those for our migration and classes), it could break our migration and stop us from running anything without an error. For example, a seed file (to put information in the program through Ruby instead of in the database) could be run by ActiveRecord before the tables/migration. This results in a large, non-descriptive error. The culprit: the program tried to add to a table before the table existed. Be sure any new files are in the correct folders.
  4. Try calling instance variables with self.variable (like “self.id”) rather than @variable (like “@id”). A few of my problems have been fixed by using self. instead of @.

Written by

Full Stack Web Developer, former English as a foreign language teacher and volleyball coach. All views and opinions are my own.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store