Ruby on Rails 4.2 migration

Foreman has been updated from Ruby on Rails 4.1 to 4.2 for Foreman 1.12, so this page provides information for plugin maintainers to help check compatibility.

The most likely problems are:

  • Changes to database migration styles
  • Any deprecation warnings from 3.x that haven't been fixed
  • Any monkey patching or use of internal Rails methods (unlikely in plugins)

To ensure compatibility of a plugin with Foreman running on Rails 4.2, work through it in this order:

  1. Update DB migration styles
  2. Run plugin tests on develop with Rails 4.1, look out for deprecation warnings and fix them
  3. Run plugin tests on Foreman's rails42 branch, fix failures
  4. Optionally fix new deprecation warnings
  5. Consider making a release of the plugin with any fixes

Foreman branch

Foreman's develop branch (after 1.11-stable was branched and released) is now running Rails 4.2 - version 4.2.6 at the time of writing.

Running plugin tests

You can run plugin tests against develop on Jenkins if you wish by running http://ci.theforeman.org/job/test_plugin_matrix/build.

Database migrations

These changes should, and can be safely made for plugins running on develop.

String limits

Rails 4.2 removes the default 255 character limit from PostgreSQL and SQLite string columns, making them unlimited length by default. MySQL remains at 255 characters.

To ensure schemas are identical on both existing and new databases, it's recommended that limits are added to all existing DB migrations that add string columns, like so:

t.column :name, :string, :null => false, :limit => 255

If you want to make the columns larger than 255 characters, add a new migration after doing this - but beware that MySQL can't do this.

Try to make and release this change before Rails 4.2 is used in Foreman. More information on foreman-dev.

Foreign key checks

Any DB migrations that check if a foreign key exists using the foreign_keys('table') method:

if foreign_keys('user_roles').find { |f| f.options[:name] == 'user_roles_user_id_fk' }.present?

... must be changed to use foreign_key_exists? as the foreign_keys method will in future throw an exception on DBs that don't support it. This is changed to:

if foreign_key_exists?('user_roles', :name => 'user_roles_user_id_fk')

This old method will be deprecated for two releases in Foreman as usual. The newer style is compatible with 4.1 (with Foreigner) so can be changed immediately.

Common deprecations

Rails 4.2 deprecates more methods in preparation for Rails 5. These are harmless for plugins, but should be fixed for future compatibility. It'll usually issue deprecation warnings to stderr, so run plugin tests and use the plugin to see these.

  1. All calls to model.exists? and model.find should supply IDs, not AR instances
  2. Routes that use :to with just an action or controller name should be use :action or :controller instead
  3. Nested arrays passed into AR finders must be flattened
  4. _path helpers should be replaced by _url helpers in mailers

Lots more are listed on http://edgeguides.rubyonrails.org/4_2_release_notes.html#railties.

Random test ordering

The rails42 branch has also been changed to enable random test ordering within a single test case. This doesn't change the overall order of test cases.

This might cause problems if there is shared state (e.g. a class-level variable in the test case) between tests, which should be changed to use setup blocks or similar.