When I pair with people I reach for binding.pry a whole lot sooner than they do. I also stay in there longer. Here's some of the stuff I've found valuable in a binding.pry session that keeps me there instead of in my editor.

rescue pry

Ever have some code the runs a lot and throws an exception some of the time? And that exception only happens after many, many runs and you aren't sure what condition causes it? Something like this (but much less contrived):

1000.times do |n|
  sometimes_throw_an_exception(n)
end

If you're suspicious of a particular value you can use a conditional.

1000.times do |n|
  binding.pry if n == 500
  sometimes_throw_an_exception(n)
end

But that depends on you having a suspcious value for n. Ruby should be able to pause execution itself when it finds a suspicious value for n.

1000.times do |n|
  sometimes_throw_an_exception(n) rescue binding.pry 
end

Now the method will run until it throws an exception. Then it will pry. Be careful not to leave any of these in your code though - it's easy to forget about them once they stop prying.

show-method

Okay, so if you read through the last example you know that sometimes_throw_an_exception always throws an exception when it recieves n as an argument. Time to go back to the code, right? Nope, the code is still fully accessible in pry.

show-method sometimes_throw_an_exception

Just run show-method against the method. Note that it's the actual method, not the method's name as a symbol.

ls and cd

Hey, it's something familiar. I know these shell commands! Did you know pry has them too? And that they do roughly what you'd expect? (Assuming you expect methods to look like files and objects to look like directories full of files...)

Stick a pry in your favorite object. Go ahead, I'll wait.

...

Ok, now type ls. You should see all the methods on your object and all its instance vars. You'll probably also see class methods and inherited methods. Oh and constants too.

This can be overwhelming, especially in an active record object. The good news is you can actually filter what you'd like to see. According to ls --help, ls has the following options (among others):

    -m, --methods               Show public methods defined on the Object
    -M, --instance-methods      Show public methods defined in a Module or Class
    -l, --locals                Show hash of local vars, sorted by descending size
    -c, --constants             Show constants, highlighting classes (in blue), and exceptions (in purple).
    -i, --ivars                 Show instance variables (in blue) and class variables (in bright blue)

There's also -G/--grep which only shows methods and variables matching a regex.

So that's ls. How about cd?

Admittedly, I don't use cd as often as ls. As a shell's cd lets you change the current working directory, pry's cd lets you navigate objects. Then when you run ls, you'll see the contents of the object you just cd'ed into.

Oh and cd .. jumps back out of an object as you'd expect.

You can try it out easily enough:

$ cd []
$ ls

Enumerable#methods: 
  all?   collect_concat  each_entry       each_with_object  find      group_by  interpose  max      min     minmax_by  original_grep  slice_before  to_set       
  any?   detect          each_slice       entries           find_all  index_by  lazy       max_by   min_by  none?      partition      sort_by       to_table     
  chunk  each_cons       each_with_index  exclude?          flat_map  inject    many?      member?  minmax  one?       reduce         sum           to_text_table
JSON::Ext::Generator::GeneratorMethods::Array#methods: to_json_without_active_support_encoder
Resourceful::Serialize::Array#methods: serialize  to_serializable
Array#methods: 
  &        clear        each              grep          paginate              reverse!            slice!          to_json_with_active_support_encoder
  *        collect      each_index        hash          permutation           reverse_each        sort            to_liquid                          
  +        collect!     empty?            in_groups     place                 rindex              sort!           to_param                           
  -        combination  eql?              in_groups_of  pop                   rotate              sort_by!        to_query                           
  <<       compact      extract_options!  include?      prepend               rotate!             split           to_s                               
  <=>      compact!     fetch             index         pretty_print          sample              take            to_sentence                        
  ==       concat       fifth             insert        pretty_print_cycle    second              take_while      to_xml                             
  []       count        fill              inspect       product               select              third           transpose                          
  []=      cycle        find_index        join          push                  select!             to              uniq                               
  abbrev   dclone       first             keep_if       rassoc                shelljoin           to_a            uniq!                              
  append   deep_dup     flatten           last          reject                shift               to_ary          unshift                            
  as_json  delete       flatten!          length        reject!               shuffle             to_csv          values_at                          
  assoc    delete_at    forty_two         map           repeated_combination  shuffle!            to_default_s    xss_aware_to_sentence              
  at       delete_if    fourth            map!          repeated_permutation  shuffle_with_seed!  to_formatted_s  zip                                
  blank?   drop         from              options       replace               size                to_h            |                                  
  bsearch  drop_while   frozen?           pack          reverse               slice               to_json       
self.methods: __pry__
locals: _  __  _dir_  _ex_  _file_  _in_  _out_  _pry_

echo -ne \a

What's this gibberish?! That gibberish is part of my pry prompt. Just like you can configure your shell's prompt, you can configure the pry prompt.

Pry's prompt is configured by editing your ~/.pryrc file and setting Pry.config.prompt to a new proc which gets executed each time you run a command. By default it shows the object you're cd'ed into and how deeply nested you are.

Okay, so why is this gibberish in your prompt? That particular bit of gibberish is a shell command that displays a visual bell. The bell bubbles up from my shell, into tmux, to my terminal, and finally to my window manager to tell me that my pry session is waiting for input.

I admit that's not the most useful feature in the world, but it seemed noteworthy that pry has a configurable prompt.

pry-remote

Okay, this isn't really something from my personal toolbox. I actually just used it for the first time 5 minutes ago. I'd been dodging this one because it seemed like it might be complicated or something other useless excuse.

pry-remote is for connecting to a pry session when you don't have access to the console running rails server. That could be a sshed into a stage server or even on developer machine running foreman. Here's how you use it:

  • Instead of binding.pry, type binding.remote_pry.

Okay, the worst of it is over. Stretch those wrists from all that extra typing and get ready for connecting to the remote_pry session.

  • bundle exec pry-remote

Wow. Such effort. I can't believe I ignored this tool for so long. It's never too late to pick up some new tricks though.