irb & script/console tips

Posted by Dan Croak

Dec 23

Let’s get interactive. You can learn a lot about your application from irb & by extension, script/console.

Wirble: colors

Color matters. You’re picky about your text editor syntax highlighting and maybe you use the excellent redgreen gem for colors in your test backtraces. Gotta have it in irb, too.

First, install Wirble:

sudo gem install wirble

Then, in your ~/.irbrc:

1
2
3
4
require 'rubygems'
require 'wirble'
Wirble.init
Wirble.colorize

Wirble: history

Wirble has an added bonus: history.

1
2
3
irb(main):001:0> history = "History?"
=> "History?"
irb(main):002:0> exit

Without Wirble, if you drop back into irb, you can’t arrow up to your previous commands. With Wirble, you can.

Wirble: auto-completion

As if that’s not enough, Wirble gives you auto-completion, too. In irb:

1
2
>> un_momento = "Spanish for like, 'hold the phone!'"
=> "Spanish for like, 'hold the phone!'"

Type, “un”, then tab:

1
2
>> un
un_momento   undef        unless       untaint      untrace_var  until

Local methods

Stick this in your ~/.irbrc:

1
2
3
4
5
6
# Easily print methods local to an object's class
class Object
  def local_methods
    (methods - Object.instance_methods).sort
  end
end

Use the #local_methods method like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
>> class BasketballPlayer
>>   attr_accessor :name
>> 
?>   def champion?
>>     name == "Kevin Garnett"
>>   end
>> end
=> nil
>> kevin_garnett = BasketballPlayer.new
=> #<BasketballPlayer:0x11988f8>
>> kevin_garnett.name = "Kevin Garnett"
=> "Kevin Garnett"
>> kevin_garnett.champion?
=> true
>> kevin_garnett.local_methods
=> ["champion?", "name", "name="]

Aliases

Don’t forget you can alias in irb. The only one I have is:


alias q exit

It makes irb feel more Vim-ish.

Create test fixtures for a third party service

Your app uses the Flickr API. You want your test suite to use legitimate data but not hit the service.

Given the actual call to the service is:


FlickrClient.search("Bruce Springsteen")

Run the query in script/console and convert the data into yaml:


yaml = FlickrClient.search("Bruce Springsteen").to_yaml

Then use your old Ruby friend, File.open with the write option (“w”) to dump it to a file:


File.open("test/fixtures/flickr/springsteen.yml", "w") { |file| file << yaml }

Add this to your test_helper.rb:

1
2
3
4
def load_yaml_fixture(path)
  absolute_path = File.join(RAILS_ROOT, "test", "fixtures", path)
  YAML::load_file absolute_path
end

Voila, when you need to mock out calls to the third party service, you can now use this in your test code:


load_yaml_fixture("springsteen.yml")

This pattern is repeatable for any third party service. Just replace the actual call with whatever you’re working on, and name the fixture something intention-revealing.

Print SQL to standard out

Oftentimes script/console is used for debugging, and what better way to do that than to get the SQL generated by each method call. Stick this in your ~/.irbrc:
1
2
3
4
5
# Log to STDOUT if in Rails
 if ENV.include?('RAILS_ENV') && !Object.const_defined?('RAILS_DEFAULT_LOGGER')
   require 'logger'
   RAILS_DEFAULT_LOGGER = Logger.new(STDOUT)
 end

This gets you:

1
2
3
>> videos = Video.limited(3)
  Video Load (0.4ms)   SELECT * FROM `videos` LIMIT 3
=> [#<Video id: 1, ...>]

Without the ~/.irbrc love, you’d be missing:

Video Load (0.4ms)   SELECT * FROM `videos` LIMIT 3

pp

After you’ve required rubygems for Wirble, require pretty print, too:


require 'pp'

This is just a nice way to have better formatting at your fingertips. It’s especially helpful when dealing with an Array of ActiveRecord objects:

1
2
3
4
>> pp videos
[#<Video id: 1, youtube_id: "TcMklv40YMY", name: "Merb, Rubinius and the Engine Yard Stack", upload_time: nil, view_count: 6171, description: "Google Tech Talks\nOctober 20, 2008\n\nABSTRACT\n\nIn th...", created_at: "2008-12-21 00:32:33", updated_at: "2008-12-21 00:32:33">,
 #<Video id: 2, youtube_id: "JySmT-dGOj0", name: "MERB SPORTS Team-Vorstellung 2008", upload_time: nil, view_count: 495, description: "MERB SPORTS stellt sich für die VDRM-Saison 2008 v...", created_at: "2008-12-21 00:32:33", updated_at: "2008-12-21 00:32:33">,
 #<Video id: 3, youtube_id: "6bc-FNNWIsM", name: "Merb && Moi", upload_time: nil, view_count: 58, description: "Amusing yes?", created_at: "2008-12-21 00:32:33", updated_at: "2008-12-21 00:32:33">]

Comments on this post

Ryan

Dec 23

Ryan said,

Awesome. I’ve been using pp and my own local_methods for a while, but never knew about wirble. Awesome.

Dan Pickett

Dec 23

Dan Pickett said,

Christmas comes a bit early for me! Thanks, Dan tons of useful tricks in here.

josh

Dec 23

josh said,

cool, this is great. bookmarking this for use later today.

Jim Lindley

Dec 23

Jim Lindley said,

Great writeup! In addition to most of the above, I stick

require 'rubygems'

And

load File.dirname(FILE) + '/.railsrc' if $0 == 'irb' && ENV['RAILS_ENV']

in ~/.irbrc

The first makes it quicker to load a gem, and the second conditionally includes Rails-specific IRB helpers, which for me consists of this prompt modification: http://gist.github.com/39408

(Culled from here http://ozmm.org/posts/railsrc.html and here http://quotedprintable.com/2007/9/13/my-irbrc )

Ben Atkin

Dec 23

Ben Atkin said,

Even just having require ‘rubygems’ in my .irbrc will save me time and frustration! I can’t count the number of times I’ve typed require ‘<lib>’ in a new irb session and it didn’t work because I forgot to type require ‘rubygems’.

Brian

Dec 23

Brian said,

Great tips, Dan.

The list of methods for Rails Model objects can get so long that you need more than sorting to help find the methods you’re looking for. Like, weren’t there some AR methods that expose SQL syntax for models? Use Array#grep to narrow that list of 390 methods:

User.local_methods.grep /sql/ => [“construct_calculation_sql”, “count_by_sql”, “find_by_sql”, “paginate_by_sql”, “sanitize_sql”, “sanitize_sql_array”, “sanitize_sql_for_assignment”, “sanitize_sql_for_conditions”, “sanitize_sql_hash”, “sanitize_sql_hash_for_assignment”, “sanitize_sql_hash_for_conditions”, “sqlite3_connection”, “sqlite_connection”]

Keep the tips coming, guys!

Avdi

Dec 23

Avdi said,

Don’t forget UtilityBelt: http://utilitybelt.rubyforge.org/

Chris

Dec 23

Chris said,

Fast-typing, fat-fingered Rubyists shouldn’t forget GuessMethod either: http://guessmethod.rubyforge.org/

DIogo Lisboa

Dec 23

DIogo Lisboa said,

Knew all of this already, but any tech writeup with basketball references gets points with me.

Szymek

Dec 23

Szymek said,

It’s also quite useful to have indentation in irb: IRB.conf[:AUTO_INDENT]=true

and with what_methods gem you can do something like this: >> “ActiveRecord::Base”.what? “active_record/base” “ActiveRecord::Base”.underscore == “active_record/base” => [“underscore”]

Thierry

Dec 23

Thierry said,

Very interesting read. As a vim user, I’d also recommend soma (http://trueaffection.net/post/55082660/we-aint-got-slime-but-we-got-something)

Soma helps you send stuff from vim to irb

Kieran

Dec 23

Kieran said,

Brilliant tips/tools! This will speed up things!

Stephen Celis

Dec 23

Stephen Celis said,

Nice tips in general. Wirble is a must for those of us used to syntax highlighting, although I don’t think auto-complete or history are Wirble features. I assume they’re just requiring “irb/completion” and “irb/ext/save-history”.

As far as `Object#local_methods` goes, you can also access a class’s local instance methods by using `instance_methods(false)`. The boolean determines whether or not to include `super` (default: `true`). Your `local_methods` doesn’t appear to account for multiple levels of inheritance.

Josh

Dec 23

Josh said,

Its nice that you can call irb from within irb

irb Customer.new self #<customer> first_name => “Josh”

Henrik N

Dec 23

Henrik N said,

Something I find pretty useful is to have the script/console irb prompt show the app root and env: http://gist.github.com/39503

So it might be e.g. “mysite.com[dev]>>”.

Jerry Cheung

Dec 23

Jerry Cheung said,

Thanks for the tips! I think my favorite tip out of the list is learning of the existence of .irbrc I finally have a good place to put this snippet of code:

def mate(content, filename='debug.txt') File.open(filename, 'w') { |f| f.write(content) } `mate #{filename}` end

I use it for skimming over to_xml results and saving output from calls.

Jerry Cheung

Dec 23

Jerry Cheung said,

Sorry, the formatting got screwed up:

def mate(content, filename='debug.txt')
  File.open(filename, 'w') { |f| f.write(content) }
  `mate #{filename}`
end
Mark Wilden

Dec 23

Mark Wilden said,

Wirble has local_methods built-in. Just type ‘po an-object’. ‘poc a-class’ prints the class’s constants.

Arthur Klepchukov

Dec 23

Arthur Klepchukov said,

@Jerry Cheung

Thanks! I improved it a bit to clean up the files it opens:
  def mate(content, filename='debug.txt', cleanup=true)
    File.open(filename, 'w') { |f| f.write(content) }
    `mate -w #{filename}` # waits for Textmate to close file
    `rm -rf ./#{filename}` if cleanup
  end
Stephen Celis

Dec 23

Stephen Celis said,

@Jerry, @Arthur; this is built into the gem utilitybelt, I believe, using the “tempfile” library.

Rich Thornett

Dec 23

Rich Thornett said,

Nice post – great to have all of these documented in one place. One more that I like is the ability to “become” an object via “irb [object]”, such that self is the object specified. For example, you can access instance variables and call private methods


# Access instance variables private methods
>> u = User.find_by_login('test_tosterone')
>> irb u # Become user object
>> @secret
=> nil
>> reveal_secret # Private method
>> @secret
=> "eek, naked object!" 

or execute migration methods from the console, e.g. to fix a half-completed migration if you’re using mysql :(


# Migrations from the console
>> irb ActiveRecord::Schema
>> remove_column :users, :status
>> remove_index :users, :email
Akhil Bansal

Dec 25

Akhil Bansal said,

Great tips, thanks for sharing .

Giles Bowkett

Dec 28

Giles Bowkett said,

Thanks Avdi! If you do gem install utility_belt you get pretty much all of this automatically, plus vi integration. You can be in irb, go into vi, code up anything you want, and on exit irb will eval it. You can do the same with emacs or TextMate also. You also get programmatic control of the clipboard, googling stuff, pastie – I wrote it before git existed – and a bunch of other crap I don’t even remember.

Giles Bowkett

Dec 28

Giles Bowkett said,

Wow, that was a stupid comment. I wrote it before gitHUB existed, I meant to say – and therefore also before gist.


Sorry, comments are closed for this article.

© 2000 - 2009 by thoughtbot, inc.
written by a bushel of tiny robots