The buzz cut

Ramblings from the barbershop

Upgrading From Rails 3.2 to Rails 4.0

| Comments

Tonight, I upgraded my first Rails 3.2 app to Rails 4.0. It wasn’t too hard, but I did hit some bumps along the way. Hopefully this post will help others better navigate those bump.

The first thing I did was upgrade to Ruby 2.0. If you’re going to throw, throw heat.

1
2
3
rvm get stable
rvm install 2.0.0-p0
rvm use 2.0.0-p0

Then it was time to install Rails 4

1
gem install rails -v 4.0.0.beta1

I fully plan on creating a new gemset for this project moving forward, but I did this within the existing gemset.

Before updating Rails in my Gemfile, I added the rails4_upgrade gem so that I could do a dependency check. More on that in a second

1
2
# Gemfile
gem 'rails4_upgrade'

After running bundle, I was then able to run a new rake task

1
bundle exec rake rails4:check_gems

In my case, this was a relatively new app that wasn’t using a ton of gems. I only had a handful that conflicted with Rails 4.

1
2
3
4
5
6
7
8
9
+--------------------+--------------------+
| Dependency Path    | Rails Requirement  |
+--------------------+--------------------+
| coffee-rails 3.2.2 | railties ~> 3.2.0  |
| devise 2.2.3       | railties ~> 3.1    |
| sass-rails 3.2.6   | railties ~> 3.2.0  |
| simple_form 2.0.4  | actionpack ~> 3.0  |
| simple_form 2.0.4  | activemodel ~> 3.0 |
+--------------------+--------------------+

Coffee & Sass were easy enough, I just updated my Gemfile to point to the Rails 4 versions:

1
2
gem 'sass-rails',   '~> 4.0.0.beta1'
gem 'coffee-rails', '~> 4.0.0.beta1'

I then swapped out my version of devise with the rails4 branch:

1
gem 'devise', :git => 'git://github.com/plataformatec/devise.git', :branch => "rails4"

I did the same thing with simple_form:

1
gem 'simple_form', :git => 'git://github.com/plataformatec/simple_form.git'

Because of the upgrades, I also had to update re-run the rake installs

1
2
rails generate simple_form:install --bootstrap
rails generate devise:install

At that point, I was ready to change my Gemfile to use Rails 4. I knew that I wanted to start with a more forgiving environment, so I also added gems for all of the things that Rails 4 removed.

1
2
3
4
5
6
7
8
9
10
11
12
# Gemfile
gem 'rails', '~>4.0.0.beta1'

gem 'protected_attributes'
gem 'activeresource', github: 'rails/activeresource'
gem 'actionpack-action_caching', github: 'rails/actionpack-action_caching'
gem 'actionpack-page_caching', github: 'rails/actionpack-page_caching'
gem 'activerecord-session_store'
gem 'rails-observers'
gem 'actionview-encoded_mail_to'
gem 'rails-perftest'
gem 'actionpack-xml_parser', github: 'rails/actionpack-xml_parser'

I ran a bundle install, and everything bundled up properly.

For whatever reason, I then thought I’d try running the check_gems rake task again, but rake crapped out on me:

1
2
3
4
5
6
7
8
9
10
bundle exec rake rails4:check_gems
rake aborted!
cannot load such file -- active_resource/railtie
/Users/adam/src/sandbox/screencast/config/application.rb:7:in `require'
/Users/adam/src/sandbox/screencast/config/application.rb:7:in `'
/Users/adam/src/sandbox/screencast/Rakefile:5:in `require'
/Users/adam/src/sandbox/screencast/Rakefile:5:in `'
/Users/adam/.rvm/gems/ruby-2.0.0-p0@rails4/bin/ruby_noexec_wrapper:14:in `eval'
/Users/adam/.rvm/gems/ruby-2.0.0-p0@rails4/bin/ruby_noexec_wrapper:14:in `'
(See full trace by running task with --trace)

Honestly, this is where things get a little blurry, but I believe what solved this first problem was a manual patch to engine.rb in the railties-4.0.0.beta1 gem. For RVM users you can do the following to find the source location for that gem:

1
gem contents railties

The manual change I made was based on this gist, which I found from this issue. Long story short, I made that change, ran my rake command again, and got a new error. I wasn’t out of the woods completely, but I’d made progress. The new error looked like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
bundle exec rake rails4:check_gems
rake aborted!
uninitialized constant Rails::SubTestTask
/Users/adam/.rvm/gems/ruby-2.0.0-p0@rails4/gems/rails-perftest-0.0.1/lib/rails/perftest/railties/testing.tasks:2:in `block in '
/Users/adam/.rvm/gems/ruby-2.0.0-p0@rails4/gems/rails-perftest-0.0.1/lib/rails/perftest/railties/testing.tasks:1:in `'
/Users/adam/.rvm/gems/ruby-2.0.0-p0@rails4/gems/rails-perftest-0.0.1/lib/rails/perftest/railtie.rb:8:in `block in '
/Users/adam/.rvm/gems/ruby-2.0.0-p0@rails4/gems/railties-4.0.0.beta1/lib/rails/railtie.rb:201:in `instance_exec'
/Users/adam/.rvm/gems/ruby-2.0.0-p0@rails4/gems/railties-4.0.0.beta1/lib/rails/railtie.rb:201:in `block in run_tasks_blocks'
/Users/adam/.rvm/gems/ruby-2.0.0-p0@rails4/gems/railties-4.0.0.beta1/lib/rails/railtie.rb:201:in `each'
/Users/adam/.rvm/gems/ruby-2.0.0-p0@rails4/gems/railties-4.0.0.beta1/lib/rails/railtie.rb:201:in `run_tasks_blocks'
/Users/adam/.rvm/gems/ruby-2.0.0-p0@rails4/gems/railties-4.0.0.beta1/lib/rails/application.rb:241:in `block in run_tasks_blocks'
/Users/adam/.rvm/gems/ruby-2.0.0-p0@rails4/gems/railties-4.0.0.beta1/lib/rails/engine/railties.rb:17:in `each'
/Users/adam/.rvm/gems/ruby-2.0.0-p0@rails4/gems/railties-4.0.0.beta1/lib/rails/engine/railties.rb:17:in `each'
/Users/adam/.rvm/gems/ruby-2.0.0-p0@rails4/gems/railties-4.0.0.beta1/lib/rails/application.rb:241:in `run_tasks_blocks'
/Users/adam/.rvm/gems/ruby-2.0.0-p0@rails4/gems/railties-4.0.0.beta1/lib/rails/engine.rb:445:in `load_tasks'
/Users/adam/.rvm/gems/ruby-2.0.0-p0@rails4/gems/railties-4.0.0.beta1/lib/rails/railtie/configurable.rb:30:in `method_missing'
/Users/adam/src/sandbox/screencast/Rakefile:7:in `'
/Users/adam/.rvm/gems/ruby-2.0.0-p0@rails4/bin/ruby_noexec_wrapper:14:in `eval'
/Users/adam/.rvm/gems/ruby-2.0.0-p0@rails4/bin/ruby_noexec_wrapper:14:in `'
(See full trace by running task with --trace)

At that point, I decided to hold off on fixing rake, and move on to seeing if I could run rails s. The result was better than expected, but still not clean.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
rails s
=> Booting WEBrick
=> Rails 4.0.0.beta1 application starting in development
=> Call with -d to detach
=> Ctrl-C to shutdown server
DEPRECATION WARNING: config.whiny_nils option is deprecated and no longer works. (called from block in  at /Users/adam/src/sandbox/screencast/config/environments/development.rb:10)
config.eager_load is set to nil. Please update your config/environments/*.rb files accordingly:

  * development - set it to false
  * test - set it to false (unless you use a tool that preloads your test environment)
  * production - set it to true

DEPRECATION WARNING: The Active Record auto explain feature has been removed.

To disable this message remove the `active_record.auto_explain_threshold_in_seconds`
option from the `config/environments/*.rb` config file.

I did some research, then ultimately made a handful of changes to development.rb, production.rb, test.rb, and application.rb. I found that creating a fresh Rails 4 app, then comparing each of those files from the new app to those on my existing app, was really helpful. I’m not going to include the exact changes I made to those files because I don’t want to lead anyone down the wrong path, but the most import changes were: removing whiny_nils configs, adding eager_loading configs, and removing the active_record.auto_explain_threshold_in_seconds config. I also started with a new application.rb based on the fresh rails4 app, then added back my non-standard configs to that.

I then tried the rake command again, and sure enough, it worked. The change to application.rb had fixed that problem.

At this point, ‘rails s’ and ‘rake’ were both working and the app was running fine. This is great progress, but I still hadn’t fully converted my app to Rails 4 code. I’ll cover that progress in a series of followup posts. The first step was using binstubs.

Comments