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
, typebinding.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.