CNK's Blog

Upgrading to Rails 4.2.0

Upgrading Rails Versions: 4.1.8 to 4.2.0

After a lot of interruptions for other work, last week I finally finished recreating my CMS app in Rails 4 - just in time for the release of Rails 4.2! Most of the information I have been reading about 4.2 has focused on new features, adequate record, foreign keys, active job, etc. So I was not really prepared for a number of issues that came up as a result of changes and depreciations. On my first pass, 871 of my 1419 tests failed! So guess I had better take some notes as I go along.

To get started, I changed the Rails version in my Gemfile from 4.1.8 to 4.2.0 and ran bundle upgrade rails and then ran my rspec test suite (rspec-rails 3.1.0 with rspec-core 3.1.2). As I said, a TON of tests failed, including the vast majority of my controller tests.

SSL Requirement

All (or nearly all) of the controller test failures pointed to my SSL-requirement gem. I need to go back and diagnose that - but since I can’t easily actually run SSL on my dev server right now, I commented out the gem in my Gemfile and include lines in my application controller:

    diff --git a/Gemfile b/Gemfile
    -gem 'bartt-ssl_requirement', :require => 'ssl_requirement'
    +# gem 'bartt-ssl_requirement', :require => 'ssl_requirement'

    diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb

    -  include ::SslRequirement
    -  ssl_allowed :all
    +  # include ::SslRequirement
    +  # ssl_allowed :all

Deprecation Warnings

New Configuration Options

Each time I run my tests, I was getting a couple of deprecation warnings, one about renaming a configuration option serve_static_assets to serve_static_files and one about suppressing errors raised within after_rollback and after_commit callbacks. The first one was fairly easy to deal with. I just searched my config directory and changed the option name in my test.rb and production.rb files. It isn’t set in development.rb so I continued to leave it out.

For the second warning, I tried adding an option in each of my 3 environments files - setting the option to true for dev and test but keeping the old exception suppression by setting this to false in my production.rb file.

    # Don't suppress errors in after_rollback and after_commit callbacks
    config.active_record.raise_in_transactional_callbacks = true

Unfortunately, setting those options did not fully suppress the deprecation warnings. I am still getting them for all 4 of the models I have that use paperclip (my documents model and all 3 of my image type models). Before reporting an issue, I thought I would try upgrading to the latest version of paperclip. Running bundle update paperclip upgraded me from paperclip 4.2.0 to 4.2.1 and cocaine 0.5.4 to 0.5.5. And that did remove the remaining ‘raise_in_transactional_callbacks’ warnings when I run my tests!!!

Truthiness

One of my tests had several instances of the following warning:

    DEPRECATION WARNING: You attempted to assign a value which is not
    explicitly `true` or `false` to a boolean column. Currently this value
    casts to `false`. This will change to match Ruby's semantics, and will
    cast to `true` in Rails 5. If you would like to maintain the current
    behavior, you should explicitly handle the values you would like cast
    to `false`.

All of these were coming from sections of the test where I was doing a create or update with invalid parameters. I had not given much thought to those params but assigned a nonsense value to one of my boolean columns:

    let(:invalid_attributes) { {:campus_only => 'banana'} }

The model in question is not super picky, so it is a little difficult to find parameters that would invalidate the model. For my create actions, sending in an empty file attribute would invalidate the model object. But for an update, an empty file would be perfectly legitimate since one can update other attributes without uploading a new file. But, since I am mocking out the save action to return false in my ‘update with invalid params’ tests, it is good enough.

Page Versions

When running the pages controller spec, I got a bunch of warnings about serialized_attributes. I suspect those are coming from my versioning system, paper_trail. But I noticed that there is also a new version of the tree plugin I use, closure tree. Looking at the changelog, I didn’t see anything that looked like it would make any difference but decided to upgrade anyway so as to keep up; this took me from closure_tree 5.0.0 to 5.2.0.

Upgrading paper_trail from 3.0.5 to 3.0.6 did not make any difference in the serialized_attributes warnings:

    DEPRECATION WARNING: `serialized_attributes` is deprecated without
    replacement, and will be removed in Rails 5.0. (called from block in
    update at /data1/srv/rails/empcms4/app/controllers/pages_controller.rb:62)

Looking at the issue queue, I guess I should have known about this for quite a while: https://github.com/airblade/paper_trail/issues/416 There doesn’t seem to be any consensus about a solution. For now I think I’ll ignore it - even though it means my page controller and versions controller specs are kind of noisy.

Errors

Changes to assert_select

Almost all of my request specs and a bunch of my view specs are failing with messages like:

    NotImplementedError:
       Implementing document_root_element makes assert_select work
       without needing to specify an element to select from.

Mass Upgrade of Gems

Fiddling with a few gem updates didn’t seem to be making any difference to this, so I decided to move my Gemfile.lock to Gemfile.lock.bak (for reference) and let bundler install the latest compatible versions of things. This made the following updates:

    acts_as_list           0.4.0        0.6.0
    aws-sdk                1.55.0       1.60.2
    columnize              0.8.9        0.9.0
    execjs                 2.2.1        2.2.2
    factory_girl_rails     4.4.0        4.5.0
    factory_girl           4.4.0        4.5.0
    jquery-rails           3.1.2        4.0.2
    jquery-ui-rails        5.0.0        5.0.3
    libv8                  3.16.14.5    3.16.14.7
    mini_magick            3.8.1        4.0.1
    mini_portile           0.6.0        0.6.1
    mysql2                 0.3.16       0.3.17
    nokogiri               1.6.3.1      1.6.5
    quiet_assets           1.0.3        1.1.0       (dev and test only)
    rspec-core             3.1.2        3.1.7
    rspec-expectations     3.1.0        3.1.2
    rspec-mocks            3.1.0        3.1.3
    rspec-support          3.1.0        3.1.2
    safe_yaml              1.0.3        1.0.4
    sass-rails             4.0.3        4.0.5
    sass                   3.2.0        3.2.2
    spring                 1.1.3        1.2.0
    sprockets              2.11.0       2.12.3
    uglifier               2.5.3        2.6.0
    webmock                1.18.0       1.20.4

I also commented out coffee-rails because I am not using coffeescript; this removed the coffee-rails, coffee-script-source, and subexec gems.

This upgrade took care of most of the errors I was seeing in my view specs. The few remaining problems pointed out actual errors - mostly some form tags that had been copied over from the rails 2.3 version of this project. I also had an error in the user mailer - again due to misuse of url_for to get an https url. I fixed those and now all of my model, mailer, routing, controller, helper, and view tests pass. So now it is just my request specs that are dorked:

    $ rspec spec/requests
    Finished in 11.54 seconds (files took 4.56 seconds to load)
    146 examples, 123 failures, 3 pending

Defining document_root_element

All the remaining errors still refer to document_root_element not being implemented. Grepping through the gems in my Rails 4.2 gemset, most references come from a new gem, rails-dom-testing. The README for the gem shows an example of using document_root_element - and refers us to the API docs in selector_assertions.rb. But even after reading that, I am somewhat unclear about what to do.

More poking around - by searching on github - turned up 2 pull requests: https://github.com/rails/rails/pull/17107 and https://github.com/rails/rails-dom-testing/pull/20 Again, very confusing but suggesting the need to add an alias to html_document - temporarily?

I looked at the other places where I found document_root_element in my rails 4.2 gemset. All 3 were places where a method by that name was defined, one each in actionpack-4.2.0/lib/action_controller/test_case.rb, actionpack-4.2.0/lib/action_dispatch/testing/integration.rb, and actionview-4.2.0/lib/action_view/test_case.rb. Two out of 3 of those defined it as:

    def document_root_element
      html_document.root
    end

So I tried dropping that into one of my test files and that caused the tests in that file to pass.

To include this in all my request specs, I created a module and included it only in my request specs:

    # spec/support/assert_select_root.rb

    module AssertSelectRoot
      def document_root_element
        html_document.root
      end
    end

    RSpec.configure do |config|
        config.include AssertSelectRoot, :type => :request
    end

With that addition, almost all of my request specs passed. I had a couple of places (in request specs and in my view specs) where I needed to change my html entities to the characters they evaluate to - as warned about in the release notes: http://edgeguides.rubyonrails.org/4_2_release_notes.html#assert-select After taking care of those issues, all my tests pass again!

Other

I still haven’t figured out the SSL requirement errors. But that is for another post.

After that, I may still want to look into rest of the release notes to see if there is anything else I should examine: And I should read through the upgrade guide to see what else I might want to deal with. There is also an intro to Rails 4.2 video

  • though I suspect that will be about the new features and not about some of the refactoring or internal changes.