One9 - Upgrade to Ruby 1.9 Now
So ruby 1.9.2 is the future and your still stuck on 1.8 at work. Why? It’s a pain … Well, let’s change that. Introducing one9 – a gem to find 1.9 method changes and make the upgrade process smoother.
Install
No surprises here.
gem install one9
Well almost. If you’re using bundler (the default in rails3), add one9 to your Gemfile if your
tests are invoked by bundler i.e. one9 test, one9 test rake * or one9 test bundle exec *.
How it works
one9 runs your 1.8 test suite, spies on methods that have changed and saves the locations of their calls
for later viewing. If you have a supported editor, it drops into an editor to let you sequentially
view and possibly fix each change. Although one9 gives you a brief message for each change, I
recommend familiarizing yourself with 1.9 changes. To see what one9 knows about 1.9 changes:
$ one9 changes +-----------------------------------+------------------------------------------------------------------+--------+ | method | message | type | +-----------------------------------+------------------------------------------------------------------+--------+ | Module#constants | Returns array of symbols instead of array of strings | change | | Module#public_methods | Returns array of symbols instead of array of strings | change | | Module#instance_methods | Returns array of symbols instead of array of strings | change | | Module#singleton_methods | Returns array of symbols instead of array of strings | change | | Module#public_instance_methods | Returns array of symbols instead of array of strings | change | | Module#protected_methods | Returns array of symbols instead of array of strings | change | ...
Run tests
First off, run your tests in the root directory of a gem or Rails app:
# Runs `rake test` by default $ one9 test # To run any other test command, just prefix it with one9 test: # Run all cucumber specs $ one9 test cucumber # Only run model specs $ one9 test rspec spec/models
After your tests run, one9 prints a report. Here’s what it all looks like for boson:
$ one9 test ............................................................................................... ............................................................................................... ............................................................................................... ............... Finished in 0.704555 seconds. 300 tests, 580 assertions, 0 failures, 0 errors ** One9 Report ** +---------------------------------+-------+--------------------------------------------------------------+--------+--------------------------------------------------------------+ | method | count | message | type | lines | +---------------------------------+-------+--------------------------------------------------------------+--------+--------------------------------------------------------------+ | Module#instance_methods | 5 | Returns array of symbols instead of array of strings | change | lib/boson/util.rb:39:in `detect',lib/boson/util.rb:40:in ... | | Module#private_instance_methods | 2 | Returns array of symbols instead of array of strings | change | lib/boson/inspectors/argument_inspector.rb:23:in `scrape_... | | Hash#to_s | 4 | An alias of #inspect instead of a spaceless join of the e... | change | lib/boson/loader.rb:87:in `initialize_library_module',lib... | | Hash#select | 4 | Returns a hash instead of an association array | change | lib/boson/loader.rb:109:in `set_library_commands',lib/bos... | +---------------------------------+-------+--------------------------------------------------------------+--------+--------------------------------------------------------------+ 4 rows in set
As you can see the report lists changed methods, how many times they were
called and where they were called from. To reprint this list any time later, run one9 list
.
Note: When you run one9 test
it overwrites the previous one test
result.
Edit Changes
Now that you have a list of changed method calls, editing those changes is easy:
# Open all changes $ one9 edit # To only open a subset of changes: # Only open Hash changes $ one9 edit Hash # Only open Hash#to_s changes $ one9 edit Hash#to_s
Currently this opens the quickfix list in vim. (For vim noobs, navigate between changes with :cn
and :cp
.) Patches for emacs and other editors welcome :)
Remember each change is a possible change. Only change the code if the new 1.9 behavior is going
to break the existing code.
For those without editing support, you can still view each line where there’s a method change:
$ one9 lines +---------------------------------+---------------------------------------------------------------------+ | method | line | +---------------------------------+---------------------------------------------------------------------+ | Module#instance_methods | lib/boson/util.rb:39:in `detect' | | Module#instance_methods | lib/boson/util.rb:40:in `detect' | | Module#instance_methods | lib/boson/loader.rb:101:in `check_for_method_conflicts' | | Module#instance_methods | lib/boson/util.rb:44:in `detect' | | Module#instance_methods | lib/boson/namespace.rb:28:in `boson_commands' | ...
Once you’ve fixed your changes, give your code a 1.9 test run. If tests are still broken, then jump
down to this section.
Rails Tips
Skip this section if you’re not on a Rails app.
So you’ve finished editing your code and tests pass. You’re done, right? Not in my opinion. My code
is only as good as the code it depends on. I’d check each of my app’s dependencies and check for any
1.9 breakages. For each gem:
1. cd to the gem: cd `bundle show $GEM`
2. Install the gem’s development dependencies: gem install $GEM --dev
3. Run tests with one9: one9 test WITH PROPER COMMAND
4. Edit gem’s changes : one9 edit
5. Verify tests pass on 1.9.
6. Fork, patch, pull as needed
Configure
one9 comes with a decent list of 1.9 changes and descriptions. If you’d like to add your
own changes, add them to your ~/.one9rc. For example:
# For methods that have changed in 1.9 change 'Class#instance_method', 'Some description' # For methods that have been deleted in 1.9 delete 'Class.class_method', 'Some description'
For more examples, see the defaults that one9 defines. If I’ve missed an important 1.9 change, feel free to fork and pull.
Additional 1.9 Changes
So even if you’ve dealt with all changed methods, there are still other changes that could effect your code:
- Encoding: Probably the most significant and thus well documented. See JEG’s thorough articles
- scoping of block variables, splat operator and block arguments
- files in
$LOAD_PATH
and$LOADED_FEATURES
are expanded - using colon (:) instead of “then” in an if/unless/case is deprecated
- retry in a loop or iterator is deprecated
$KCODE
,$=
andVERSION*
constants are deprecated?x
now returns a single character string instead of an integer- For anything I may have missed see the official changelog or the unoffical one
Motivation
This gem aims to get the ruby community to seriously use 1.9.2 and to port as many of the 1.8 gems
to 1.9. Since this gem maintains a list of 1.9 changes, it could be used as a multi-purpose tool.
Some ideas for future commands:
- grep command to grep code for changed methods. Basically for porting test-deprived code.
- info command to explain a method’s change in detail with examples and possible solutions
- rails command to ease porting a rails app and all its dependencies.
- automating code changes like python’s 2to3
If you’re interested in implementing these or other such commands, please do contribute.
Conclusion
Ruby 1.9.2 isn’t the future, it’s already here. So why are you waiting?