2. Installing Pry
• gem install pry-plus --no-ri --no-rdoc
• Pry-plus contains pry
+ pry-doc (documentation for C methods)
+ pry-debugger (step-through debugger)
+ pry-rescue (opens pry on unhandled exceptions)
+ pry-stack_explorer (call-stack navigation)
+ gist support, bond support, more docs…
3. What’s Pry?
• “like irb, but better”
• Pry is a REPL for Ruby
– (Read-Evaluate-Print Loop)
• An aide for ruby programmers
4. Pry as an aide
• Pry doesn’t solve your problems
• Pry helps you solve your problems
• Lots of simple tools to make your life better
5. Progress
• Introduction
• How do I use the Base64 library?
• Why doesn’t my method work?
• Where did that nil come from?
• What does ordinalize actually do?
• Conclusion
6. How do I use the Base64 library?
$ pry
[1] pry(main)> require „base64‟
=> true
[2] pry(main)> ls Base64
Base64.methods: decode64 encode64
strict_decode64 strict_encode64
urlsafe_decode64 urlsafe_encode64
7. How do I use the Base64 library?
$ pry
[1] pry(main)> require „base64‟
=> true
[2] pry(main)> ls Base64
Base64.methods: decode64 encode64
strict_decode64 strict_encode64
urlsafe_decode64 urlsafe_encode64
8. How do I use the Base64 library?
$ pry
[1] pry(main)> require „base64‟
=> true
[2] pry(main)> ls Base64
Base64.methods: decode64 encode64
strict_decode64 strict_encode64
urlsafe_decode64 urlsafe_encode64
9. How do I use the Base64 library?
$ pry
[1] pry(main)> require „base64‟
=> true
[2] pry(main)> ls Base64
Base64.methods: decode64 encode64
strict_decode64 strict_encode64
urlsafe_decode64 urlsafe_encode64
10. How do I use the Base64 library?
$ pry
[1] pry(main)> require „base64‟
=> true
[2] pry(main)> ls Base64
Base64.methods: decode64 encode64
strict_decode64 strict_encode64
urlsafe_decode64 urlsafe_encode64
11. How do I use the Base64 library?
$ pry
[1] pry(main)> require „base64‟
=> true
[2] pry(main)> ls Base64
Base64.methods: decode64 encode64
strict_decode64 strict_encode64
urlsafe_decode64 urlsafe_encode64
[3] pry(main)>
12. How do I use the Base64 library?
[2] pry(main)> ls Base64
Base64.methods: decode64 encode64
strict_decode64 strict_encode64
urlsafe_decode64 urlsafe_encode64
[3] pry(main)> (“hi”)
=> “aGk=n”
[4] pry(main)> Base64.decode64(_)
=> “hi”
13. How do I use the Base64 library?
[2] pry(main)> ls Base64
Base64.methods: decode64 encode64
strict_decode64 strict_encode64
urlsafe_decode64 urlsafe_encode64
[3] pry(main)> Base64.encode64(“hi”)
=> “aGk=n”
[4] pry(main)> Base64.decode64(_)
=> “hi”
14. How do I use the Base64 library?
[2] pry(main)> ls Base64
Base64.methods: decode64 encode64
strict_decode64 strict_encode64
urlsafe_decode64 urlsafe_encode64
[3] pry(main)> Base64.enc<tab>4(“hi”)
=> “aGk=n”
[4] pry(main)> Base64.decode64(_)
=> “hi”
15. How do I use the Base64 library?
[2] pry(main)> ls Base64
Base64.methods: decode64 encode64
strict_decode64 strict_encode64
urlsafe_decode64 urlsafe_encode64
[3] pry(main)> Base64.encode64(“hi”)
=> “aGk=n”
[4] pry(main)> Base64.decode64(_)
=> “hi”
16. How do I use the Base64 library?
[2] pry(main)> ls Base64
Base64.methods: decode64 encode64
strict_decode64 strict_encode64
urlsafe_decode64 urlsafe_encode64
[3] pry(main)> Base64.encode64 “hi”
=> “aGk=n”
[4] pry(main)> Base64.decode64 _
=> “hi”
17. How do I use the Base64 library?
[2] pry(main)> ls Base64
Base64.methods: decode64 encode64
strict_decode64 strict_encode64
urlsafe_decode64 urlsafe_encode64
[3] pry(main)> Base64.encode64 “hi”
=> “aGk=n”
[4] pry(main)> Base64.decode64 _
=> “hi”
18. How do I use the Base64 library?
[2] pry(main)> ls Base64
Base64.methods: decode64 encode64
strict_decode64 strict_encode64
urlsafe_decode64 urlsafe_encode64
[3] pry(main)> Base64.encode64 “hi”
=> “aGk=n”
[4] pry(main)> Base64.decode64 _
=> “hi”
19. How do I use the Base64 library?
[2] pry(main)> ls Base64
Base64.methods: decode64 encode64
strict_decode64 strict_encode64
urlsafe_decode64 urlsafe_encode64
[3] pry(main)> Base64.encode64 “hi”
=> “aGk=n”
[4] pry(main)> Base64.decode64 _
=> “hi”
20. How do I use the Base64 library?
[2] pry(main)> ls Base64
Base64.methods: decode64 encode64
strict_decode64 strict_encode64
urlsafe_decode64 urlsafe_encode64
[5] pry(main)>
21. How do I use the Base64 library?
[2] pry(main)> ls Base64
Base64.methods: decode64 encode64
strict_decode64 strict_encode64
urlsafe_decode64 urlsafe_encode64
[5] pry(main)> ? Base64.strict_encode64
22. How do I use the Base64 library?
[5] pry(main)> ? Base64.strict_encode64
From: ~/ruby-1.9.3/lib/ruby/base64.rb
Owner: #<Class:Base64>
Visibility: public
Signature: strict_encode64(bin)
Returns the Base64-encoded version of
bin.
This method complies with RFC 4648.
No line feeds are added.
23. How do I use the Base64 library?
[5] pry(main)> ? Base64.encode64
From: ~/ruby-1.9.3/lib/ruby/base64.rb
Owner: #<Class:Base64>
Visibility: public
Signature: encode64(bin)
Returns the Base64-encoded version of
bin.
This method complies with RFC 2045.
Line feeds are added every 60 characters.
24. How do I use the Base64 library?
• Evaluate ruby code.
• Colour
• Tab-completion
• _ (the last output)
• ls (list methods)
• ? (show-doc)
25. Progress
• Introduction
• How do I use the Base64 library?
• Why doesn’t my method work?
• Where did that nil come from?
• What does ordinalize actually do?
• Conclusion
26. Why doesn’t my method work?
• Broken code can be downloaded if you’re
following along
– (n.b. /raw/ is important!)
curl https://gist.github.com/raw/4463940 >
basic_auth.rb
27. Why doesn’t my method work?
[1] pry(main)> cat basic_auth.rb
require „base64‟
module BasicAuth
def self.encode(username, password)
s = [username, password].join(“:”)
“Basic #{Base64.strict_encode64 s}”
end
def self.decode(header)
base64 = header[/Basic (.*)/, 1]
Base64.decode64 base64.split(“:”)
end
end
50. Why doesn’t my method work?
• wtf? (show backtrace, also _ex_.backtrace)
• $ (show-source)
• edit-method (uses $EDITOR)
• <Alt+_>, <esc>_ (copy last word down)
• <ctrl+r> (search history)
• _file_ (last shown file, also _dir_)
• _out_ (array of all output values, also _in_)
51. Progress
• Introduction
• How do I use the Base64 library?
• Why doesn’t my method work?
• Where did that nil come from?
• What does ordinalize actually do?
• Conclusion
52. Where did that nil come from?
• To follow along get the next file
– (the /raw/ is still important)
• curl https://gist.github.com/raw/4464704 >
post.rb
53. Where did that nil come from?
$ ruby post.rb
post.rb:11:in `make_safe': undefined method
`gsub' for nil:NilClass (NoMethodError)
from post.rb:7:in `safe_title'
from post.rb:19:in `<main>‟
$
54. Where did that nil come from?
$ ruby post.rb
post.rb:11:in `make_safe': undefined method
`gsub' for nil:NilClass (NoMethodError)
from post.rb:7:in `safe_title'
from post.rb:19:in `<main>‟
$ subl post.rb
58. Where did that nil come from?
$ subl post.rb
$ ruby post.rb
59. Where did that nil come from?
$ subl post.rb
$ ruby post.rb
From: post.rb @ line 19 :
16: new_post = Post.new(
17: 'title' => 'new post',
18: 'body' => 'your text here')
=> 19: binding.pry # Added for debugging
20: puts new_post.safe_title
[1] pry(main)>
60. Where did that nil come from?
$ subl post.rb
$ ruby post.rb
From: post.rb @ line 19 :
16: new_post = Post.new(
17: 'title' => 'new post',
18: 'body' => 'your text here')
=> 19: binding.pry # Added for debugging
20: puts new_post.safe_title
[1] pry(main)> puts new_post.safe_title
61. Where did that nil come from?
$ subl post.rb
$ ruby post.rb
From: post.rb @ line 19 :
16: new_post = Post.new(
17: 'title' => 'new post',
18: 'body' => 'your text here')
=> 19: binding.pry # Added for debugging
20: puts new_post.safe_title
[1] pry(main)> puts new_post.safe_title
NoMethodError: undefined method `gsub' for nil
62. Where did that nil come from?
[1] pry(main)> puts new_post.safe_title
NoMethodError: undefined method `gsub' for nil
[2] pry(main)>
63. Where did that nil come from?
[1] pry(main)> puts new_post.safe_title
NoMethodError: undefined method `gsub' for nil
[2] pry(main)> cd new_post
64. Where did that nil come from?
[1] pry(main)> puts new_post.safe_title
NoMethodError: undefined method `gsub' for nil
[2] pry(main)> cd new_post
[3] pry(#<Post>):1>
65. Where did that nil come from?
[1] pry(main)> puts new_post.safe_title
NoMethodError: undefined method `gsub' for nil
[2] pry(main)> cd new_post
[3] pry(#<Post>):1> ls
66. Where did that nil come from?
[1] pry(main)> puts new_post.safe_title
NoMethodError: undefined method `gsub' for nil
[2] pry(main)> cd new_post
[3] pry(#<Post>):1> ls
Post#methods: make_safe safe_title
instance variables: @params
locals: _ _dir_ _ex_ _file_ _in_ _out_ _pry_
[4] pry(#<Post>):1>
67. Where did that nil come from?
[1] pry(main)> puts new_post.safe_title
NoMethodError: undefined method `gsub' for nil
[2] pry(main)> cd new_post
[3] pry(#<Post>):1> ls
Post#methods: make_safe safe_title
instance variables: @params
locals: _ _dir_ _ex_ _file_ _in_ _out_ _pry_
[4] pry(#<Post>):1> $ safe_title
68. Where did that nil come from?
[1] pry(main)> puts new_post.safe_title
NoMethodError: undefined method `gsub' for nil
[2] pry(main)> cd new_post
[3] pry(#<Post>):1> ls
Post#methods: make_safe safe_title
instance variables: @params
locals: _ _dir_ _ex_ _file_ _in_ _out_ _pry_
[4] pry(#<Post>):1> $ Post#safe_title
69. Where did that nil come from?
[4] pry(#<Post>):1> $ safe_title
From: post.rb @ line 7:
Number of lines: 3
Owner: Post
Visibility: public
def safe_title
make_safe @params[:title]
end
[5] pry(#<Post>):1>
70. Where did that nil come from?
[4] pry(#<Post>):1> $ safe_title
From: post.rb @ line 7:
Number of lines: 3
Owner: Post
Visibility: public
def safe_title
make_safe @params[:title]
end
[5] pry(#<Post>):1> @params
71. Where did that nil come from?
[4] pry(#<Post>):1> $ safe_title
From: post.rb @ line 7:
Number of lines: 3
Owner: Post
Visibility: public
def safe_title
make_safe @params[:title]
end
[5] pry(#<Post>):1> @params
{“title”=>”new post”, “body”=>”your text here”}
[6] pry(#<Post>):1>
72. Where did that nil come from?
[4] pry(#<Post>):1> $ safe_title
From: post.rb @ line 7:
Number of lines: 3
Owner: Post
Visibility: public
def safe_title
make_safe @params[:title]
end
[5] pry(#<Post>):1> @params
{“title”=>”new post”, “body”=>”your text here”}
[6] pry(#<Post>):1> edit --ex
73.
74.
75. Where did that nil come from?
[5] pry(#<Post>):1> @params
{“title”=>”new post”, “body”=>”your text here”}
[6] pry(#<Post>):1> edit --ex
[7] pry(#<Post>):1>
76. Where did that nil come from?
[5] pry(#<Post>):1> @params
{“title”=>”new post”, “body”=>”your text here”}
[6] pry(#<Post>):1> edit --ex
[7] pry(#<Post>):1> .git diff
77. Where did that nil come from?
[7] pry(#<Post>):1> .git diff
diff --git a/post.rb b/post.rb
index d0ed356..057d37c 100644
--- a/post.rb
+++ b/post.rb
@@ -4, 7 +4,7 @@ class Post
end
def safe_title
- make_safe @params[:title]
+ make_safe @params[„title‟]
end
[8] pry(#<Post>):1>
78. Where did that nil come from?
[7] pry(#<Post>):1> .git diff
diff --git a/post.rb b/post.rb
index d0ed356..057d37c 100644
--- a/post.rb
+++ b/post.rb
@@ -4, 7 +4,7 @@ class Post
end
def safe_title
- make_safe @params[:title]
+ make_safe @params[„title‟]
end
[8] pry(#<Post>):1> cd ..
79. Where did that nil come from?
[8] pry(#<Post>):1> cd ..
[9] pry(main)>
80. Where did that nil come from?
[8] pry(#<Post>):1> cd ..
[9] pry(main)> whereami
81. Where did that nil come from?
[8] pry(#<Post>):1> cd ..
[9] pry(main)> whereami
From: post.rb @ line 19 :
16: new_post = Post.new(
17: 'title' => 'new post',
18: 'body' => 'your text here')
=> 19: binding.pry # Added for debugging
20: puts new_post.safe_title
[10] pry(main)>
82. Where did that nil come from?
[8] pry(#<Post>):1> cd ..
[9] pry(main)> whereami
From: post.rb @ line 19 :
16: new_post = Post.new(
17: 'title' => 'new post',
18: 'body' => 'your text here')
=> 19: binding.pry # Added for debugging
20: puts new_post.safe_title
[10] pry(main)> puts new_post.safe_title
83. Where did that nil come from?
[9] pry(main)> whereami
From: post.rb @ line 19 :
16: new_post = Post.new(
17: 'title' => 'new post',
18: 'body' => 'your text here')
=> 19: binding.pry # Added for debugging
20: puts new_post.safe_title
[10] pry(main)> puts new_post.safe_title
new-post
=> nil
[11] pry(main)>
84. Where did that nil come from?
[10] pry(main)> puts new_post.safe_title
new-post
=> nil
[11] pry(main)> puts new_post.safe_title;
85. Where did that nil come from?
[10] pry(main)> puts new_post.safe_title
new-post
=> nil
[11] pry(main)> puts new_post.safe_title;
new-post
[12] pry(main)>
86. Where did that nil come from?
[10] pry(main)> puts new_post.safe_title
new-post
=> nil
[11] pry(main)> puts new_post.safe_title;
new-post
[12] pry(main)> <ctrl+d>
87. Where did that nil come from?
• binding.pry (open pry right here, right now)
• cd (change self)
• whereami
• edit --ex (also, edit -i)
• . (run’s shell commands)
• <ctrl-d> (cd .. or exit)
• ; (suppress output)
88. Progress
• Introduction
• How do I use the Base64 library?
• Why doesn’t my method work?
• Where did that nil come from?
• What does ordinalize actually do?
• Conclusion
91. What does ordinalize actually do?
[1] pry(main)> help gem
Gems
gem-cd Change working directory to
specified gem's directory.
gem-install Install a gem and refresh
the gem cache.
gem-list List and search installed
gems.
gem-open Opens the working directory
of the gem in your editor.
[2] pry(main)>
92. What does ordinalize actually do?
[1] pry(main)> help gem
Gems
gem-cd Change working directory to
specified gem's directory.
gem-install Install a gem and refresh
the gem cache.
gem-list List and search installed
gems.
gem-open Opens the working directory
of the gem in your editor.
[2] pry(main)> help gem-install
93. What does ordinalize actually do?
[1] pry(main)> help gem
Gems
gem-cd Change working directory to
specified gem's directory.
gem-install Install a gem and refresh
the gem cache.
gem-list List and search installed
gems.
gem-open Opens the working directory
of the gem in your editor.
[2] pry(main)> gem-install --help
94. What does ordinalize actually do?
[2] pry(main)> gem-install --help
Usage: gem-install GEM_NAME
Installs the given gem and refreshes the gem
cache so that you can immediately 'require
GEM_FILE'
-h, --help Show this message.
[3] pry(main)>
95. What does ordinalize actually do?
[1] pry(main)> help gem
[2] pry(main)> gem-install --help
[3] pry(main)> gem-install activesupport
101. What does ordinalize actually do?
[6] pry(main)> break Fixnum#ordinalize
Breakpoint 1: core_ext/integer/inflections.rb:14
12: # -1001.ordinalize # => "-1001st"
13: #
=> 14: def ordinalize
15: Inflector.ordinalize(self)
16: end
17: end
[7] pry(main)>
102. What does ordinalize actually do?
[6] pry(main)> break Fixnum#ordinalize
Breakpoint 1: core_ext/integer/inflections.rb:14
12: # -1001.ordinalize # => "-1001st"
13: #
=> 14: def ordinalize
15: Inflector.ordinalize(self)
16: end
17: end
[7] pry(main)> 5.ordinalize
103. What does ordinalize actually do?
[7] pry(main)> 5.ordinalize
Breakpoint 1. First hit.
From: core_ext/integer/inflections.rb:14:
=> 14: def ordinalize
15: Inflector.ordinalize(self)
16: end
[8] pry(5)>
104. What does ordinalize actually do?
[7] pry(main)> 5.ordinalize
Breakpoint 1. First hit.
From: core_ext/integer/inflections.rb:14:
=> 14: def ordinalize
15: Inflector.ordinalize(self)
16: end
[8] pry(5)> step
105. What does ordinalize actually do?
[8] pry(5)> step
From: core_ext/integer/inflections.rb:15:
14: def ordinalize
=> 15: Inflector.ordinalize(self)
16: end
[9] pry(5)>
106. What does ordinalize actually do?
[8] pry(5)> step
From: core_ext/integer/inflections.rb:15:
14: def ordinalize
=> 15: Inflector.ordinalize(self)
16: end
[9] pry(5)> step
107. What does ordinalize actually do?
[9] pry(5)> step
From: active_support/inflector/methods.rb:280
279: def ordinalize(number)
=> 280: if (11..13).include?(number.to_i.abs % 100)
281: "#{number}th"
282: else
283: case number.to_i.abs % 10
284: when 1; "#{number}st"
285: when 2; "#{number}nd"
286: when 3; "#{number}rd"
287: else "#{number}th"
288: end
289: end
290: end
[10] pry(ActiveSupport::Inflector)>
108. What does ordinalize actually do?
[9] pry(5)> step
From: active_support/inflector/methods.rb:280
279: def ordinalize(number)
=> 280: if (11..13).include?(number.to_i.abs % 100)
281: "#{number}th"
282: else
283: case number.to_i.abs % 10
284: when 1; "#{number}st"
285: when 2; "#{number}nd"
286: when 3; "#{number}rd"
287: else "#{number}th"
288: end
289: end
290: end
[10] pry(ActiveSupport::Inflector)> next
109. What does ordinalize actually do?
[10] pry(ActiveSupport::Inflector)> next
From: active_support/inflector/methods.rb:283
279: def ordinalize(number)
280: if (11..13).include?(number.to_i.abs % 100)
281: "#{number}th"
282: else
=> 283: case number.to_i.abs % 10
284: when 1; "#{number}st"
285: when 2; "#{number}nd"
286: when 3; "#{number}rd"
287: else "#{number}th"
288: end
289: end
290: end
[11] pry(ActiveSupport::Inflector)>
110. What does ordinalize actually do?
[10] pry(ActiveSupport::Inflector)> next
From: active_support/inflector/methods.rb:283
279: def ordinalize(number)
280: if (11..13).include?(number.to_i.abs % 100)
281: "#{number}th"
282: else
=> 283: case number.to_i.abs % 10
284: when 1; "#{number}st"
285: when 2; "#{number}nd"
286: when 3; "#{number}rd"
287: else "#{number}th"
288: end
289: end
290: end
[11] pry(ActiveSupport::Inflector)> next
111. What does ordinalize actually do?
[11] pry(ActiveSupport::Inflector)> next
From: active_support/inflector/methods.rb:287
279: def ordinalize(number)
280: if (11..13).include?(number.to_i.abs % 100)
281: "#{number}th"
282: else
283: case number.to_i.abs % 10
284: when 1; "#{number}st"
285: when 2; "#{number}nd"
286: when 3; "#{number}rd"
=> 287: else "#{number}th"
288: end
289: end
290: end
[12] pry(ActiveSupport::Inflector)>
112. What does ordinalize actually do?
[11] pry(ActiveSupport::Inflector)> next
From: active_support/inflector/methods.rb:287
279: def ordinalize(number)
280: if (11..13).include?(number.to_i.abs % 100)
281: "#{number}th"
282: else
283: case number.to_i.abs % 10
284: when 1; "#{number}st"
285: when 2; "#{number}nd"
286: when 3; "#{number}rd"
=> 287: else "#{number}th"
288: end
289: end
290: end
[12] pry(ActiveSupport::Inflector)> continue
113. What does ordinalize actually do?
[12] pry(ActiveSupport::Inflector)> continue
=> “5th”
[13] pry(main)>
114. What does ordinalize actually do?
[12] pry(ActiveSupport::Inflector)> continue
=> “5th”
[13] pry(main)> gist -m ActiveSupport::Inflector.ordinalize
115. What does ordinalize actually do?
[12] pry(ActiveSupport::Inflector)> continue
=> “5th”
[13] pry(main)> gist –m ActiveSupport::Inflector.ordinalize
Gist created at https://gist.github.com/465407823ee6182d8833 and
added to clipboard.
[14] pry(main)>
116. What does ordinalize actually do?
[12] pry(ActiveSupport::Inflector)> continue
=> “5th”
[13] pry(main)> gist –m ActiveSupport::Inflector.ordinalize
Gist created at https://gist.github.com/465407823ee6182d8833 and
added to clipboard,
[14] pry(main)> !!!
117. What does ordinalize actually do?
[12] pry (ActiveSupport::Inflector)> continue
=> “5th”
[13] pry(main)> gist –m ActiveSupport::Inflector.ordinalize
Gist created at https://gist.github.com/465407823ee6182d8833 and
added to clipboard,
[14] pry(main)> !!!
$
118. What does ordinalize actually do?
• help (and --help)
• break (pry-debugger)
• step/next/continue (pry-debugger)
• gist
• gem-install (-cd, -open, -list)
• !!! (exit)
119. Progress
• Introduction
• How do I use the Base64 library?
• Why doesn’t my method work?
• Where did that nil come from?
• What does ordinalize actually do?
• Conclusion
120. More good plugins (pry-plus)!
• pry-rescue
– Automatic binding.pry where-ever you have an
unhandled exception or test failure.
• pry-stack_explorer
– Lets you move up-and-down the callstack.
• pry-doc, pry-docmore
– ?/show-doc for C methods, ruby syntax
• bond
– Better-yet tab completion
121. Configuration
• Configuration
– ./.pryrc and ~/.pryrc
• Custom commands
Pry.commands.add_command „test‟ do
output.puts “test”
end
• Documentation on the wiki
122. There’s still more…
He
p
l bitlsa
enrk
roife
aA`
ka
po b
` *** REMOTE GEMS ***
hoa mTeof abf>
ewmayl<`rr tato
p ic d`pfoinu
lS lf nef>mo.
hs shoi o <
o
t .p o o
o n blsat
eop
rifeis
ark`
k`o
A
sbn
a
pr
iA
ltifi
cls`
a
og
`
t
s
-
p
l
c
Cxon
e
t e erm`
lmA- e
i- dife d
f olsl o
a
oh
s
` pry-awesome_print (9.6.5)
d vnobe
c oacxcp
Mtenjt )
ew(e.
n er
io toos
o
c hls
or
to
sa
irifi
y`
As h
t pry-bot (0.0.1)
n hec t ta ue si
idtdrrr ewC dtcaef
f- eRlamdin oortm.
m ch h hls lhn p
oufa o a eu a
v
iy M e
so / re c
es n A
ta
so
iifi
jlsg
`
r
t
s
S hrmdup
lhtlfnescte
swv titrs.
oedhhn
o
ts o
s ne
ia oec qls
ur
Ai
ta
iifx
oe
`
t pry-buffers (1.0.0)
pS tbrP.
yh efe
rcohern
b chi
-kwaty
a ks
r ro
t toe
e qgAxm
umrr `
tr ifig
ir lso
p oa
-a ar
o` e
t
p
- pry-capture (1.0)
aRenfcpc
rpatoets.
esc oete
sin try
i-ax uurn
uep tn
o n
i hia hmdsw`
s - eAo-r
o t lf s
whio ooa u
h
s
`e
rc pry-clipboard (0.1.1)
esRa.
reEce
stPn
Retls
thLaot
ea
wmwsnett
h ihcudccx
e S origro
r odutun
a e nee
ohn. Gt
s
i pry-coolline (0.1.5)
wwafmnn
? tbt otp
f eo tx
tohe se
S ch rc
h ke et
r o
t ci gmdrnGb
G oxt
tt hes H
ss t reirt.
ii eoshiu
a po ot
iyo pry-de (0.1.0)
pry-debugger (0.2.1)
E
d n
t
ig M c
s
i pry-debundle (0.6)
Ciureprssode
!apfsepergyt
e teuro noc
lrnuf acwau
h . i igg s
t b l se ng
e U no u
h
t
f k pS P.
yh y
rn rn
vw
- ov
ee
oo
i i
s s
r r
aee eleuu o
m-Anot le d
nmafimm.
d dip t e
n
i nn -
l in i n e- tdasftttsdtd
raeRduaise e
o olhrhapm
ldhetotcnc h
m oeioh o
e i
cne
l f pry-developer_tools (0.1.1)
ekeira
dtddf
n ul
Ioao
teftoi.
iveltn
hee mr te e t
i l- plti lpp
spmgspm
e Th r .
p omo
o e pry-disasm (0.0.1)
eeEsor e.
dtdedmd
t oiof h
i hdue t
m hca
- tro o
e olTsih.
tl-rgxh
gotgg
elylt
ong
ceii
oan
h pry-doc (0.4.4)
h apahlsr
t dR s:i
swraleay
ihnlydirie
S eet h
o iosnyt
A
.o
paroeop
akibmrs.
lycar tdat
Pslahau
av in
lyg ofi
be l
n
i
r
t e pu1
yg)
rb0
dr
-e
e(
v2
. pry-docmore (0.0.3)
hip tcnnueme.
s -uwnfipfrctuxn
onohtteteu les
wt es urr tp
S oobte i e
h e on- r
h
t h nio btdkt
ertro
reibi.
aap
k en
Sa
o
e pry-editline (1.1.1)
bitfdp
enbis
roieat
as ro
kL en
pe k.
dn pry-em (0.2.1)
nc
Ite
on
rt
p
s
o
i oeter xanP.
cunp eneen
nCug cndr
i i o u hi
tormtdty
ai s
o eo
iiwmnra
Vrc n.a
r ioe.ey`
ed tge
u ai#
or h
i`c
A ntirs rn
isctn es
fEntmr
hua t.
ecc
xle u
uuf
ek r pry-exception_explorer (0.2.3)
hc ahhrr D
s - mS tsfM
oo noeo .
w dwu
m oC e
c nteeinrt e
ehlwes .
E x hn
teehum
xn ttca
et e
un k
ci c r
f pry-full (1.2.0)
hsS hrr eoewtd
s -rotsfmdlso- e
oowu t ri:, m
wh eo hc$ h
u oa oss o
e e ah
c c l.aA eenem
tScitnr td
spnee e.
pxox h
et hl
tutto o
on
i i pry-full18 (0.4)
a tn insnila
ti md tat__c
sweif anfad
V hooddo
e or e rl
m __e
l .
i s pry-gist (5.1.12)
p o3
ye
rc r.)
d(
-m
ov 0
ndu
Ipot
uu
ap
tt
n hdotd nfmd rble
s -cwoen e/ oas
oo hc to tc dlA
wh em r hs /.i:
S u aa oyga
o ao
i lk l ?
e
w pry-git (0.2.3)
< m lx ig rds
.smaAwrate
h ntl n dth
e de a e e
o oi
c o . h.
l >f 'wol
o
f
s hd ryrnvym
s -co odrbco
oo e dvdo r
w s sa p e
mw c r
k e
t sd
i r-
L aoy
e pry-github (0.0.2)
a cr frurein
cwf apfrlst.
S d i,ybttp
t om' teao
h e lPue
o oe ,h
s ox
n
i c pry-hack (0.1)
aoutt hP
sEagn tR
vrfsnmE
etiicf eL
l
i ooo
fpee
-xlnr . pt_r.3
yne
rpe()
e p2
-i xv
co
x l0
o
h dls dg p td p.
s ogl orpd pfmn
e ee eiwmic lt
l Th .in r aoe
m mn l o
- oe B o n ie oenmntcen
cutAptertp
n-pt tiuux.
i c c et
tx e ohc
e o ei
o no
i pry-highlight (0.0.1)
epnnet
ntEexlsin
e tofa
txncotp
ri ette
-orex
e c
c hho pry-multi_debugger (4.8.15)
Ng ar
vy
g
ia
n
t
p enexctp
-pacoren
ttvttet
icenec
xLtofux.
eeeni
o
i hh o pry-nav (0.2.3)
pyonnr dux.
!trnrtivoimen
ys ce k tp
rPnsw les
Si uh s i r
a es m - e
re le ni
of ; o
etpsigsOg)lsi
Pe no ir a
tpeid x At
iorb(Nem:u
xhiuneTr .ie
v d ta q
o p o pu)
ylr
rp.3
pi0
-a
ot
y
v
( pry-note (0.2.9)
etctinigddigrc
aerpnneop
-drP(pliigrrtl.e
t eo nnne
ilnus b)uas
xhyoast ct
En a Ae puruyes
ylrt tyuf
rprprqce
pio iby
- ayhfn
otpsr o
yi o u
Se
n pry-padrino (0.1.2)
emtctg.lsirm
p nurmeo !
-gEep Atg,
tr er qa
ir hn a-r
x dro i:u
o a p
a pry-plus (0.2.0)
up pideeigig .
jmmbgrtsplidlw
o an h bb
t oif ppn s
-J tnrutoan
u u a ne
hk
tc o
, p(4
y0
re
e.)
-v
u
c
s1
nonf a
ewg t.
n in
ig tim
th soo
s er in
Sn cs oeuen
d vpsx
a teap
-e erlrc
u ovid
Mtiyt
ho ieo pry-popularity (0.0.3)
wrwoaiitumy)
si-tesinbgctubbg
hn - nhn ds
ca bnnra r e
tS uoides en
o s ne t
e c i.k n
n
( yedust
rnehdp
tiRcttsixn
ateei
- -oatc
gr ch
y e
h o pry-pretty-numeric (0.1.1)
pry-rails (0.2.2)
Gs
em plr.7
yo
re()
a0
te
sp4
-xv
k
c
_ pry-remote (0.1.6)
g-hwdsd'ic
eca oicpesr
mn rrremy
dgkec d
Ceigyig r.
ntf e
o o
t t
o dndncn
oGwet
wo tae
oolcx
ho
te.
s
'
g-lsmrtgc
eisgafe a
mlenseh
n d m.
a h
tt e e
n
Ia a wa .
r Star e
f eitpm
mcrfht
olu
c
ia pry-remote-auto (1.1.0)
g-dsgs
elnite.
msnm
ah
Lce
tra
sa
ield hsw s
s -oae
ot lm
wf
ar
k
c
Sh pry-remote-em (0.7.3)
uotcn
puet
Gtae
plrx
o' .
h
eo
c
s pry-rescue (0.14)
Cm
oa
mn d
s
mI o ms
i p pmat
or n
ta e
rt d
e
so
- c
m pry-stack_explorer (0.4.7)
n atild m
is mIsbma
a dso d
tmnldc n
o a
c a
- ne .
l pry-syntax-hacks (0.0.6)
pry-theme (0.1.3)
pry-vterm_aliases (1.0.0)
Aa
ie
ls
Ax `
!lsrm
ag
ifio
ore
`
ra
t
p
-
@r
! Ax a
if-
lsl
oe
``
a
t
i
$rw`
Ao-r
au
if o
ls s
oc
h
s
`e
?rw
Ao-c
a`
if o
ls d
oh
s
`
Hello, I’m Conrad. One of the maintainers of Pry.Just before we get started, how many people here already know about pry?Cool. How many of you would say you understand it?Hmm. Luckily I’m planning to go through a lot of that today.
The structure for this talk is as a set of use-cases that allow me to demonstrate some of pry’s features.I thought it would be interesting if I structured it so that you could follow along on your own laptops. So that’s what I’ve tried to do.If you’d like to follow along, you’ll need a laptop with pry-plus installed. Pry-plus is a gem that encompasses both the base pry and also some of the most useful additional plugins.I’d advise installing with the --no-ri and --no-rdoc flags if you want the install to finish more quickly.
So while people are installing.What is pry?If you’ve been using ruby for a while the easiest way to think about pry is that it’s like irb but better. You can start irb from bash and then type ruby into it, and irb tells you what the ruby evaluates to.In the same way, you can start pry from bash, and then you can type ruby into it, and pry tells you what the ruby evaluates to. I say “but better”, because pry also has additional features, for example we have commands that wrap ruby’s introspection features; which makes it easier to explore programs. We also have binding.pry, which lets you open a REPL at any point in your program.We also have syntax highlighting, which I think might the reason that most people use pry.More formally, both pry and irb are REPLs. REPLs or read evaluate print loops were first invented by the lisp people way back when. They read in a line of user input, evaluate the code, and then print out the result. This is useful for iteratively creating programs, because you can see immediately whether a line of code works or not.Calling pry a REPL, or saying that it’s like irb but better, tells you what it is; but it doesn’t tell you why it’s like that.I like to think of pry as an aide for ruby programmers.
What that means is that pry isn’t directly going to solve any of your problems.Instead pry is designed to help you solve your problems yourself.In particular, most programming problems are somewhat creative in nature. You’re not going to be able to teach a computer to program in the same manner a human is expected to program.What this means is that pry contains a large number of simple tools that help you solve problems.This is somewhat annoying for talking about pry, because it means that there’s not as much depth as I’d like. Instead there’s a phenomenal amount of breadth.
So the way this talk is structured is as a set of four different questions that a programmer might need to ask; and I’m going to demonstrate how to combine several features of pry into solving each one.The aim is to let you know how pry works, so the examples are deliberately on the simple side.Does everyone who wants to follow along have pry-plus installed?I should say, if at any point something isn’t clear, let me know and I can go through it in more detail. I’m used to talking to other programmers, so going for an hour without being interrupted is pretty unusually. So, if you have a question, that’ll help me feel like this is a more normal conversation.
So “how does Base64 library work?”A non-lazy programmer, i.e. someone who believes in doing things properly more than getting them done efficiently, might try to learn the library by going on the internet, searching for the docs and then reading them.I find that a pretty inefficient solution, as I don’t easily remember documentation having just read it once. I like to play with a library and see what it actually does.So step 1, obviously is to start pry.As I said you can do this by just typing pry.
And immediately, the prompt appears. Note the [1] on the far left that means that Pry is waiting for the first line of input. We’ll go over what (main) means later.As we’re trying to learn the Base64 library, let’s require it.
You can type arbitrary ruby code into pry. You can even split it across multiple lines if necessary, though in this case it’s not.
You’ll notice that when I hit return at the end of the line, pry goes back a syntax-highlights the text I wrote.As I said earlier I think this is one of the main reasons people actually use pry instead of irb. It’s just a bit more friendly, and bit easier to see what is going on.Now we’ve required the library, we need to guess at how it works.In Ruby, I’m sure you’ve noticed, almost every library consists of a top-level module with the same name as the library. In this case, Base64.
I’m going to use the pry command “ls” on Base64.In bash, as you know, ls shows you the list of files in a directory.In pry, ls shows you the list of methods on an object.Interestingly, the ls command in bash gets a lot of abuse for having 26 different options or something silly. I didn’t realise quite why, until I had to change the ls command in pry. We’re not doing quite that badly yet, but I think ls has about 12 different options to show you different combinations of methods, private methods, local variables, constants, globals, everything.Given how much it can do, ls is one of the most-used pry commands by a long way.Anyway, I run ls Base64
Anyway I run ls Base64 and it tells me that there are 6 methods available. That seems a bit over the top, but fair enough.There’s decode64 and encode64, they make sense; and then there’s strict_encode64 and strict_decode64. I’ll come back to them later, and then there’s urlsafesomethings, I’m not going to go into detail about them.Now I know which methods are available, I want to try calling them. This helps cement my knowledge, so I can hopefully avoid checking the docs again at a later stage.
So I start typing out Base64.encode64, so that I can see how it works, and then I got bored half-way through.Luckily pry, like irb, has me covered, and I can just hit <tab> and it completes the method for me.
That might seem trivial, and indeed a lot of Pry’s features do, when they’re described. It’s just “obvious” once you know, but at one point the tab-completion code was a large messy portion of the code-base.It’s still a messy portion, but the rest of the code-base has grown so that it no-longer feels so large.
Ok, I run that method with “hi” as the argument and it gives me a string that looks convincingly like Base64 wonderful.Now, let’s try decoding.
At this point I could type in “aGk=\\n”, but instead I can just use the underscore variable.
_ is a special variable maintained by pry that contains the previously output result.So in this case, _ is equal to “aGk=\\n”
And, obviously, when I hit return, it gives me back the string I started with.
So looking back at the list of methods, I’m still curious as to what the difference is between encode64 and strict_encode64.Luckily pry has me covered again.
The ? Command otherwise known as show-doc shows the documentation of a method.In this case I’m going to look at the strict_encode64 function.
And here are the docs.You’ll notice that there’s a few lines of meta-data added by pry. It shows you the file in which the method is defined, the owner which is the Base64 module, or its singleton class. It’s also a public method, that takes one argument.The docs are self-explanatoryReturns the Base64-encoded version of bin. This method complies with RFC 4648. No line feeds are added.For comparison, the docs of Bae64.encode64 say
Line feeds are added every 60 characters.This distinction is worth being aware of, as HTTP headers can’t include line-breaks, and so if you just blindly use encode64, your application may well be buggy.There was an issue filed against em-http-request for exactly this reason. When they were encoding an HTTP BasicAuth header, with a long username + password, the header line-wrapped and thus was broken.
Ok, so that’s the first, and most basic example.I showed you syntax highlighting, which is still my favourite pry feature. Tab-completion, which no REPL worth its salt would omit.The underscore variable contains the most recently output value from pry.Then I showed you two commands, ls which lists methods, and ? Which shows documentation.Are there any questions so far?<drink lots of water>
So I hope that the previous section felt quite easy. Because it’s going to get a little more advanced from here-on-in.
If you’re following along still, you can get the code for the next section from gist.github.com. 4463940So, given that I just mentioned HTTP Basic authentication, the next example is based on that.I wrote some code that was supposed to implement encoding and decoding of HTTP Basic Auth headers, but it has a bug.
First things first.Here’s pry’s “cat” command in action.Cat in pry, just like in bash, prints a file to your terminal.Because pry loves syntax highlighting, if you pass it a file that CodeRay knows how to highlight, it will do that for you. CodeRay knows how to highlith most programming languages, and of course it knows how to highlight ruby.So here’s basic_auth module that I wrote.It’s using the Base64 library and it provides two methods encode which takes a username and a password, joins them together with a colon, and then encodes them in Base64 and adds the word “Basic” at the front.The decode method is exactly the opposite, it takes a header, extracts the Base64 from the string. (This is clever ruby syntax for extracting a regex match, because I like showing off).It then takes the base64, decodes it and splits on a colon.There is a bug, but keep it to yourself for now.
Ok, so now we know what the code is supposed to do let’s require it.I could have typed require “basic_auth.rb”, but pry provides another handy shortcut._file_ is a special pry variable that keeps track of the last file you interacted with using a pry command. So show-doc which we’ve already seen also sets _file_, as do a variety of other comands we’ve not seen yet.There’s a similar variable called _dir_ which keeps track of the directory containing _file_. It’s less useful, so it’s not officially included in the good parts, just gets an honourable mention.Now the library is loaded, let’s test it.
Good, if I try encoding my username, which is “hi” and my password, which is “mum”, I get back a very convincing looking HTTP header.Obviously if I was not being lazy, I would have written an actual test suite; but because this is just an example for my slides, I’ve not done that.And so, when I try the decode method, I find.
*boom* NoMethodError: undefeined method unpack for bleagh Array.Ummm….That doesn’t make much sense, because I’m not calling the unpack method.
So I ask pry wtf? Which stands for “where’s the failure?”
The wtf? Command shows the backtrace of the most recent exception.Before the wtf? Command existed you could do this manually using another pry special variable called _ex_, which contains the most recent exception.So, wtf? Shows me that the unpack went wrong in the base64 library itself. So I suspect that the actual problem is in BasicAuth.decode function which is the second line of the backtrace(it’s the second line, but it’s labelled with a 1 because we’re proper programmers and numbers start form 0).
So in order to find out what the problem is I’m going to use another pry command.This time, dollar. Dollar is similar to question-mark except that instead of showing the documentation for a method it shows the source code.Dollar can be written in full as show-source, but no-one does that.You can also pass it modules and classes, but usually a method is what you want.
So in order to find out what the problem is I’m going to use another pry command.This time, dollar. Dollar is similar to question-mark except that instead of showing the documentation for a method it shows the source code.Dollar can be written in full as show-source, but no-one does that.You can also pass it modules and classes, but usually a method is what you want.
Here’s the source for my decode method, you might remember it from a few slides back.Pry has helpfully added a header, the same as before, so the file is basic_auth.rb, the owner is the BasicAuth module, the visibility is public.Now I read the source closely, and I think I can spot the problem.I’m splitting the Base64 before I decode it. I actually need to decode the base64 and then split the resulting string.This is easy to fix, and pry can make it even easier.
All I need to do is fix the BasicAuth method.Enter pry-command number 5 I think. We’re going through them quite fast.Edit-method does exactly what it says on the tin. It opens the method in your editor.Now, I could type out BasicAuth.decode after edit-method, but I thought I would share a readline tip I came across recently.It turns out that you can type <alt+_> on LInux
Or <esc> followed by _ on mac
And readline will copy the last word of the previous line down to the current line.This is really useful in both pry and bash, if you want to perform a new action on the same argument.And, on with the demoSo I hit return, and pry opens up my editor, which is configured using $EDITOR to be sublime.
Then I insert the necessary parenthesis
And then save and quit.If you’re following along, you need to add brackets around the base64 variable on line 10. lOOOKAnd if Pry has opened vim, and you don’t know how to use vim, then just :q will get you back into pry.
Once my editor has quit, pry automatically reloads the code that was changed.This means that without having to do anything else I can test the library again!Obviously, it would be a bit much to ask me to type out those lines of test code again, so the second readline feature I want to show you is reverse history search.
At a prompt, type <ctrl+r> and it will open reverse search.
Now all I need to do is type three letters, let’s say “e-n-c”
And pry finds the previous line contained enc; which, luckily enough, Is the BasicAuth.encode ‘hi’, ‘mum’ test.So I run that.
Good, changing the decode method hasn’t broken the encode method.
Now I do the same thing again, to avoid re-typing BasicAuth.decode _. And then I run that.This time, instead of exploding, it gives me back my username and password correctly.
If I’d wanted to avoid re-testing the encode function, I could have instead used pry’s _out_ variable to access the output of the previous BasicAuth.encode test.I think it was about line 3. So, just like _ is the output of the previous line, _out_ is the array of all outputs ever.For efficiency it actually only keeps 50 or so around, but I’ve never noticed the missing ones.So _out_[3] is the string “Basic aGk” from the previous test of encode, and as expected it gives me the username and password correctly.
If I’d wanted to avoid
Ok, so that’s example two over and done with, a quick recapThewtf command shows the backtrace of the most recent exception. The more questions marks and exclamation marks you give it, the more lines of backtrace it gives you. I think it’s about 10 per question-mark so you never need to get tooo carried away.$ also known as show-source shows the source code for a function. It’s very similar to show-doc, except it shows you stuff that’s actually true.Edit-method, edits a method. There’s also another edit command, which we’ll come to in a bit.Readline tips I inserted for good measure, alt+_ or <esc>_ copies the last word of the previous line down to the current line. Very useful in both pry and bash.Ctrl-r searches backwards in history until a matching line is found.Then two more pry special variables. _file_ is the most recently touched file by a pry command, and its companion _dir_ is the directory containing that file_out_ is the array of all output values ever, and its companion _in_ contains the input string for all things you’ve typed so far.
Thefavourite exception of every ruby programmer is of course “udnefinedmethoed for nil”.And so, I’m going to show you how pry can let you see easily why these are happening.
Again, this requires an extra lump of code, which you can get from gist.github.com/raw/4464704 and save it in a file called post.rbThe problem usually with errors that say “undefined method for nil” is that they aren’t local problems. You didn’t actually write nil.gsub, or whatever, instead you wrote a method that is expecting something that’s not nil and a pesky caller calls your method with a nil.These can thus be a bit fiddly to debug, because you need to look in more than one place to understand the problem, but pry to the rescue!
So if you try running that file, you’ll see that you get an exception. Unsurprising, as I told you you would, but still annoying.
So, let’s open our trusty editor and add some pry goodness to the file.
Here’s the code for the current example.It’s a simple “Post” class. Post as in ‘blog post’, because all ruby examples are required to include at least one reference to blogsIt takes in a some params, and stores them as @params. It also provides a method for getting the safe_title. The safe title, is one that could be included in a URL for example, it has all the special characters removed.The make_safe function does the actual substituting, replacing any non-word character by a hyphen.The file ends with two lines, that test this class. The first creates the new post, and the second outputs its safe_title.I’m going to make two changes, one is to add a “require ‘pry’” to the first line, so that pry is available. The other change is to add a binding.pry on line 18, because the program crashed on line 19.
binding.pry is one of the more exciting features of pry. It allows you to start a pry repl from in the middle of your program. All the local variables and methods will be available to play with just as though you were adding code to your program in realtime.
Now we’ve saved those changes, let’s try running the program again
Instead of raising an exception as before, it’s going to stop at the binding.pry line.
So you can see that pry has stopped on line 19, where there’s a binding.pry (hmm, I thought it was line 18, ah well, must be formatted differently).Regardless, we’ve stopped at the binding.pry just before the line that crashes (you can see where we are by looking at the arrow in the source listing).We can double-check that the next line is the problem by just copying-and-pasting it into pry, and seeing that it does indeed raise the same exception.
Ok, so we know that new_post.safe_title crashes. But it’s going to be a bit inconvenient to explore new_post from the outsideEvery time we want to type something, it’s going to have to start with new_post.
This is where pry’s “cd” command comes in handy.As in bash, cd moves the current directory. In pry, cd moves the current object. It changes the value of self, and also changes where methods are defined.In order to debug a problem with new_post more efficiently, let’s cd inside it.
You can see that the prompt has now changed.Instead of showing (main), it now shows (#<Post>) bracket. The #<> is the standard way of saying saying “an instance of” in ruby. So the prompt is telling us that self is currently an instance of the post class. It’s also gained a :1 which is there to remind us that we have cd’d one level away from the top.Given that self is now the new_post object, it makes sense to use `ls` to find out as much as possible about the new_post.
Before, we used ls on a module and it showed us a list of methods.Now we’re going to use ls with no argument which shows not only methods, but also instance variables and local variables.
As you’ll remember from the source, the two methods are make_Safe and safe_title (safe_title calls make_safe with the title).Post objects also have an @params instance variable which contains all of the data that was passed in to the constructor.There are no local variables yet, because we have just cd’d into the object, but there are the 7 pry special local variables. We’ve already mentioned most of them, _dir_ and _file_ are the last path touched by a pry command, _in_ and _out_ are arrays of input and output, underscore is the most recent return value, _ex_ is the most recent exception, and _pry_ is the current pry instance. That’s actually mainly useful for debugging pry, but we left it in anyway in case you get curious.
Or even that we wanted the safe_title method that was defined on the Post class.
The convention of referring to a method defined in a class with a # separator is copied from various documentation tools.You’ll also notice that it was used in the output of ls to show that the methods where defined on the post class.
The source code should look familiar, we’ve seen it before. It’s just passing the title of @params to make_safe.Unfortunately we know this doesn’t work, because it raises an exception.In order to see clearly what the problem is we need to look at the value for @params.As self is currently new_post, this is as easy as typing @params.
And again, it’s obvious what the problem is. I’m referencing @params[:title], but @params contains string title.As in the previous example, this is pretty easy to fix. I just need to use an edit command.
For something different, I’m going to use edit --ex, which means edit the location of the most recent exception. Several other pry commands, for example also use the convention of --ex to refer to where the exception happened.The edit command also has other flags, the most important, and the default is actually -i which means, edit the current pry input, This is useful if you have made a typo while trying to define something in pry, so that you can go back and redo it using a proper editor.
Ok, you’ve seen enough of my sublime, so let’s just say that edit has happened.For those of you who are following along, I’ll show you the change that was made using git diff instead.
Pry allows you to run any program as though you were in bash by prefixing it with a .So in this case, I can run git diff
And it will show you that I made the sane change to the file to ensure that the safe_title method works.Replacing the symbol title by the string title.Another classic ruby error, in case you haven’t come across it before.
Now we’ve finished debugging the new_post, we can cd out of it again.Just like in bash, cd .. means move up a level
And after doing that, the prompt goes back to pry(main)>.By the way, if you don’t know. The top-level object in ruby, when you’re not inside a method or a class definition, is a special object called “main”. I think it’s created by ruby early on by just doing Object.new, and then the .to_s method is overridden so that it outputs main.
As we’ve been in the new_post object for a while, it’s good to get a refresher of where we were before we cd’d into it.Pry contains a command whereami that does this.
You’ll notice that the output is exactly the same as when pry first opened on this line; and that’s not a coincidingWhenever a binding.pry starts, whereami is automatically run for you so that you don’t have to remenber to do it.Ok, so the whole point of that was to fix line 20, so let’s verify that we’ve actually fixed it by running it again.
I could have used reverse-history-search, but in this case I just copied and pasted.
Yay, it output new-post!You’ll notice that in addition to outputting new-post, pry also said that it was nil.This is because the puts method returns nil.You can tell pry not to show the output value of a line by terminating it with a semi-colon, for example:
That’s mostly the end of section three, but I wanted to show you <ctrl+d>
If you hit control d and you are at the top-level, i.e. not cd’d into anything, then <ctrl-d> will exit pry.If you are cd’d into something then ctrl-d will act the same as cd ..
Ok, 3 out of 4 examples complete.Perhaps the most important pry feature of all, binding.pry. You can use this to open a pry whereever you like. It’s so useful that people have been known to add it as a keyboard-shortcut in their text editor, so that they can add a binding.pry in 0.01 of a second).The three commands I mentioned where cd, to concentrate on a different object temporarily; whereami, which shows you which binding.pry you are stopped at, edit –ex edit’s the most recent exception. I also mentioned, but didn’t demonstate edit –I, which edits the current input buffer of pry.Because pry evaluates commands on a line-by-line basis, you can even use edit -I in the middle of a multiline expression.A . At the start of a line tells pry to pass your input on to bash.A ; at the end of a line tells pry not to show you the output.Finally, <Ctrl-d> can be used to exit an object that you have cd’d into, or to exit pry so that the program can resume after your binding.pry
The final use-case I want to go through is somewhere between the first one and the second two.It’s not really learning, and it’s not really debugging. But the tools I’m going to use, can be applied to both.For this task, I’m going to step outside the realm of pure pry, and show you the pry-debugger gem.Pry-debugger is a fusion of the ruby debugger gem which adds step-through debugging to ruby, and pry. So that you can step through your program, with pry at your fingertips.
So, I want to step through the ordinalize method from activesupport, because it sounds reasonably interesting, but hopefully small enough to fit on a slide.Unfortunately, I haven’t yet told you to install active-support.No worries, I’m sure pry can think of something.
Pry comes with reasonably thorough help for all of its commands.You can pass an argument to help which asks it to filter the results.Given that I want a way for you all to install the active support gem, let’s try asking help what we can do with gems.
There are actually four commands that involve gems.Gem-cd, changes the working directory to that of a gem, gem-open is similar except that instead of moving your pry session it opens your editor.Gem-list gives you a list of gems that are currently visible, which is occasionally useful when trying to understand what Bundler is up to this time.But the command that we are going to use is gem-install.If you need more details on any command, you can run help and then command name, so for gem-install I could run “help gem-install”, or like in bash, most commands respond to –help, so I could do gem-install –helpThat said, a lazy programmer wouldn’t bother, it’s obvious how to use gem-install, we just give it a gem-name.
There are actually four commands that involve gems.Gem-cd, changes the working directory to that of a gem, gem-open is similar except that instead of moving your pry session it opens your editor.Gem-list gives you a list of gems that are currently visible, which is occasionally useful when trying to understand what Bundler is up to this time.But the command that we are going to use is gem-install.If you need more details on any command, you can run help and then command name, so for gem-install I could run “help gem-install”, or like in bash, most commands respond to –help, so I could do gem-install –helpThat said, a lazy programmer wouldn’t bother, it’s obvious how to use gem-install, we just give it a gem-name.
There are actually four commands that involve gems.Gem-cd, changes the working directory to that of a gem, gem-open is similar except that instead of moving your pry session it opens your editor.Gem-list gives you a list of gems that are currently visible, which is occasionally useful when trying to understand what Bundler is up to this time.But the command that we are going to use is gem-install.If you need more details on any command, you can run help and then command name, so for gem-install I could run “help gem-install”, or like in bash, most commands respond to –help, so I could do gem-install –helpThat said, a lazy programmer wouldn’t bother, it’s obvious how to use gem-install, we just give it a gem-name.
There are actually four commands that involve gems.Gem-cd, changes the working directory to that of a gem, gem-open is similar except that instead of moving your pry session it opens your editor.Gem-list gives you a list of gems that are currently visible, which is occasionally useful when trying to understand what Bundler is up to this time.But the command that we are going to use is gem-install.If you need more details on any command, you can run help and then command name, so for gem-install I could run “help gem-install”, or like in bash, most commands respond to –help, so I could do gem-install –help
No underscore, just activesupport all one word.Then we let that run for a bit.
And the activesupport gem is now installed, along with dependencies, as usual.
Ordinalize is part of the core_extensions that active support provides, so we require those here.Note that when requiring you need to require ‘active_support/core_ext’ with two underscores, even though the gem name has no underscore. Confusing.
So, like with most step-through debuggers, the easiest way to start using it is to add a break-point.Break-points take variety of sytaxes, you can read help break at your leisure, but I’m just going to use the standard class#method_name syntax
So, we’ve added a break-point, and it’s on line 14 of core_ext/integer/inflections, that seems fine.Now, in order to start stepping, we’ll need to call the method.
So I just do 5.ordinalize and hit return
And here I am at breakpoint 1.Like with a binding.pry, it’s automatically run the whereami command, so that I can see where I am.I’m sure you’ve all used step-through debuggers before so I’ll try not to labour the point.In order to move forward I can just do “step”
And here I am at breakpoint 1.Like with a binding.pry, it’s automatically run the whereami command, so that I can see where I am
And you can see that that’s moved me from line 14 to line 15.Also notice how the prompt contains the number 5, this is because I am debugging code where self is 5. it’s as though I had cd’d into it.
The step command here is going to take us into the call to Inflector.ordinalize, there is a related command, ‘next’ which moves over a line without calling methods,But as there’s no real code here, let’s step into it and see what Inflector.orginalize does.
I’ve reduced the font-size a bit because this method is huge, but hopefully it’s still legible.You can see that the prompt has again changed, because self is now ActiveSupport::Inflector.
It’s hopefully obvious what this line of code does, so we don’t need to bother executing it, let’s just skip over it to the next line. With next.
And again
as expected because number is 5, we’re going to make it into “5th”.Once we’ve debugged enough, we can tell the program to stop waiting on us, and just continue.
This takes us back up to the pry where we typed 5.ordinalize, and even though we were debugging in the middle, it’s remembered that the output value is “5th”.Now, it wouldn’t be worth stepping through activesupport code unless we could tell someone we’d done it. And so pry provides a gist command that let’s you upload various things to gist.github.com
We want to upload a method, so we just gist –m, as usual gist –help would explain how to upload other things.
It uploads as a private gist, and then we’re done.
Just for completeness, here is the !!! Command. What that does is to run the exit function included in ruby..For various legacy reasons, just typing exit will only exit pry, so !!! Is a useful alternative.
Ok, so that was fourth and (you’ll be glad to know) final example.Perhaps the most useful topic covered in this section is pry’s builtin help. The chances are that if you want to know how to use pry, the help command knows. Almost all pry commands support –help as well, and if you find any that don’t please file a bug.I also went over pry-debugger, which is not a core part of pry, but an extension that merges pry with the debugger gem.The gist command is one that I often use, as it’s useful to be able to share fragments of ruby with other people; particularly when giving support on IRC, or complaining about some terrible code in hipchat. I only showed it’s –m version, but you can of course gist pry input with –I, or entire classes with –c, see –help for more.Pry has some commands to help you with gems, though you should be careful of using them when bundler is involved. Gem-install is particularly useful if you just want to have a play.Finally, !!! Is used to robustly exit pry regardless of your current state.
Ok, a few more slides before I’m done.
I didn’t have time to finish going through everything in pry-plus.I’d particular recommend pry-rescue, and not just because I wrote it. It automatically adds a binding.pry where-ever you have an unhandled exception, so it can make debugging considerably more efficient.Pry-stack_explorer allows you to move up and down the stack from a binding.pry, this means you can see what called the method you’re in, the local variables in them, everything.Pry-docmore is a new attempt to document ruby syntax in addition to methods. It hooks into the ? Command and includes documentation for things like module and defined? Which are not methods.Bond is a library originally written for ripl, another ruby-shell, that we’ve been adding support for to pry. It allowed tab-completion, not just of method names, but also parameters. For example if you are accessing a hash, it can complete the keys for you too.
I also haven’t mentioned at all configuration,Pry is designed to be highly tailorable. While we go to some effort to ensure that it works out of the box, there are always going to be disagreements between what we think makes sense and what you makes sense.A particularly interesting form of customization is adding new commands. These can be used to do anything from outputting the string test to step-through-debugging. There’s more documentation on the pry wiki, but I’d encourage people to play with these.
And there’s more and more and more.On the left is the output of help with pry-plus installed, on the right is a list of currently available pry plugins.I couldn’t possibly go through them all, but hopefully you’ll find a few that are useful to you.If you’re using a framework like rails or eventmachine you’ll find pry-rails and pry-em. If you’re using a framework for which there’s no pry plugin yet, please make one, it’s really easy .
If you need more information on pry, start with the home-page. It contains links to everwhere else.If you can’t find something, come and find us on IRC; we have a reasonably active channel so there will probably be someone awake who can help.Thanks for listening.