-
JOEL TURNBULL: Thanks for coming.
-
My name is Joel Turnbull.
-
I'm a developer for Gaslight in Cincinnatti,
Ohio.
-
I also head up and coordinate a blog over
there,
-
in case anybody ever wants to talk about that.
-
But today, I'm here to talk about debugger
driven
-
development with Pry. Most Rubyists I know
don't use
-
debuggers. Rubyists I know, when faced with
a problem,
-
would prefer to ponder code than pop open
a
-
debugger and poke around.
-
This is crazy to me. I've always thought it
-
was, because to me, trying to solve a problem
-
by pondering code is like trying to find your
-
keys in the dark, when you're holding a flashlight,
-
but you're consciously deciding not to use
it.
-
So why is this? I, I used to think
-
it might be about egos or culture or something
-
like that, but really it's pretty simple.
I think
-
we've had a lack of really good tools up
-
to this point. But ultimately, my talk isn't
about
-
using debuggers in a traditional sense to
fix software,
-
but using debuggers as a tool in your workflow
-
to build software.
-
And, so why do I think we can do
-
this right now? I feel like we finally have
-
a tool that we can use to explore this
-
debugger driven, debugger driven workflow.
And that tool is
-
Pry.
-
Can I get a show of hands of who
-
uses Pry? Awesome. Like, everybody. All right.
Cool. So
-
I'm talking about debugger driven development
with Pry. Conrad
-
Erwin gave a talk not even like six months
-
ago called REPL Driven Development with Pry.
I swear
-
to god I had no idea.
-
But, and both are accurate, I think. You know,
-
but I think both terms kind of undersell what
-
the power of Pry is. So here's my favorite
-
definition. Pry is an IRB alternative and
runtime developer
-
console. So if we take the first part of
-
that and we think about Pry as an IRB
-
alternative, you know, anything that you can
do with,
-
with, both, both are REPLs, right. And, and
a
-
debugger is a REPL, too. Anything you can
do
-
in Ruby, you can do in IRB. Anything you
-
can do in IRB, you can do in Pry.
-
What makes both of them powerful, is they
both
-
leverage this idea of runtime. And, to me,
runtime
-
is all about immersion. It's about being immersed
in
-
a live system, where you can play with code
-
and you can look at your objects and, and
-
all that kind of thing. You can validate your
-
implementations. Everything you need to do.
And it's like,
-
looking for your keys with a flashlight.
-
So, given that Pry and IRB are both REPLs
-
and they both have this idea of runtime, why
-
should you use Pry instead of IRB? It's got
-
a couple vital workflow features right out
of the
-
box. Syntax highlighting and tab completion.
Both super handy.
-
But, what I want to talk about today is
-
some of the bigger, game-changing features
of Pry. The
-
first one is enhanced introspection. Here's
our friend again.
-
Introspection is the ability to, of, of a
language,
-
where you can ask a language questions about
itself.
-
And it's built into Ruby, and that's awesome.
-
If you've ever asked a class what method you
-
can call on it, or you've asked an instance
-
what class it is, you're doing introspection.
-
What if you want to go deeper? Like, what
-
if you want to know what the class methods
-
are versus the instance methods? You know,
what if
-
you want to know what methods are inherited,
and
-
from where? What if you want to know what
-
state an instance holds onto during its life
cycle?
-
You can answer all these questions with plain
Ruby
-
and IRB. But the problem is, is that, it's,
-
the, the amount of effort involved is non-trivial.
I
-
would classify it as daunting.
-
So. Given that. You know. I would, I would
-
classify this as DRTFM. This is what I, this
-
is what I point to. I mean, this is
-
the workflow that I like.
-
I like to take the things out of the
-
box. I like to get a feel for what
-
the pieces are. I like to play around with
-
them. I like to try to put it together
-
without reading the manual, and if I get stuck,
-
then I read the manual, right.
-
The second really game-changing feature of
Pry, to me,
-
is extendability through plugins. And the
best way that
-
I can show this is to just demo some
-
of my favorites for you.
-
So, I'm gonna show you a Rails app. Instead
-
of calling it in a normal way, like rails
-
s, I'm gonna call it like this. Under the
-
umbrella of Pry rescue. And I'll show you
why
-
in a minute.
-
But here we are. This is an app I've
-
been working on late, late nights, you know.
Please
-
don't steal this. This is a bowling score
count,
-
tracker, right. You can push any number after
you
-
bowl and it will record what you, what, how
-
many pins you knocked down, right.
-
So, the first thing I'm gonna show you about
-
Pry, for those who aren't necessarily familiar,
is how
-
you invoke a runtime at any point in your
-
application, where you're running Ruby, right.
-
Here, I've inserted a couple binding dot prys.
One
-
into my controller action and one into my
template.
-
On the lower left we have our model. OK,
-
so let's rerun it with that in mind.
-
Let's go back to our running server, and we'll
-
see that we've halted our execution here,
and we've
-
been dropped into a run time. And we can
-
do things in here like look around. We can
-
play lines of code. Let's play the line that
-
sets the bowling game. And then we can look
-
again.
-
When we exit from this, we've returned from
our
-
controller. We're starting to render our template,
and we've
-
hit our next binding dot pry. You can put
-
binding dot prys inside your erb tags, right.
-
Same drill. We can look at bowling games.
We
-
can, we can step into our next, our, our,
-
our implementations of our methods. Here we've
stepped into
-
the frames method of our bowling game model.
-
Same drill. We can look around here. We can
-
look at ourself. We can go to the next,
-
or we can continue.
-
So, you can see how handy that would be
-
if things aren't necessarily blowing up, but,
you know,
-
something's not quite right, either. So what
if things
-
do blow up, though? Right.
-
So, here I am. I'm gonna, I'm gonna spark
-
an exception here by bullet, trying to bowl
the
-
next ball of my next frame. I'm gonna bowl
-
a big nine. I'm gonna come back here and
-
we've been dropped into a runtime, because
an exception
-
was thrown. That's what being under the watchful
eye
-
of Pry rescue is gonna do for us within
-
this context here.
-
So, some interesting, interesting things we
can do here.
-
We can call the show-stack command of the
Pry
-
stack explorer plugin. And we're seeing the
whole stack
-
here. this is like caller, but it's alive,
right.
-
We can move up the stack. We can move
-
up the stack nine frames. We can move down
-
the stack. We can take a look at the
-
state of any object here at any level of
-
our stack trace.
-
We can look at our stack again just to
-
see where we're at. We're on frame ten. But
-
this is a big hairy kind of Rails stack
-
trace, and we're not getting a whole lot of
-
value out of that right now.
-
So let's call the cd-cause command of Pry
rescue.
-
And see if it can track down what caused
-
this problem in the first place.
-
There we go. This looks more familiar, right.
Here
-
we are in our template. And I will guess
-
that on line thirteen we have a problem with
-
frame one. And that's true. So we just need
-
to add a little bit of a guard in
-
here, and say, you know, if we have pins
-
on frame one, let's render that. Otherwise
let's just
-
render a dash.
-
And we get feedback that that's going, that's
what's
-
gonna happen, right. We know that this is
a
-
working implementation.
-
So let's copy our history. This is another
plugin
-
called Pry clipboard. That's gonna copy that
implementation into
-
my clipboard. I'm gonna edit a file where
the
-
last exception was raised. It drops me right
where
-
I need to be. I'm gonna paste in that
-
implementation, drop back in, and I'm gonna
ask Pry
-
rescue to try it again.
-
And we're back. And we've got our dash. So,
-
and we can continue to bowl, right. That's
legit,
-
right. A five and a six. OK, cool.
-
So, what do we do here? We used binding
-
dot pry to invoke a runtime anywhere in our
-
app where we're doing Ruby code. We used the
-
pry-debugger gem to give us our step, next,
and
-
continue functionality that we expect out
of our debugging
-
tools. We used pry-rescue and ran our Rails
app
-
under the umbrella of pry-rescue to drop us
into
-
a runtime when things go wrong, so that we
-
can poke around. We used the pry-stack_explorer
gem to
-
navigate the stack and explore state at any
level.
-
A few commands we saw were cd-cause in pry-rescue
-
that took us to the, the root of our
-
problem. We used play and we used copy-history
to
-
not mess around with, you know, copying things
with
-
our mouse and pasting them into our REPL,
which
-
can be a pain. We used the edit command
-
with the e flag to take us to the
-
file where the exception occurred so that
we could
-
fix it. And then we used pry-rescue, try-again,
which
-
under this, under the context of Rails, just
replayed
-
our request. We didn't have to reload our,
our
-
page, or do any of that nonsense. Reload the
-
whole environment or anything like that, right.
So it
-
was fast.
-
So, the, that's, that's great, and having
demoed Pry
-
in a debugger context, you know, I can show
-
some of those things. But, really, what I
find
-
interesting is this idea of Pry as a runtime
-
developer console, right.
-
So there's some really awspect- really awesome
aspects of
-
Ruby, right. It's introspective, which we've
talked about a
-
little bit and we'll talk about more. And
it's
-
a dynamic and it's reflective, which means,
you know,
-
we don't have to compile it and we can
-
change things on the fly in its runtime.
-
And I think we, we take advantage of these
-
things, you know, a lot in the code that
-
we write, whether we're doing metaprogramming
or monkeypatching or,
-
or anything like that. But we, we haven't
really
-
taken advantage of, of these things in the
tools
-
and in our workflow yet.
-
So, when I talk about workflow and our problems
-
with our workflow, I see big problems with
the
-
traditional workflow in, in Ruby development
that I, that
-
I see. Right, I mean. By that I mean
-
we write some code in an editor. We save
-
it. We hop over to a terminal or we
-
pop over to a webpage and reload it and
-
run it to see if it worked and, if
-
it worked, we go back and continue on. If
-
it didn't, we fix it, we save. We go
-
back. We reload it, rerun it. Rinse, repeat,
right?
-
What, what are, what problems do I see with
-
this? First of all, it's disruptive and it's
distracting
-
to keep switching back and forth, right. Some
amount
-
of context-switching is always gonna be imminent,
right. But
-
any effort you can make to reduce that is
-
just gonna be a huge win for your flow,
-
you know, and your focus.
-
The second problem I see with that is it's
-
just guess work. We just write some code.
Oh,
-
yeah, I think it's gonna work. We save it.
-
We go over. We run it to see if
-
it works. We're just taking shots in the dark,
-
you know. You can ask this guy.
-
Taking shots with a flashlight is much more
accurate.
-
And recommended, apparently. So do that.
-
And, to me, it just seems backwards, right.
We,
-
we're like solidifying and codifying our code
into our
-
code base just in an attempt to see if
-
it works. It should be the opposite. Our code
-
base, it should be the, the record of code
-
that we've, we've already validated, right.
And I, I
-
mean these things are just kind of things
that
-
we accept and, and we, we take for granted,
-
right.
-
But I mean, I think other languages have,
have
-
been more effective and intentional about
integrating this idea
-
of a runtime into the, their workflow, you
know.
-
And blurring this line between static and
running code.
-
Clojure comes to mind, right.
-
But, we've talked about the awesome aspects
of Ruby,
-
and there's really nothing that restricts
or limits us
-
from doing the same, right. I mean, I think
-
the Ruby language is, the Ruby language enables
it,
-
you know. It's just that up to this point,
-
we really haven't had the tools to do so.
-
So, we talked about these workflow problems.
How does
-
Pry solve these workflow problems, right?
I see that,
-
you know, the introspection and the documentation
and the
-
source code browsing, which we'll see in a
minute,
-
that's, that's baked into Pry, gives us ninety
percent
-
of the information that we need to write code
-
right now, you know, in most cases.
-
It has a runtime that you can throw your
-
code against and validate it and get feedback
on
-
whether it, whether it works or not, immediately.
And
-
it's smart about editing. You don't have to
think
-
about what file you need to open. Pry usually
-
knows what file you want to edit and usually
-
knows exactly where you want to edit it. Which
-
is really nice.
-
So, when I talk about this idea of runtime
-
development, I'm really talking about being
immersed in this,
-
in this environment that, you know, loves
us and
-
can give us feedback, and, and is alive, right.
-
So we want to spend the majority of our
-
development time there, and we want our editor
to
-
just be an after thought. And that's just
a
-
place where we just push working code when
it's
-
done, right.
-
So, let me demo to you a little bit
-
about how I see that working, right.
-
So. Our mission is to write an empty class
-
definition, OK. This is just a script. No
Rails
-
involved here or anything. But given a class
like
-
name like BowlingGame, we want to create a
file,
-
bowling_game dot rb, and write a class definition
to
-
it, like class BowlingGame empty space end.
Right, and
-
I've created a little skeleton here of, of
how
-
I think that might work, right.
-
We're gonna, we're gonna read in a string
from
-
the command line, we're gonna pass that string
into
-
a method called file_name_for_class and get
a file name.
-
We're gonna pass that string into a method
called
-
class_definition for class and get a class
definition, and
-
then we're gonna create that class by writing
that
-
class definition to that file. Right.
-
So let's step out here and let's just run
-
that. So, we get an expected error, right.
We
-
haven't implemented anything called file_name_for_class,
yet. So we could
-
jump into our editor and start coding and
all
-
that, but why don't we see what this is
-
like.
-
Why don't we use Pry rescue and leverage that
-
exception to drop us into a runtime and start
-
this runtime development process. So we do
that. We
-
get the same error, but the difference is,
we're
-
inside of a runtime now, OK. So, the first
-
problem is pretty easy. We know that we need
-
to define file_name_for_class. And we do so,
right.
-
The difference is in here, I'm gonna raise,
in
-
the implementation of this class, and drop
back out.
-
And I'll show you why. When we ask Pry
-
to try again, we get in here. We're right
-
where we need to be to define the implementa-
-
working implementation of this class. Although,
I already know
-
that I have forgotten to pass in the BowlingGame
-
string, like I always do.
-
OK. Now we have everything we need. So we
-
have something like BowlingGame, right, and
we're looking for
-
something like bowling_game dot rb, OK. So
I'm just
-
gonna preview my favorite Pry command of all
time
-
here. ls.
-
When I call ls, and give it the class
-
or the object I'm working with, I immediately
know
-
I'm working with a string and I'm seeing all
-
of the methods that are available to me on
-
that string. And when I say all of the
-
methods, I don't mean all of them. Notice
that
-
the object methods are not in here. And, you
-
know that if you've ever used IRB to get
-
the method, you always do, thing dot method
minus
-
object dot methods blah, blah, blah.
-
The, that's just noise, right, in most cases.
So
-
the default is just to leave that out. The
-
developers of Pry have thought of that, right.
So
-
we can try to class downcase, which gets us
-
so close, but yet so far away. We don't
-
really know where to put that underscore.
-
But, as Ruby devs, Rails devs, we know we
-
have things like ActiveSupport that can help
us out
-
with that.
-
So we include that, and now when we ls
-
our class, we've got some extra stuff in here,
-
right. Demodulalize, deconstantize, right.
That kind of stuff. And
-
if it, that's hard to see, we can just
-
ls ActiveSupport::Inflector itself and see
what's available to us
-
there, right.
-
So we need an und, we needed an underscore.
-
I see a method called underscore there. Tab
completion
-
is nice. All right. So now we're getting a
-
lot closer. All we need to do is stick
-
on our file exception, and I think we're done,
-
right.
-
So that, there's our filename. So let's copy
that.
-
Let's drop back into our file. Right here,
exactly
-
where we need to put the implementation, let's
put
-
it in there. And let's save it and continue
-
on. OK, I know, I'm not gonna continue through
-
this whole thing, in the interest of time,
but
-
I do want to, to implement this last method
-
inside of the create_class, so I can talk
a
-
little bit more about what I love about introspection,
-
right.
-
Let's just reflect on what we did there, though,
-
with the workflow, OK. So we used, the, we
-
used pry-rescue to leverage the power, you
know, to
-
leverage that exception, to pop us into a
runtime,
-
and we used the runtime of the debugger not
-
to fix code, but to drive our development
process,
-
right.
-
So. We're in here. We've raised inside of
our
-
create_class method. We try again. We've got
our file
-
name, and we've got our class definition.
And we
-
have this file class, right. And, and I know
-
about this file class, and I know this is
-
exactly what I need to get the job done.
-
But, I mean, this is exactly what I, what
-
happened to me. I don't really remember exactly
what
-
I need to do here, OK.
-
So I can pop out to StackOverflow or I
-
can pop out to, to Ruby-docs or something
and
-
take a look. Or I can just ls file,
-
right here. And just take a minute to look
-
at this, and think about all of the low-level
-
Ruby instrospection acrobatics you would have
to go through
-
to get this brain dump of information right
here.
-
We've got all of the methods that you can
-
call on instances of file. We've got all the
-
methods you can call on the file class. We've
-
got all of the methods that file inherits,
and,
-
from its superclass, and we know what that
superclass
-
is. IO.
-
We also know all the constants involved and
if
-
there was state involved in class or instance
variables.
-
We would see that here as well. So, all
-
of a sudden, I'm informed about, about everything
I
-
need to know about this class, and I have
-
a pretty good idea, just from a, from a
-
moment's notice, of how I can use it, or
-
what I can do to play around with it.
-
So let's. I see the right method. And I
-
don't really want to write anything or mess
with
-
anything right now, so I'm just gonna look
at
-
the documentation for it. OK. It opens the
file.
-
It optimally seeks to the given offset. Writes
a
-
string, then returns the length written. Write
ensures that
-
the files close before returning. This sounds
like what
-
I want.
-
I page down. I see some examples there. Great.
-
I'm ready to go.
-
Alternatively, I can do the same and call
show-source,
-
OK. Which isn't doing a lot for me here,
-
but when I'm in my, my own code base,
-
this is what I lean on more often, right.
-
So, let's get our bearings again.
-
And let's give it a try, right. File.write(file_name.class_definition).
OK.
-
Something happened. It seemed to work, right.
How do
-
I know? Really easy to shell out in Pry.
-
You get really nice output. Exactly what you
would
-
expect, which is, I can't say the same for
-
IRB in that, in that case.
-
I have this thing called bowling_game in there.
Let's
-
take a look at it. That looks correct to
-
me. So let's just do that again. I'm gonna
-
copy the history again. And then I'm gonna
remove
-
bowling_game, just to make sure that my script
is
-
doing what it promises, right. Oops.
-
And it's not there anymore. So let's go back.
-
Let's put in that, let's put in that implementation.
-
And drop back in. Let's ask Pry to try
-
again. No more exceptions. Do we have our
bowling_game?
-
We do.
-
OK. So, what happened there, right? We used
the
-
debugger and the runtime as, as, as a tool
-
for driving our development process and build
our implementation.
-
Not just to fix software, right.
-
We validated our implementation before codifying
it, and we
-
reversed this traditional workflow that I've
got so many
-
problems with. We explored and we informed
ourselves about
-
how to, how to use our classes without context
-
switching. Right, we stayed focused in one
tool. And
-
then we didn't have to reload our, our libraries
-
and our environment every time we wanted to
run
-
code, so it was fast.
-
So, and, you know. We're in the testing track
-
here, so I should probably talk about testing
a
-
little bit. And, that might have felt a little
-
bit like TDD to you. I mean, it does
-
to me, right. As, as practitioners of TDD,
you
-
know, I may not, I'm, I'm, I love TDD.
-
I think most, many Rubyists do.
-
But I mean, what I love about it most
-
is it keeps me focused and, and, and, having
-
a test suite allows me to aggressively refactor
my
-
code, you know, and have the confidence to
do
-
that. You know, and I'd rather do that upfront
-
than after the fact, right. But, as practitioners
of
-
TDD, you know, we've learned to love failure,
you
-
know.
-
TDD is all about making something fail, then
writing
-
the code to make it pass. When we have
-
bugs, we want to exercise that exact piece
of
-
code that's giving us the error and get that
-
error, you know, before we then go, cause
we
-
know we're about to do something cool and
fix
-
it, right.
-
So, we love to see red. And so a,
-
a practice that's, that's centered around
failure is naturally
-
suited to a debugging tool, right. I mean,
that's
-
what a debugging tool does. It's meant to
handle
-
failures, catch failures, and then give you
the tools
-
you need and enable you to fix them as
-
quickly as you can. And we've seen how awesome,
-
you know, a debugger Pry can be.
-
And, so, the promise of this talk is that
-
I'm going to, you know, deliver a, a, a
-
Pry-enabled TDD workflow. But before I do
that, I
-
mean, I mentioned that, you know, I've had
a,
-
kind of specific experience that made me a
believer
-
that this workflow even happens. I mean, I've
actually
-
done this before. I'm not creating this, right.
-
And, and that specific experience was this.
Does anybody
-
know what this is? Smalltalk. Yeah. This is
a
-
screenshot of a Farrow Smalltalk IDE, right.
And I
-
spent about a year or so in the 2000s
-
writing a web application in the C-side framework
in
-
Smalltalk for a company in New York City with,
-
with a team of guys.
-
And, really delving into object-oriented programming,
and learning so
-
much about it, I really learned to love this,
-
right. But what first, what first struck me
when
-
I saw Pry and I saw the ls command
-
was it reminded me of this, right. Right here,
-
we are looking at a ZnClient class in a
-
Zinc HTTP package. We see the class definition
right
-
there at the bottom, with all of the instance
-
variables that this class makes use of listed
out.
-
On the right hand side, we see all the
-
methods that we can call on this, on a,
-
on an instance of class, and we can click
-
on any of those to see the source code
-
of that method. I mean, that's all, that's
all
-
you need, as far as I'm concerned. I mean,
-
that gets you ninety percent of the way there
-
almost every, like, almost every time, right.
-
So, I wanted to, I wanted to demo, like
-
a, a Smalltalk TDD workflow, cause that's
the other
-
really cool thing about Smalltalk and different
thing about
-
Smalltalk is that it really, like, enables
this awesome
-
TDD workflow. And I don't think I'm gonna
have
-
the time to do that unfortunately.
-
But the TL;DR is this, basically. OK. So if
-
I write a test, and I try to exercise
-
a class that doesn't exist, like BowlingGame
here, Smalltalk's,
-
when I save this, Smalltalk's gonna say, that
doesn't
-
exist. Do you wanna, what do you want to
-
do?
-
And the first option there is define new class.
-
You just click it and it does it, right.
-
When I try to call a method on that
-
class that doesn't exist, Smalltalk asks me
if I
-
want to implement that method, and when I
say
-
yes, it drops me into a debugger, right. A
-
runtime, where I have everything available
I need to
-
create the implementation of that class, and
I can
-
expect all the things I need to do so.
-
Right, I'm not in a static code editor here.
-
This is like, living system, right. So I can
-
do so. Just want to return zero. And when
-
I save, my tests pass. So that's. That's,
that's
-
the idea, right. And, and it, it's small,
but,
-
you know, small changes in your user interface,
you
-
know, can really turn, like a daunting experience
into
-
a really motivating flow, right.
-
It doesn't take much.
-
So, when I talk about, you know, this power
-
of Pry and, and we've talked about some of
-
the plugins and how powerful they are and
how,
-
you know, Pry is so easy to extend, you
-
know, even I can do it. And, and so,
-
I've kind of gotten the ball rolling.
-
I pushed a little code up to GitHub. It
-
defines a new command called define-it in
Pry. Right
-
now, it's just a PryRC, and you can define
-
Pry commands in your PryRC or you can do
-
gems or whatever, and that's, that's where
I want
-
to move it.
-
But, this is my attempt to kind of get
-
this workflow going in, in Ruby, right. So,
all
-
right. So here it is. Here's my PryRC. I'm
-
creating a command called define-it, and then
I'm implementing
-
- every Pry command implements this method
called process,
-
and that is what is going to happen when
-
you call the command from within the Pry REPL,
-
right.
-
And so I'm kind of using this idea that
-
we demoed in the last demo of, when I
-
hit a name error, I just want to automatically
-
generate an empty class definition and move
on. What
-
it will also do is when I hit a
-
NoMethodError, it's gonna generate an empty
method definition and
-
put you right in there where you need to
-
be to implement it, right.
-
So let's take a look. So, once again. Oh,
-
let me just show you this real quick, though.
-
So here is a spec and a set of
-
tests that exercise this BowlingGame class,
right. The first
-
test just verifies that BowlingGame is a thing.
The
-
second test says if I ask a new BowlingGame
-
for its score, it should return zero. The
third
-
test says, if I bowl a four then the
-
game's score should reflect that.
-
And the last test says, if I bowl twice,
-
you know, the, the score should reflect that,
that
-
sum. So, when I run rSpec under pry-rescue,
pry-rescue,
-
you know, it does different things in different
contexts,
-
right. So just like before, pry-rescue's gonna
break on
-
unhandled exceptions, just like it always
has done, but
-
in the context of rSpec, it's also gonna break
-
on assertion failures, all right. So you can
poke
-
around and get those fixed.
-
So, here we are. We. We've got our first
-
exception, right. It's the name error. Uninitialized
constant BowlingGame.
-
So let's define it.
-
All right. Didn't see it, but it did it.
-
Next. Believe me.
-
All right. So next. Next, we've got our next
-
exception here right. Undefined method 'score'
for BowlingGame. Our
-
NoMethodError. So let's define-it. You guys
didn't believe me,
-
but there it is. All right. There we go.
-
We're in our empty method. Let's TDD, right.
We
-
just need to make the test pass so we
-
return zero out of there. Ask pry-rescue to
try
-
again. We got another exception here. NoMethodError:
undefined method
-
'bowl' for BowlingGame.
-
So, let's define-it. Now I feel like we're
gonna
-
need to keep track of a little state, so
-
let's. We want to make that the fixnum.
-
We want to return @score out of here now,
-
instead. And let's initialize @score to be
zero when
-
you create a new BowlingGame. Let's save that
and
-
let's try again.
-
All right. That worked. We're in our last
test
-
here, and we've hit our first assertion error,
right.
-
It expected nine and it got five, cause we're
-
not doing any of the, the totaling yet. So
-
let's, this is another way you can call edit.
-
You can just ask it to edit the class,
-
and it'll know what file to drop into. So
-
I feel like we're gonna want to keep track
-
of our scores now. So let's just push those
-
fixnums on a scores array. Let's get our score
-
by reducing those values. That's how you keep
score
-
in bowling, right. You just add everything
up. All
-
right. Cool.
-
And let's, let's initialize it with an array
with
-
initial value of zero as well. Let's try again.
-
Something's wrong there. There it is.
-
All right. Four examples, zero failures. rSpec
thought we
-
didn't fail at all, you know. It's pretty
cool.
-
So. So what happened there? All right. I mean,
-
basically, you know, we. We, again, we used
Pry
-
to drive our development process. We used
our own
-
Pry plugin there to kind of make that a
-
little bit easier, and within one runtime,
we fixed
-
all of our assertions, exercised our class
and implemented
-
the whole solution, right.
-
No reloading, no nothing like that.
-
So, in conclusion, embrace your runtime and
all things.
-
Don't read the effing manual.
-
Use a kickass flashlight.
-
If you're fixing software, use a debugger.
If you're
-
building software, use a debugger. And when
you use
-
a debugger, use Pry.
-
Thank you very much.