Hirb - Irb On The Good Stuff
Irb is a great place for interacting with Ruby. Unfortunately, even with the colorful help of wirble, it’s not so great for visualizing the output of those interactions. Hirb aims to change that.
Hirb provides a mini view framework for console applications, designed with irb in mind. Given the output of a console application, it applies a view if there is one to apply, based on the output’s class. To get a better idea of what that means, let’s look at Hirb’s included table view and its use with Rails:
bash>script/console Loading local environment (Rails 2.2.2) # Load hirb and enable view framework irb>> require 'hirb' => true irb>> Hirb::View.enable => nil # This is the default config which maps output classes to their views. irb>> Hirb::View.formatter_config => {"ActiveRecord::Base"=>{:class=>"Hirb::Views::ActiveRecord_Base", :ancestor=>true}} # Tag is an ActiveRecord::Base descendant which inherits ActiveRecord::Base's view. irb>> Tag.last +-----+-------------------------+-------------+---------------+-----------+-----------+-------+ | id | created_at | description | name | namespace | predicate | value | +-----+-------------------------+-------------+---------------+-----------+-----------+-------+ | 907 | 2009-03-06 21:10:41 UTC | | gem:tags=yaml | gem | tags | yaml | +-----+-------------------------+-------------+---------------+-----------+-----------+-------+ 1 row in set =>true irb>> 'this remains' =>'this' irb>> :the_same =>:the_same
Note no configuration was needed for Tag
since Hirb is preconfigured to associate ActiveRecord::Base
descendants with a table view. Also notice that the above string and symbol resorted to irb’s default echo mode. This happens whenever an output class has no configuration in Hirb::View.formatter_config
.
Hirb not only detects objects with configured output classes but also arrays of these objects:
irb>> Tag.all :limit=>3, :order=>"id DESC" +-----+-------------------------+-------------+-------------------+-----------+-----------+----------+ | id | created_at | description | name | namespace | predicate | value | +-----+-------------------------+-------------+-------------------+-----------+-----------+----------+ | 907 | 2009-03-06 21:10:41 UTC | | gem:tags=yaml | gem | tags | yaml | | 906 | 2009-03-06 08:47:04 UTC | | gem:tags=nomonkey | gem | tags | nomonkey | | 905 | 2009-03-04 00:30:10 UTC | | article:tags=ruby | article | tags | ruby | +-----+-------------------------+-------------+-------------------+-----------+-----------+----------+ 3 rows in set =>true
Views For Everyone
Although Hirb’s views were built to enhance irb’s echo mode, you can use them as methods:
#These examples don't need to have Hirb::View enabled. irb>>Hirb::View.disable =>nil # Import table() and view(). irb>> extend Hirb::Console => main # Url is an ActiveRecord::Base descendant. irb>> urls = Url.all :limit=>2, :order=>'id DESC'; table urls +------+------------------------+------------------------+------------------------+------------------------+ | id | created_at | description | name | updated_at | +------+------------------------+------------------------+------------------------+------------------------+ | 1548 | 2009-03-12 17:53:27... | blogger that mainta... | http://www.datawran... | 2009-03-12 18:11:48... | | 1544 | 2009-03-12 07:06:19... | | http://rubylearning... | 2009-03-12 07:06:19... | +------+------------------------+------------------------+------------------------+------------------------+ 2 rows in set =>true # Produces same table as above. irb>> view urls, :class=>Hirb::Helpers::ActiveRecordTable
You may have noticed that most of the fields were truncated with an ellipsis. This is because those fields exceeded their allowed widths and had to be truncated. Allowed widths? Of course. Hirb’s table view auto adjusts widths depending on the number of columns and has options to customize per table:
# Instead of seeing all of Url's columns, let's only see certain fields. irb>> table urls, :fields=>[:id, :name, :description] +------+-----------------------------------------------+-----------------------------------------------+ | id | name | description | +------+-----------------------------------------------+-----------------------------------------------+ | 1548 | http://www.datawrangling.com/some-datasets... | blogger that maintains a large collection ... | | 1544 | http://rubylearning.com/blog/2009/03/12/50... | | +------+-----------------------------------------------+-----------------------------------------------+ 2 rows in set =>true # Let's vary the table width and one of the headers. irb>> table urls, :max_width=>70, :fields=>[:id, :name, :description], :headers=>{:name=>"Url"} +------+-----------------------------------+-----------------------------------+ | id | Url | description | +------+-----------------------------------+-----------------------------------+ | 1548 | http://www.datawrangling.com/s... | blogger that maintains a large... | | 1544 | http://rubylearning.com/blog/2... | | +------+-----------------------------------+-----------------------------------+ 2 rows in set =>true # Fields don't have to be a database table's column. They can be any object method. irb>> table urls, :fields=>[:id, :name, :tag_list] +------+------------------------------------------------------------+-----------------------------------+ | id | name | tag_list | +------+------------------------------------------------------------+-----------------------------------+ | 1548 | http://www.datawrangling.com/some-datasets-available-on... | page:tags=data, page:tags=2link | | 1544 | http://rubylearning.com/blog/2009/03/12/50-ruby-related... | page:tags=person, page:tags=2link | +------+------------------------------------------------------------+-----------------------------------+ 2 rows in set => true
In the last example, let me reiterate that any method can be a field. For example, tag_list
is actually a string version of the many tags associated with each url.
Configuration
The variety of options that a view can offer can also be configured per output class. For example, say I want Tag
to have certain fields. I can put this into a configuration block when enabling Hirb:
Hirb::View.enable :output=>{
"Tag"=>{ :options=>{:fields=>%w{id name tag_list}} }
}
Hirb also supports a yaml configuration file (config/hirb.yml or ~/.hirb.yml). The previous configuration block as yaml would be:
--- :output: Tag: :options: :fields: - id - name - tag_list
For another yaml example, see this one I use in my Rails app.
Conclusion
Although this post mainly focused on a use case with a Rails console, I’d like to remind you that Hirb’s views can be applied to any Ruby class and outside of irb. The readme has more examples including creating your own views and using Hirb with standard Ruby objects.
To install Hirb:
gem install hirb
If you have some clever views you’d like to contribute, fork away.