Inheritance on-the-fly with Ruby on Rails

Tech - RubyCademy
RubyCademy
Published in
3 min readFeb 7, 2019

--

Today, I’d like to try a new format of blogpost.

Indeed, the goal here is to break down a well known piece of Ruby code that we encounter everyday.

Today we’re going to talk about the way that Ruby on Rails ensure the compatibility of your migrations when you upgrade Ruby on Rails.

All the magic is done within the ActiveRecord::Migration class.

So, let’s get the party started!

Case Study

We use Ruby on Rails 5.2.x.

Let’s generate a Product model from the terminal

?> bin/rails generate model Product name:string description:text

Among all the generated files, this command will generate a migration class

Here a CreateProducts class is generated.

At first glance, this class seems to inherit from anything but a class.

But, in Ruby, a class can only inherits from a class.

So, what happens here?

Class.new(super)

As we’ve seen in the short guide to learning how Classes work in Ruby article, a class is an instance of the class Class.

So, our CreateProducts class could be defined as following — without using the class..end syntactic sugar

Normally, the Class.new method expects a class as parameter that will be set as superclass of the returned instance of Class.

So, as expressions passed as arguments to methods are always evaluated before the method call itself, then ActiveRecord::Migration[5.2] is evaluated and its return value — which is a class — is passed as argument of the Class.new method call.

So what’s theActiveRecord::Migration[5.2] return value?

ActiveRecord::Migration.[](version)

This statement is a shortcut to the ActiveRecord::Migration.[](version) class method call.

This method is in charge of returning the version of the ActiveRecord::Migration class that corresponds to the version of Ruby on Rails passed as argument — Ruby on Rails 5.2.x in our case.

Let’s see what’s the returned class in this case

Here we see that ActiveRecord::Migration[5.2] returns a class named as ActiveRecord::Migration::Current and that this class inherits from ActiveRecord::Migration.

This class contains a set of changes related to the current version of Rails— 5.2 in our case.

Also, this class derivates from ActiveRecord::Migration. So it shares all its properties.

Note that a call to ActiveRecord::Migration[5.1] returns the ActiveRecord::Migration::Compatibility::V5_1 class which derivates from ActiveRecord::Migration::Current.

From 5.2 to 6.0

So, let’s suppose that we want to upgrade our app to Ruby on Rails 6.0.

To ensure the compatibility of our migrations, all our migration are version to ActiveRecord::Migration[5.2].

If so, all our migration should generate the same database schema without any effort.

Let’s see what the Ruby on Rails Team does about migration when they release a new version of Ruby on Rails:

1- The ActiveRecord::Migration::Current is now returned by a call to ActiveRecord::Migration[6.0] — and not [5.2] anymore.

2- An ActiveRecord::Migration::Compatibility ::V5_2 class is created and all the specialisations of the old ActiveRecord::Migration::Current are moved within this class.

3- new changes that correspond to the Ruby on Rails 6.0 release are implemented within the ActiveRecord::Migration::Current class.

4-ActiveRecord::Migration[5.2] returns— in Ruby on Rails 6.0 — to ActiveRecord::Migration::Compatibility::V5_2.

So this mechanism ensures that the same database schema is generated when a Ruby on Rails application is upgraded to a newer version of Ruby on Rails.

Conclusion

The ActiveRecord::Migration — which is the superclass of any migration class — is versioned to avoid regression and side effects during database migration.

In effect, as the ActiveRecord::Migration library +/- differs between each major or minor version of Ruby on Rails, then the generated schema can also slightly differ between each of these versions.

Concretely, if an app in Ruby on Rails 5.2 is upgraded to Ruby on Rails 6.0, then, when migrations are played, the generated schema can slightly differ between these versions and some undesired side effects can occur accordingly.

So, Ruby on Rails decided to version the ActiveRecord::Migration to address this issue.

Ruby Mastery

We’re currently finalizing our first online course: Ruby Mastery.

Join the list for an exclusive release alert! 🔔

🔗 Ruby Mastery by RubyCademy

Also, you can follow us on x.com as we’re very active on this platform. Indeed, we post elaborate code examples every day.

💚

--

--