Categories
Rails

Ruby and Ruby on Rails version compatibility

I have recently been planning upgrades for an application which runs on both an old version of Ruby on Rails and an old version of Ruby.

The recommended upgrade path for rails is to upgrade through each version, rather than try and jump several versions in one go.  I.e 3.2 to 4.0 to 4.1 to 4.2 to 5.0 to 5.1 to 5.2. At each stage, a compatible version of Ruby will need to be used.

Finding which versions of Ruby are compatible with each rails version is quite hard, and while some rails release notes have recommended or minimum Ruby versions listed, there doesn’t seem to be a list of supported versions.

Googling reveals only old answers.

So I decided to see which versions of Ruby the rails project was testing against for each branch, on the basis that you wouldn’t test something if you weren’t going to try to support it. (UDPATE: Verified by David Heinemeier-Hansson)

From 9th April 2019, Buildkite was used for testing, so this information can be found in the rails.gemspec file in the rails source.

Versions of ruby specified by rails.gemspec, by -stable branch, excluding ruby-head:

Rails 6.0

  • >= 2.5.0

Rails 5.2

  • >= 2.2.2

Rails 5.1

  • >= 2.2.2

Rails 5.0

  • >= 2.2.2

Rails 4.2

  • >= 1.9.3

Rails 4.1

  • >= 1.9.3

Rails 4.0

  • >= 1.9.3

Rails 3.2

  • >= 1.8.7

Rails 3.1

  • >= 1.8.7

Rails 3.0

  • >= 1.8.7

Prior to 9th April 2019, travis-ci was used for testing, so this information can be found in the .travis.yml file in the rails source. Note that the .travis.yml file was removed from the rails source, so you’ll need to view the source prior to this commit.

Versions of ruby that were specified by .travis.yml, by -stable branch, excluding ruby-head:

Rails 3.0

  • 1.8.7
  • 1.9.2
  • 1.9.3

Rails 3.1

  • 1.8.7
  • 1.9.2
  • 1.9.3

Rails 3.2

  • 1.8.7
  • 1.9.2
  • 1.9.3
  • 2.0.0
  • 2.1.8
  • 2.2.6
  • 2.3.3

Rails 4.0

  • 1.9.3
  • 2.0.0
  • 2.1
  • 2.2

Rails 4.1

  • 1.9.3
  • 2.0.0
  • 2.1
  • 2.2.4
  • 2.3.0

Rails 4.2

  • 1.9.3
  • 2.0.0-p648
  • 2.1.10
  • 2.2.10
  • 2.3.8
  • 2.4.5

Rails 5.0

  • 2.2.10
  • 2.3.8
  • 2.4.5

Rails 5.1

  • 2.2.10
  • 2.3.7
  • 2.4.4
  • 2.5.1

Rails 5.2

  • 2.2.10
  • 2.3.7
  • 2.4.4
  • 2.5.1

Rails 6.0

  • 2.5.3
  • 2.6.0
Correct as of 3rd January 2020.
Categories
Rails

The problem with renaming a model in Rails

So you’ve decided to rename a model in Rails. What could be simpler than renaming and editing a bunch of files? You make your edits in development, run migrations and so on.
There’s a potential issue you might hit though. Suppose you have model Foo, which you want to modify (e.g. add a column). So you create a migration with:
add_column :foo, :quantity, :integer
…and you run your migration.
Then you decide you want to rename the model to Bar. So you use rename_table in your migration, and rename and edit the appropriate files. All works beautifully.
Now you come to deploy, and it all goes wrong when you migrate the database, saying it can’t find the model. The reason? Well your first migration now refers to a model that doesn’t exist, because the new model file is in place.
The messy solution is to perform the migration yourself, by renaming the database table directly in the database.
The clean solution is to avoid making changes like this in the first place. I guess it’s an example of where “deploy often” can reap benefits.

Categories
Rails

Renaming a model in Rails

When renaming a model in Rails (2.3), there are a range of files you may need to change:

Create a migration to rename the database table:

(rename_table :oldname, :newname)

Rename the model.
Edit any associations in other models.
Rename the controller (if required)
Modify routes.rb
Modify any links in views.
Rename views.
Rename the model in controllers and views.
Rename and modify any tests.

Moral of the story – name your models correctly from the start. Keep them as generic as possible. This post came about because I initially had a model for appointments for training sessions, so the model TrainingSession was created. Then I needed to store appointments which were for a different type of session, but I kept the model name the same, as it was only seen internally, and used a named scope. Now I need to store appointments of any type, so having code referring to TrainingSession will still work, but it makes it counterintuitive to refer to generic appointments as TrainingSession.generic. Instead, Appointment.generic and Appointment.training are so much more logical.