eigenclass logo
MAIN  Index  Search  Changes  PageRank  Login

FastRI 0.1.1: not only faster, also smarter than ri (the Ruby documentation browser)

FastRI is a much improved ri (the standard tool for browsing core/stdlib/third party Ruby documentation):

  • a lot faster --- don't you hate hearing your HD moan for several seconds with plain old ri?
  • better support for RI documentation in RubyGems packages
  • more intelligent: configurable search strategies (case-independent, "nested exact", partial matches, etc)
  • DRb-enabled: serve RI documentation to other machines in your LAN (uses a Rinda Ring to autodiscover services)

FastRI is faster than ri (read here to see what makes it so fast), and as of 0.1.1 it's also much smarter, as it's got a configurable search strategy that includes "nested exact", partial, "nested partial", as well as case-insensitive modes.


You can get FastRI here or install it via RubyGems

 gem install fastri

Comparing to ri

RubyGems support

Compare this:

$ ri -T ActiveRecord::Base#toggle
 More than one method matched your request. You can refine
 your search by asking for information on one of:
      ActiveRecord::Base#toggle, ActiveRecord::Base#toggle!,
      ActiveRecord::Base#toggle, ActiveRecord::Base#toggle!,
      ActiveRecord::Base#toggle, ActiveRecord::Base#toggle!,

to this:

$ fri Base#toggle
---------------------------------------------- ActiveRecord::Base#toggle
     Turns an attribute that's currently true into false and vice 
     versa. Returns self.


fri is much faster than ri; here are some times measured with a cold cache:

$ time fri -f plain Array#fetch
------------------------------------------------------------ Array#fetch
     array.fetch(index)                    -> obj                       
real    0m0.287s  (real    0m0.127s with a hot cache)
user    0m0.048s
sys     0m0.008s

Compare to:

$ time ri -T -f plain Array#fetch
------------------------------------------------------------ Array#fetch
real    0m10.136s (real    ~ 1.5s with a hot cache)
user    0m1.140s
sys     0m0.464s

Search strategies

"Nested exact"

This illustrates FastRI's ability to locate classes deep in the class hierarchy:

$ fri Base
------------------------------------------------------ Multiple choices:

     ActionMailer::Base, ActionView::Base, ActionWebService::API::Base, 
     ActionWebService::Base, ActionWebService::Client::Base, 
     ActiveRecord::Base, MapReduce::ActiveRecord::Base, 
     RSS::Maker::Base, Scruffy::Components::Base, 
     Scruffy::Formatters::Base, Scruffy::Layers::Base, 
     Scruffy::Renderers::Base, Scruffy::Themes::Base
$ fri Themes::Base
------------------------------------------- Class: Scruffy::Themes::Base
     Author: Brasten Sager


$ ri Themes::Base      .... several seconds later ...
Nothing known about Themes::Base
Case-independent, partial matches
$ fri string.ca
------------------------------------------------------ Multiple choices:

     String#capitalize, String#capitalize!, String#casecmp

That's not all, if you're really lazy, you can use case-independent, partial matching over nested namespaces!

$ fri base.rend
------------------------------------------------------ Multiple choices:

     ActionView::Base#render, Scruffy::Components::Base#render, 
     Scruffy::Layers::Base#render, Scruffy::Renderers::Base#render

Summary of changes in 0.1.1 since 0.1.0


  • the search strategy can be specified with --order
  • added case-insensitive search strategies
  • --show-matches returns a list of matching entries
  • default output format defaults to 'plain' on win32


  • the home directory is detected correctly on win32
  • no more SecurityErrors due to calls to #require after $SAFE=1
  • index creation doesn't bomb when RubyGems is not installed
  • executables are added the .rb extension when installing on win32 with setup.rb

umm.. how do we use it again? - titan (2006-11-11 (Sat) 06:57:48)

titaniums:~$ ri fastri
Nothing known about fastri
titaniums:~$ ri fri 
Nothing known about fri
titaniums:~$ man fri
No manual entry for fri
titaniums:~$ fri Array#size
Couldn't initialize DRb and locate the Ring server.

Please make sure that:
 * the fastri-server is running, the server is bound to the correct interface,
   and the ACL setup allows connections from this host
 * fri is using the correct interface for incoming DRb requests:
   either set the FASTRI_ADDR environment variable, or use --bind ADDR, e.g
      export FASTRI_ADDR=""
      fri Array

mfp 2006-11-11 (Sat) 09:30:51

You have to run


first. It will index all your RI docs the first time you run it, and then block (daemon mode is under development). Then you can try

 fri Array#size

which will connect to the server. Both fastri-server and fri bind by default to

jadams 2006-11-13 (Mon) 11:47:34

'ri Array' works.

'fri Array#size' works.

'fri Array' bugs out.


(druby:// /usr/lib/ruby/1.8/rdoc/ri/ri_descriptions.rb:99:in `concat': can't convert nil into Array (TypeError)

       from (druby:// /usr/lib/ruby/1.8/rdoc/ri/ri_descriptions.rb:99:in `merge_in'
       from (druby:// /usr/lib/ruby/gems/1.8/gems/fastri- `get_class'
       from (druby:// /usr/lib/ruby/gems/1.8/gems/fastri- `get_class'
       from (druby:// /usr/lib/ruby/gems/1.8/gems/fastri- `info'
       from (druby:// /usr/lib/ruby/gems/1.8/gems/fastri- `capture_stdout'
       from (druby:// /usr/lib/ruby/gems/1.8/gems/fastri- `info'
       from (druby:// /usr/lib/ruby/1.8/drb/drb.rb:1552:in `perform_without_block'
       from (druby:// /usr/lib/ruby/1.8/drb/drb.rb:1512:in `perform'
        ... 7 levels...
       from (druby:// /usr/lib/ruby/gems/1.8/gems/fastri-
       from (druby:// /usr/bin/fastri-server:18
       from /usr/lib/ruby/gems/1.8/gems/fastri-
       from /usr/bin/fri:18

mfp 2006-11-13 (Mon) 12:09:44

You're not using ruby 1.8.5, right? It's a bug in rdoc/ri pre-1.8.5 which was solved in June. You can fix it either by applying this patch or by adding this to fastri-server:

module ::RI
  class ModuleDescription
    remove_method :merge_in
    # merge in another class desscription into this one
    def merge_in(old)
      merge(@class_methods, old.class_methods)
      merge(@instance_methods, old.instance_methods)
      merge(@attributes, old.attributes)
      merge(@constants, old.constants)
      merge(@includes, old.includes)
      if @comment.nil? || @comment.empty?
        @comment = old.comment
        unless old.comment.nil? or old.comment.empty? then
          @comment << SM::Flow::RULE.new
          @comment.concat old.comment

The next release will most probably include this workaround.

Last modified:2006/11/10 03:35:25
Keyword(s):[blog] [ruby] [frontpage] [fastri] [0.1.1] [release] [ri]