Creating Tables and Associations using Ruby/Active Record/Rake

This blog is written to help beginners take their first steps in creating a database using Ruby, Active Record, and Rake. Before all this can happen one needs to create the skeleton of each table and how they will be associated to one another. We will start using the "entity relation" table in https://app.diagrams.net/.

Imagine we are currently building out the backend for a social media music website and want to collect certain data and have access to this data through other pieces of data. Our tables let us visualize this. We see two arrows pointing from the fans' table's unique id and the musicians' table's unique id to the musicianfans' table. A third arrow is seen pointing from the bands' table's unique id to the musicians' table. With this in place we can visualize how we will write our association methods.

In our example the fans table has and arrow signifying that a fan has many musicianfans. But what is the purpose of the musicianfans table? Its purpose is to allow a fan to have many musicians through the table and a musician to have many fans through the table as well, serving as a join table. A join table contains data from two or more other tables. Thus, a many to many relationship is created between the data. Our join table also has data from the musician table, meaning a musician has many musicianfans and has many fans through musicianfans. In our join table, a musicianfan belongs to a fan and to a musician. Looking closer at our musicians' table, we can also deduce that a musician belongs to a band due to it containing a column holding the band_id. Lastly in our bands' table, a band can have many musicians and many fans. These associations will allow us to move throughout our database with ease.

I like to first build out the migration tables. To do this we can use the Rake tasks in Ruby. If you ever want to see a list of the tasks you can perform, use rake -T in your terminal. From there I made three migrations using rake db:create_migration NAME=create_fans. The next three I substituted "fans" for "musicians", "bands" and then "musicianfans". Keep in mind that it is best practice to use the plural form as a name. After each migration is created we then build out our tables. Using our table picture from before is a great reference point to add in our columns. Once everything in our tables have been written we can migrate everything using rake db:migrate. Our empty tables are now created. From here one can start working on their associations.

In this example I created three model files that will inherit Active Record and allow us to create our association methods.
Again using the initial brainstorming picture of the tables will be a good indicator for which Active Record associations we will use for each model. Some things to watch out for. Make sure your has_many associations are plural and belongs_to are singular. They won't work otherwise. Also, make sure your "has_many through" associations are created under the others as they rely on the association that comes before it. In the example above, the order of associations in the Band model matters. "has_many :musicians" needs to come before the "through" association below it or the association won't be read. We now can move on to making our seed data.

Creating a seeds.rb file allows one to visually see how your association methods work in action. In the example various instances of fans, bands, and musicians are created. The fan and band instances are set to variables so we can assign the musician instances' id keys a value pertaining to the unique id of the fan instance and band instance. Once we have our data we use the Rake task rake db:seed. At this point our tables that we have migrated are now populated with our seeds data. We will test this out in a moment. But fist, drawing one's attention to the top of the seeds picture one can see that the ".destroy_all" and ".reset_pk_sequence" method are being called on each class. What this does is it allows us to mess around with the seeds data, updating and deleting instances, without having to worry about duplicate data or ids changing when we re-seed. Great for trying things out in the beginning. This is thanks to a gemfile. Install gem install activerecord-reset-pk-sequence -v 0.2.0 in the terminal and then add gem 'activerecord-reset-pk-sequence' to your gemfile. Make sure the gem is pasted at the bottom as the the order matters here as well.

Now is the moment of truth. We want to test out to see if all our association methods are working.

In the above picture we are testing to see if our Band's model's associations are working. To get into the console use the task rake console. From here we can see that calling the .all method on the class of Band shows us all of our band instances within an array. Moving downward I create a variable "band" to signify just one band. In this case it's the first band instance within the array. Creating this variable provides us a cleaner way to move throughout the process. Let's test our first Band association, has_many musicians. As we can see it works! Moving down when the "fans" instance method is called on our band variable we see all the associated fans.

Always remember that these associations are instance methods! musicians, fans, bands, band, musicianfans, and fan are all instance methods that we call upon... instances!

Let's test our other associations! In the pictures below I do something very similar to the previous test. I am looking through my model associations and testing them on an individual instance of that particular model.

Testing Fan
Image description

Testing Musician
Image description

With everything we have gone over in place, we now have a good platform to begin other endeavours such as creating custom Ruby/Active Record methods or your own API!

56