Fixing Ruby pry/readline under Ubuntu

Disclaimer: I don’t know why this error occurred on my office installation of Ubuntu 10.04 but this is what I did to solve it.

After installing pry (with a RVM ruby version) and wanting to run it I got the following error block:


mallibone@troulwd0062:~$ pry
/home/users/mallibone/.rvm/gems/ruby-1.9.3-p125@global/gems/pry-0.9.8.2/lib/pry.rb:11: warning: already initialized constant DEFAULT_HOOKS
/home/users/mallibone/.rvm/gems/ruby-1.9.3-p125@global/gems/pry-0.9.8.2/lib/pry.rb:22: warning: already initialized constant DEFAULT_PRINT
/home/users/mallibone/.rvm/gems/ruby-1.9.3-p125@global/gems/pry-0.9.8.2/lib/pry.rb:47: warning: already initialized constant SIMPLE_PRINT
/home/users/mallibone/.rvm/gems/ruby-1.9.3-p125@global/gems/pry-0.9.8.2/lib/pry.rb:56: warning: already initialized constant CLIPPED_PRINT
/home/users/mallibone/.rvm/gems/ruby-1.9.3-p125@global/gems/pry-0.9.8.2/lib/pry.rb:61: warning: already initialized constant DEFAULT_EXCEPTION_HANDLER
/home/users/mallibone/.rvm/gems/ruby-1.9.3-p125@global/gems/pry-0.9.8.2/lib/pry.rb:67: warning: already initialized constant DEFAULT_EXCEPTION_WHITELIST
/home/users/mallibone/.rvm/gems/ruby-1.9.3-p125@global/gems/pry-0.9.8.2/lib/pry.rb:70: warning: already initialized constant DEFAULT_PROMPT
/home/users/mallibone/.rvm/gems/ruby-1.9.3-p125@global/gems/pry-0.9.8.2/lib/pry.rb:81: warning: already initialized constant SIMPLE_PROMPT
/home/users/mallibone/.rvm/gems/ruby-1.9.3-p125@global/gems/pry-0.9.8.2/lib/pry.rb:83: warning: already initialized constant SHELL_PROMPT
/home/users/mallibone/.rvm/gems/ruby-1.9.3-p125@global/gems/pry-0.9.8.2/lib/pry.rb:90: warning: already initialized constant NAV_PROMPT
/home/users/mallibone/.rvm/gems/ruby-1.9.3-p125@global/gems/pry-0.9.8.2/lib/pry.rb:106: warning: already initialized constant DEFAULT_CONTROL_D_HANDLER
/home/users/mallibone/.rvm/gems/ruby-1.9.3-p125@global/gems/pry-0.9.8.2/lib/pry.rb:120: warning: already initialized constant DEFAULT_SYSTEM
/home/users/mallibone/.rvm/rubies/ruby-1.9.3-p125/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require': cannot load such file -- readline (LoadError)
        from /home/users/mallibone/.rvm/rubies/ruby-1.9.3-p125/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
        from /home/users/mallibone/.rvm/gems/ruby-1.9.3-p125@global/gems/pry-0.9.8.2/lib/pry.rb:163:in `'
        from /home/users/mallibone/.rvm/rubies/ruby-1.9.3-p125/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
        from /home/users/mallibone/.rvm/rubies/ruby-1.9.3-p125/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
        from /home/users/mallibone/.rvm/gems/ruby-1.9.3-p125@global/gems/pry-0.9.8.2/bin/pry:12:in `rescue in '
        from /home/users/mallibone/.rvm/gems/ruby-1.9.3-p125@global/gems/pry-0.9.8.2/bin/pry:8:in `'
        from /home/users/mallibone/.rvm/gems/ruby-1.9.3-p125/bin/pry:19:in `load'
        from /home/users/mallibone/.rvm/gems/ruby-1.9.3-p125/bin/pry:19:in `'

Now the line that shows us the error is this one:


/home/users/mallibone/.rvm/rubies/ruby-1.9.3-p125/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require': cannot load such file -- readline (LoadError)

So we have a readline error. No need to click onto that link and go off reading just keep in mind that this library does the following:

The GNU Readline library provides a set of functions for use by applications that allow users to edit command lines as they are typed in.

But back to the original problem, how do we get it running? Well in your Ruby installation there is a extconf.rb file which according to the read-me: The Readline module provides interface for GNU Readline.. So what we have to do now is update our installation i.e. update this wrapper module. I’m using RVM so I found the file under the path[1]:

/home/users/mallibone/.rvm/src/ruby-1.9.3-p125/ext/readline

To update our wrapper cd into your readline directory and run the following commands:


ruby extconf.rb
make
sudo make install

The typing pry into the shell resulted in the rewarding response:

[1] pry(main)>

Update

Under Ubuntu 11.10 you have to further install libreadline library to get pry and AFAIK the rails console. One way to do this is by the following lines (again using RVM):


rvm uninstall 1.9.3-p125
sudo apt-get install libreadline-dev
rvm install 1.9.3-p125 --with-readline-dir=/usr/include/readline

Thank you megas for pointing out this issue under Ubuntu 11.10 and providing a good explanation and solution to the problem.

Resources:

Readline LoadError Solution
GNU Readline

[1] If you don’t know where or what kind of installation you have type cd / into your command line and then

find . -name "extconf.rb"

This should show you where your extconf.rb file is but may take a while looking for it.

Run all your tests with rake

When writing automated tests one of the things you will always want to do is execute them. When using RSpec the only thing you have to do is type rspec into your console and of they go. All your tests i.e. specs get executed. Now you might have already heard about rake a.k.a. Ruby make. Within rake there is a test task that can be used to execute tests in the RSpec style described before with only a few lines of Ruby.

So lets started, open your Rakefile[1] and add the following lines of code, I’m using MiniTest::Spec for some of my projects but I’ll explain in a bit how you can modify the task to suit your needs.

  
    require 'rake/testtask'

    Rake::TestTask.new do |t|
      t.libs = ["lib"]
      t.warning = true
      t.verbose = true
      t.test_files = FileList['spec/*_spec.rb']
    end
  

This lets us run all spec files that are in the spec directory and the filenames end with _spec.rb by typing rake test into the console.

If your using another test library e.g. TestUnit you can change the seventh line to t.test_files = FileList['test/*_test.rb'], which will run all your tests analog to the spec command but in another directory i.e. with a different filename ending.

Now what are all the other configurations for? Well lets go through them one by one.

  • libs: In the example case loads the lib directory into as default environment, this allows you to use require 'my_class' in your unit tests instead of having to use relative paths e.g. require_relative '../lib/myclass'.
  • waring: This runs your tests with the warning flag enabled i.e. ruby -w, this shows you possible problems and we don’t want to give other people potential problems do we?
  • verbose: Verbose output e.g. files used in test

It’s up to you which flags you want to enable and disable the one argument you should provide is test_files.

Separating slow tests

Now not every test you write may be a unit test and those tests that aren’t have the tendency to run slower then a unit test, which leads to favoring separation of unit tests and for example integration tests.

I like to add an additional directory for my integration tests within the spec directory. Which then looks something like this:

  
    |-spec
       |---integration
  

Our original rake task will not work with this structure i.e. it will just ignore the specs we store under spec/integration. Further we would actually like to run our unit tests and integration tests separately. So lets add a new task for our integration tests.

  
    #previous code omitted

    Rake::TestTask.new do |t|
      t.libs = ["lib", "spec"]
      t.name = "test:integration"
      t.warning = true
      t.test_files = FileList['spec/integration/*_spec.rb']
    end
  

If we now type rake test:integration into the console all our integration tests will be run. Note that by adding the spec folder you can require 'spec_helper.rb' in the integration tests.

Naming a test task allows you to choose between them, but there is a more convenient way of naming a test task. Let me show you by adding a further task that will execute all our specs/tests in the spec directory including sub folders.

  
    #previous code omitted

    #integration test code omitted

    Rake::TestTask.new("test:all") do |t|
      t.libs = ["lib", "spec"]
      t.warning = true
      t.test_files = FileList['spec/**/*_spec.rb']
    end
  

With rake test:all we can now run all our tests in one go. And if we decide to add another category of tests they will also be run with this approach.

References

Rake:TestTask
Ruby Inside MiniTest::Spec

Further reading rake

A good point to get some more rake skills is the Rake Tutorial by Jason Seifer or the Official Rake Tutorial.

—-

[1] If not present just create a file named Rakefile and continue on reading.

Getting started with RSpec in Rails 3.2

Installing RSpec with Rails is pretty straight forward. The only task left since Bundler is to add RSpec to the Gemfile. And there is more good news, there is a special RSpec gem for Rails which has some handy shortcuts ready for you, I’ll be showing you some of those in future blog entries.

Quickest way is to append the gem to the Gemfile using the Console or Terminal just execute the following command in your project root directory(1):


echo "gem "rspec-rails", :group => [:test, :development]" >> Gemfile

Once you appended the RSpec gem install the gem via bundler i.e. bundle install.

We now got a new Rails generator commands:


Rspec:
  rspec:install

So lets install RSpec for our Rails project by running the following command rails g rspec:install

This will setup the RSpec environment in your Rails directory. Now we are ready to start cranking out RSpec tested code.

You may have noticed that we did not only add the gem to the test group but additionally to the development. You may ask yourself why? Well by adding it to the development group we get some more RSpec goodness. If you now use e.g.:


rails g model Something some_name some_description
      invoke  active_record

      create    db/migrate/20120207071500_create_somethings.rb
      create    app/models/something.rb
      invoke    rspec
      create      spec/models/something_spec.rb

Your Rails generator will automatically generate you the RSpec spec file. Let the BDD begin..

Sources:

RSpec book
Railscasts
Tekpub Rails 3 intro


(1)Or just simply open the Gemfile in the editor of choice and add the line: gem "rspec-rails", :group => [:test, :development]