Prying Open The Black Box
This is a modal window.
The media could not be loaded, either because the server or network failed or because the format is not supported.
Formal Metadata
Title |
| |
Title of Series | ||
Part Number | 8 | |
Number of Parts | 94 | |
Author | ||
License | CC Attribution - ShareAlike 3.0 Unported: You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this | |
Identifiers | 10.5446/30691 (DOI) | |
Publisher | ||
Release Date | ||
Language |
Content Metadata
Subject Area | ||
Genre | ||
Abstract |
|
RailsConf 20158 / 94
1
4
7
8
9
10
11
13
14
16
17
19
21
24
25
29
30
33
34
35
36
37
39
40
42
47
48
49
50
51
53
54
55
58
59
61
62
64
65
66
67
68
70
71
77
79
81
82
85
86
88
92
94
00:00
Order (biology)Level (video gaming)Computer animation
01:06
Row (database)Ruby on RailsMetropolitan area networkGame theoryGoodness of fitWeb 2.0Table (information)Multiplication signInterior (topology)Real numberComputer programmingOffice suiteSign (mathematics)Core dumpNewsletterSpeech synthesisInternetworkingComputer animation
02:58
NewsletterMathematicsPairwise comparisonSparse matrixRight angleTwitterSpeech synthesisBitLoop (music)Self-organizationComputer animation
04:03
Process (computing)Client (computing)Complex (psychology)SoftwareMobile appHydraulic jumpMultiplication signCodeSoftware bugComputer animationMeeting/Interview
04:53
Figurate numberForcing (mathematics)NumberProcess (computing)CodeProjective planeComputer animation
05:32
Revision controlNumbering schemeBeta functionLatent heatBitSoftware bugSeries (mathematics)Multiplication signBranch (computer science)DigitizingPatch (Unix)TwitterData conversionError messageCodeMobile appCore dumpDefault (computer science)Point (geometry)Stability theoryGreatest elementComputer fileLine (geometry)Exception handlingCuboidOrder (biology)Visualization (computer graphics)Game controllerTrailWebsiteElectronic program guideElement (mathematics)Network topologyWordUsabilityRule of inferenceDatabase normalizationVelocityKey (cryptography)MereologyReal numberComputer animation
12:23
2 (number)Game controllerFrame problemDirection (geometry)Greatest elementSystem callStack (abstract data type)Exception handlingTrailPoint (geometry)Tracing (software)Cartesian coordinate systemBlock (periodic table)AuthorizationNetwork topologyShift operatorTouchscreenPulse (signal processing)Order (biology)Computer animation
14:41
Binary treeComputer fileGreatest elementLine (geometry)BitMultiplication signSlide ruleTouchscreenTracing (software)Error messageFitness functionFactory (trading post)Network topologyNeuroinformatikCodeMobile appComputer animation
16:33
Error messageCodeState of matterInformationPhysical systemRight angleException handlingPointer (computer programming)Ocean currentRootCausalityFactory (trading post)Statement (computer science)Point (geometry)Tracing (software)Computer animation
18:13
CodeMultiplication signVariable (mathematics)TouchscreenPRINCE2Observational studyComputer animation
18:52
BitObject (grammar)Instance (computer science)Hash functionCodeLibrary (computing)Point (geometry)GodStatement (computer science)InformationMultiplication signoutputVariable (mathematics)Exception handlingAnalytic continuationInsertion lossSelf-organizationFunction (mathematics)Complex (psychology)LoginComputer animation
20:07
Instance (computer science)Variable (mathematics)Computer fileSystem callLine (geometry)Graph coloringDebuggerStatement (computer science)Video game consoleSoftware bugComputer animation
20:37
NeuroinformatikMobile appComputer fileLibrary (computing)MathematicsFiber bundleText editorVariable (mathematics)Spring (hydrology)Formal languageRadical (chemistry)String (computer science)Multiplication signIntegrated development environmentRegular graphPhysical lawLine (geometry)NumberFrame problemWeb browserSystem callDebuggerTheoryRow (database)Bookmark (World Wide Web)Different (Kate Ryan album)Template (C++)Statement (computer science)Point (geometry)Interpreter (computing)Internationalization and localizationType theoryView (database)Open setMeta elementVideo game consoleComputer animation
24:02
Branch (computer science)Latent heatRepository (publishing)Fiber bundleDirectory serviceOpen setComputer fileVariable (mathematics)Function (mathematics)Matching (graph theory)outputForm (programming)Parameter (computer programming)Instance (computer science)CodePoint (geometry)Line (geometry)Library (computing)Letterpress printingLinear regressionSet (mathematics)Real numberServer (computing)NeuroinformatikFocus (optics)Exterior algebraCone penetration testMachine visionCASE <Informatik>Source code
26:38
Social classError messageSystem callNeuroinformatikType theoryFigurate numberEndliche ModelltheoriePointer (computer programming)View (database)Event horizonShift operatorDebuggerModule (mathematics)CodeData storage deviceLine (geometry)Computer animation
28:22
InformationDebuggerText editorProjective planeMultiplication signImpulse responseContext awarenessComputer animation
28:55
Social classSource codeString (computer science)Type theoryLine (geometry)NumberModule (mathematics)Default (computer science)Form (programming)Computer fileMetadataMereologyUniform resource locatorReal numberInformationSymbol tableHydraulic jumpEndliche ModelltheoriePolygon meshComputer animation
30:02
CodeLine (geometry)MathematicsImplementationPoint (geometry)Focus (optics)Branch (computer science)Multiplication signComputer animation
31:07
Mobile appMultiplication signElectronic program guideContext awarenessTraffic reportingTemplate (C++)Software bugRepository (publishing)Local ringSpring (hydrology)Row (database)Endliche ModelltheorieInverse elementSoftware testingCASE <Informatik>Library (computing)Maxima and minimaBoilerplate (text)CodeGroup actionLine (geometry)Touch typingComputer fontOptical disc driveOnline helpComputer fileCartesian coordinate systemTask (computing)MereologyRight anglePoint (geometry)Variable (mathematics)Charge carrierResultantGraphical user interfaceExtension (kinesiology)MIDIMathematicsCode refactoringView (database)FlagZoom lensBitInheritance (object-oriented programming)Computer animation
35:36
Multiplication signCodeMilitary baseRow (database)IntranetMobile appInternetworkingCore dumpOffice suiteComputer animation
Transcript: English(auto-generated)
00:12
Good morning. I'm very honored to be the person to kick off this conference for you all. You probably know from all the banners we have around downtown,
00:20
the theme of this year's conference is one industry, one stage. The last few years have been exceptionally great for our industry, and with all of us here at one stage, our industry is stronger than ever. So ladies and gentlemen, welcome to Clean 2015, the biggest trade show for the laundry and dry cleaning industry.
00:42
Nah, I'm just kidding. If you're here from the dry cleaning industry, unfortunately your conference actually ended two days ago. You should probably stick around anyway because as you will find out, our industry is also very obsessed with keeping things dry and clean.
01:00
All right, let's try this again. Welcome to 2015 defense industry. No, but really, welcome to RailsConf 2015, everyone. I'm Godfrey Shan. You can find me on the internet as jenkincode. I love coming to RailsConf. This is actually my fourth RailsConf,
01:20
and this is actually a conference with a lot of sentimental value for me personally. Four years ago, I was at RailsConf, my first tech conference ever on the RailsConf scholarship program. I came back the year after, went to the RailsConf office hour and had my request merged. Since then, I've been making regular contributions to Rails,
01:42
and shortly after RailsConf last year, I was accepted into the RailsConf core team. And a year later here, I'm speaking at RailsConf for the first time. So I would like to thank the community for supporting me and what I do. And if you were at Austin four years ago, I would like to personally thank you for chipping in for my ticket,
02:03
and I hope that was a worthwhile investment for you. And if you're here for the first time, or if you just recently picked up Rails, I would like to welcome you on behalf of the Ruby and the Rails community. I promise that you will have a good time here.
02:20
In fact, I had such a good time from RailsConf last year, I took one of the signs with me and traveled around the country with it. As you can see, we have been through a lot. We went to Hollywood, we went on the Conan show together, we sat at a pokey table, and we even made it to Canada after spending a few days on a big boat.
02:44
By the way, if you're thinking about this, please don't steal a RailsConf sign. At least not until the conference is over. Like I mentioned earlier, I'm on the Rails core team. I also work on a newsletter called This Week in Rails.
03:03
If you would like to keep up with the latest changes in Rails, this would be a pretty good way to do it. You can subscribe to your newsletter at that URL, or if you're interested in writing this newsletter, we should have a chat after this. I work for a small agency in Vancouver, Canada, called Brewhouse.
03:24
Yeah, speaking of Canada, if you have never been there, and if you would like to experience Canada for yourself, I wrote a gem for that. You can run a gem in Start Canada, and all you need to do is require Canada, and you'll be able to program like a Canadian.
03:42
If you want to actually experience Canada, though, we're organizing a Ruby conference in Vancouver later this year. The details are a little bit sparse right now, but if you're interested in coming, you can follow the Vancouver Ruby Twitter account to stay in the loop. All right, let's actually get on to the real talk.
04:04
Like many of you, I watched David's keynote last year, and I stopped calling myself an engineer, and I became a software writer instead. After carrying this job title around for a year, I realized that perhaps this didn't really fully capture what I do for work.
04:22
You see, when I work on a client's project, I get to work on some pretty complex Rails apps, and when I work on these complex Rails apps, I spend most of the time fixing things instead of making my code look pretty. So either I'm fixing an existing bug in the app, or perhaps I'm writing some new code,
04:40
and that new code somehow broke the app in unexpected ways, and I have to figure out why. So this is something that I take a lot of pride in, and you can see I take myself very seriously. But of course, in reality, what I actually do is pretty boring. All I do is I dig into the code,
05:01
I figure out what's wrong, and I fix it, rinse, and repeat. By the way, that's my coworker, Horse Can Code. If you see him around the conference, please do not be alarmed. As boring as my job is in reality, though, because I work on the Rails code base, so when I get dropped into these projects,
05:21
sometimes people think that I'm doing something really special for them. In fact, you've probably heard of this before, and you might even feel the same way personally about it. This Rails thing is basically just magic, and it might be cool for a while, but as soon as things stop working the way you expected,
05:43
magic becomes black magic, and black magic is obviously bad because you can't understand it, and the only way out is to hire a wizard to fix your code for you. One of the Rails core team members recently tweeted about this topic, so it turns out that there's actually no magic in Rails.
06:04
It has some same default and conventions, but all you need to do is actually just read the documentation, learn about these things yourself. One of the, this tweet sparked a conversation on Twitter, and one of the replies kind of summed it up pretty eloquently.
06:22
Perhaps what it really is is that Rails work a little bit too well out of the box. You can be really productive without actually spending a lot of time studying the documentation, so it almost feels like it can read your mind. And that's basically the key. The cost of learning Rails is not piled up front.
06:43
You do not need to spend a lot of time learning before you can start writing code. And with that lens, perhaps Rails is not really magic after all. Perhaps we're just treating it as a black box because we don't really understand what's inside the black box.
07:01
So today we're gonna pry open the black box together so you don't have to be afraid of it anymore. You've probably had this happen to you before. You wrote some code in your Rails app, and it blew up on you, and you have no idea why. The first thing you need to do is don't panic. Take a deep breath, it's not too bad.
07:22
You see, what actually happened here is that you wrote some code, and you tried to run the code, you expected the code to do something for you, and that didn't happen. Perhaps the code did something else, perhaps nothing happened, or perhaps you get an exception. But you see, you actually have some pretty solid advantages here.
07:42
Well, first of all, you wrote the code, so presumably you probably understand the code that you wrote. And because you wrote the code, you have access to the code. You can run it, you can modify it, you can do whatever you want with the code. And third, because you wrote the code,
08:01
you understand exactly what went wrong here. Now, you might not know why or how it went wrong yet, but what you do know is that you expected A and B happened, and that's pretty key. Finally, because there's no magic involved, your bug is not going anywhere, it's not going to magically disappear on you,
08:22
so you have time to fix it. So, with that in mind, we're going to look at some of the weapons you have to help you figure these things out when they do not work the way you expect. This is probably a little bit obvious, but as Jeffrey pointed out on Twitter,
08:41
you should probably start with checking the documentation. Surprisingly, not a lot of people know where to look for Rails documentation. This is not an API for Rails that spits out JSON. This is actually the official documentation. So, this is where you get the documentation for a latest stable release, and if you're using not the latest stable release,
09:03
that's not a problem. You can get the docs for any tagged version from the same website. And finally, if you're on the bleeding edge, if you're running Edge Rails, or if you're using a beta or an RC, you can go to edgeapi.rubyandrails.org, and you'll see the latest documentation for what is on master.
09:21
There's also this thing called Rails Guides, which is basically more detailed and hands-on articles about specific topics. And same thing, you can get a tagged version or you can get the Edge version as well. Another seemingly obvious thing is that you should probably be using the latest version of Rails because the problem you're having
09:40
might already have been fixed. But this is easier said than done because which version is the latest? How do I find out? If you're new to this, this might not be very obvious because the Rails version scheme might not work the way you expect. The first digit in the version there is the major version,
10:02
and the one in the middle is called the minor version, and the last thing is called the patch version. Now, the major-minor thing doesn't really matter so much because the first two digits together is called release series. And basically, for this purpose, as long as you stay on the same release series, it should be 100% compatible with what you're using,
10:23
only with more bug fixes applied. So in other words, you should try to stay on the latest patch version of the release series that you're using. When a bug's yet fixed for a particular version, they get backported into this thing called the stable branches for a particular release series.
10:43
So if you see that someone fixed a bug on GitHub, the pull request was merged, but there's no released patch version for that yet. You can change your gem file and point that to the corresponding stable branch, and you'll get the code instantly. Okay, so the easy stuff is out of the way.
11:01
You read the documentation, and you're using the latest version, and you're still having the same problem. So this is a good time to get serious and dig in and get to the bottom of the problem. The first and the most powerful weapon you have is called the stack trace. You've probably seen it before.
11:20
You get one of these things whenever you get an error in your app. And the first line is basically telling you what the error was, and the rest of them is the stack trace. The stack trace is basically a bedroom trail of your code. It's arranged in chronological order. The bottom is the oldest thing that it ran,
11:42
and the top is the most recent thing that was executed. There are apparently some talks of reversing this order in Ruby 2.3. I just heard that yesterday. Either way, one of them is the latest, one of them is the oldest, and it goes in that order.
12:03
Perhaps a visualization will make it easier to understand. What this stack trace is really telling you is that at some point, this create method in your post controller... Can you... Okay. Yeah, this create method in the post controller is executed.
12:21
I wonder if I can fix this real quick. Sorry. Give me half a second. Oh, well, I guess it's just gonna be that way. Anyway, so this is the post controller, and at some point, Rails executed a create method here, and that's the blue frame at the bottom of the screen,
12:43
and now the create method eventually calls to respond to block, and that's the purple frame on the stack trace, and that purple block eventually called post.save. Ah, it's fixed. Thank you. Whoever did that. It calls post.save,
13:00
which eventually calls the ensure author before save callback, which is the red thing on the stack trace, and finally, that calls this ensure permission method somewhere, and that's the yellow frame, and at this point, something... We don't know what yet, but something went wrong in here,
13:21
and an exception was raised. So really, the stack trace is really just a snapshot of the last breadcrumb trail that led to the point where things started going south. Sorry. I noticed a lantern. No offense intended.
13:41
But something is not right here. Well, first thing, someone must have called the post controller create method, right? Like, it cannot just, you know, call itself in thin air, and if you remember, we didn't really call the before create
14:01
or the before save callback directly. All we're calling is the .save method, and somehow that calls the ensure author, and it's not showing up in the stack trace, so I don't think Rails is being completely honest with us here, and yeah, come on, Rails. We need the full story here.
14:22
So it turns out that Rails is, in fact, hiding something from us here. Rails ships with this thing called the backtrace cleaner. By default, it will only show you the application stack trace. Sorry, it will only show you the application stack frames and the stack traces, and it will remove everything else,
14:41
and in fact, if you look at your initializer folder, you probably see one of these files, and it tells you how you can customize this backtrace cleaner, and at the bottom of there, there's a line that you can uncomment. If you do that, then Rails is going to give you the full stack trace, which now looks like this. This is exactly the same error,
15:01
and because it doesn't fit on the screen anymore, I adjusted the font size a little bit. I hope you can still read it. If you can, I made another slide that zooms in for you. I tried to highlight the four lines that we see in the original stack trace. As you can see, it is embedded in this sea
15:22
of very tall stack trace, but once we disabled the backtrace cleaner, we see everything that's actually going on here. As it turns out, this Rails thing, it's just Ruby code on your computer that's executing it somewhere, and what it's really doing is it's just trying really hard to stay out of your way.
15:42
This is pretty reasonable because when something went wrong, it's most likely in your app code, and by having the backtrace cleaner, it helps you focus on what is most likely to be wrong, but at the same time, if you suspect Rails is responsible for problems, then you really need to see everything to get the full picture and understand what's going wrong.
16:06
Okay, so now we have learned to read the stack traces. You might start to appreciate how useful they could be, but you only get stack traces when you have an error. What if you don't have an error? What if your code basically just silently failed, or perhaps your app somehow executed some code
16:23
and you have no idea how it got there? Well, you can just raise your own error. This might look very simple, but this is actually a very useful thing to do. For example, let's say you have no idea it got to the ensure permission method, and you can just raise an error within there,
16:41
and boom, you have a stack trace, and you know exactly what led to the execution of that code. Sometimes a stack trace just doesn't give you enough information to develop the problems, though. As we mentioned earlier, a stack trace is a snapshot of the state of the system right before it went, the exception happened.
17:04
In reality, a bunch of other things probably happened before that point, and the root cause of your problem can be anywhere within there. As an example, let's say you got a no method error, and you look at the stack trace, you understand why that's happening. You're trying to call current user dot name,
17:23
but because current user is nil, you end up calling nil dot name, and obviously that doesn't work. But looking at the stack trace here doesn't really help you, though, because you understand, yes, I'm getting a no method error because I'm trying to call dot name on nil,
17:41
but what you really want to know is why current user is nil to begin with, and current user is set in the before filter all the way at the left, so the stack trace does not capture any of that information for you, and that's not very helpful. So, to find out why current user is nil, we're gonna look at this really advanced debugging method called the put statement.
18:05
This is probably the first thing you learn when you learn Ruby, but it can actually be a pretty powerful weapon for debugging as well. This is how you use it. You go into the piece of code that you want to investigate, and you put some I got a thousand times.
18:22
Well, it doesn't actually have to be that, but basically the idea is you want to print something ridiculous onto the console so that you can possibly miss it, so whenever it runs this code, it prints some I got a thousand times in your console, and you will immediately spot it that it's happening, and with that you can print a lot of other stuff in there.
18:41
You can look at the variables you have access to. You can print anything you need on the screen to help you understand the problem. There are some other things that you can try to do here. For example, you can put scholar, which basically gets you a stack trace without actually throwing an exception, so your code is going to continue to run after that point,
19:01
but you still have a stack trace to tell you what exactly led to the execution of that code. There's also this thing called PP in the standard library, which stands for pretty print. It gives you a little bit more organized output of complex objects when you print them to your console, and Rails also gives you this thing called instance values,
19:21
which basically gives you a hash of all the instance variables on the current object, which is also pretty handy when you're debugging problems. The problem with the advanced debugging technique, other than the fact that it's going to pollute your logs with a lot of so many gods,
19:40
is that you need to know ahead of time exactly what you need to find out. So if you forgot to put statements for the session user ID variable, then you don't get that information in your log, and you have to basically change your code, add that back, rerun everything, and restart over.
20:00
Fortunately, there's a better way to do this, even more advanced debugging technique called a debugger, and if you're using Rails 4.2 or above, you'll notice that you already have a debugger in your gem file called by bug, and if you don't have one, you can just add that yourself.
20:22
So to use it, basically you just replace all the put statements with a by bug call, and when it reaches that line, you get something like this in your console. From here, you can execute arbitrary Ruby code, so you can check the callers, you can check instance variables, and so on. Besides the usual Ruby code, there are some by bug-specific commands that you can run.
20:42
I don't have time to get into that, but you can look up the documentation yourself. And finally, in Rails 4.2, you can also add this console helper in your ERB templates, which allows you to do similar things but in the browser.
21:00
All right, so, but we still have another problem. Even really advanced debugging technique of using a debugger does not do enough for us, because if you look at the stack trace, you will see at the first few frames that we actually want to investigate. They're all Rails code, so it's not like you can actually open up the file and add the debugger call to the method.
21:23
Or can we? Now, if you look very closely, you will see that there is a file name and a line number in each frame of the stack trace, and you might be wondering, hmm, perhaps these are just regular Ruby files sitting on my computer somewhere, so maybe if I open this file in my text editor
21:43
and change it and save it, perhaps that would just work, and you would be absolutely right. This is one of the nice things about working with interpret language like Ruby. Most of the things you're executing, they're just like plain text files sitting on your computer somewhere, and you can modify them without recompiling them,
22:02
relinking them, or whatever. So you can totally just open up your text editor, point it to this file, change it, and it will work. Or there's a more convenient way called bundle open. So because you're using Bundler for a Rails app anyway, you can just type bundle open the gem name, for example. Bundle open i18n is gonna bring up i18n gem
22:22
in your favorite text editor. And you can modify these files however you like. You can add put statements in there, or you can add debugger calls, or you can change stuff around to experiment with any theories that you might have. You can literally go crazy with this and not feel too bad about breaking things
22:41
because once you're done, you can run this command called gem pristine, and it will basically restore every changes that you, like all the damages you made to the gem so you don't have to feel too cautious about doing this. There's one thing to remember. Because all the gems are loaded once when you start your Rails app,
23:02
if you made any changes to the gems, Rails, or any other libraries, you would need to restart your Rails server. And if you're using Spring, you have to stop that as well. Which gets pretty annoying if you're gonna make a lot of changes to these files constantly. So you can temporarily disable Spring by setting the disableSpring environment variable,
23:24
and Spring will be disabled for that terminal session. Okay, so now if you have your computer view and you actually tried this in your app, and you tried running bundle open Rails, you would notice something pretty strange. Yes, your text editor opened. Yes, you're in the Rails gem, but the gem is empty.
23:43
So this is actually because Rails is divided into a few smaller libraries, and the Rails gem is actually just a meta gem that requires all of them. So some of these libraries you might be familiar with is ActiveRecord or ActiveSupport. But you don't really need to know what's the difference between each library
24:02
because your stack trace already tell you which library you're looking at. So in this case, it's pretty obvious that you need to do bundle open ActiveRecord. So that's bundle open. Right, so as an alternative, if you happen to have a Rails code locally on your computer,
24:26
instead of using bundle open, you can also modify your gem file and point it to a directory. And this directory could happen to be the Rails checkout that you have locally. And this is pretty cool because the Rails checkout that you have
24:41
is obviously a Git repository. So all the commands that you know about Git already works in there. You can stash stuff, you can reset stuff to clean after yourself. You can even check out specific branches or specific tags to, like if you suspect that the latest 4.2.1 has a regression, you can compare between 2.0 and 4.2.1
25:04
just simply by checking out the corresponding tags in the repository and restarting your Rails server. So that's pretty convenient. Okay, so going back to the stack trace. So let's say you finally figure out how to make this bundle open thing work
25:22
and you finally open the first file in the stack trace. It looks like this. If you have 20-20 vision, you can probably read it, but I don't. And this file is like 300 lines and I have no idea what it is about. What do you do? Well, first of all, take a deep breath. It's not that bad.
25:42
There are a lot of stuff going on in the file, but most of them doesn't actually matter to you. What you need to do is you need to stay laser focused on the problem you're working on and ignore everything else. Otherwise, you would just get overwhelmed like trying to learn all of Rails and the one hour debugging session that you have is not gonna work.
26:00
So to help you with that, you can basically ask yourself four questions. Whenever you're looking at a method, try to, as quickly as possible, find out what this method is supposed to do. What are the inputs to this method? Now, that could come in the form of the arguments in the method or it could be instance variables or it could be global variables,
26:21
but given the specific set of inputs, what is the expected output of this method? And finally, did the actual output match the expected outcome? So, let's follow the breadcrumbs and see what happens. We are in this method.
26:40
This is the method that the stack trace pointed us to. It's called find SDI class. Now, without knowing anything else about this method, you can quickly notice that this is probably the right place to look because in our stack trace, we're getting a subclass not found error and this line is raising as a class not found error,
27:02
so this is probably what is ultimately causing a problem. What is unclear, though, is why is this code raising this error? It just is an unconditional raise. Why is that? Ah, so it turns out that it's rescuing name error and then ignoring the origin name error and raise this subclass not found error.
27:21
Okay, so now the problem shifts into this because we know that the code rescued name error and so something from here must be throwing a name error for some reason. And because you learned to use the debugger, you can quickly check the value of this store full SDI class thing.
27:41
It might be a variable, it might be a method, but it doesn't really matter because it's going to return a Boolean or like a true or false thing. And based on that, you can quickly eliminate either one of these branches. So, let's say store full SDI class is false, so all you need to do is look at this compute type method and figure out why it's raising a name error.
28:05
But there's a problem though. We know that we need to look inside this method, but we don't know where this method is actually defined. Because Ruby allows you to mix in a lot of modules into classes, the answer to this question might not be immediately obvious to you.
28:22
The first thing you might try to do is open up your text editor and do a project-wide search, but this doesn't usually go very well in Rails because we override the same method like 50 times and call super and num, so you're probably gonna find a lot of definitions for the same method. But fortunately, because Ruby knows about
28:41
where this method is, otherwise it can't call it, right? So, we can actually just ask Ruby for this information. To do this, you add a debugger like we always do, and it has to be in the same context that calls a method. But once you're in there, you can call the method helper, which is a method that takes the name of the method
29:03
you want to check in the form of symbol, and it returns some pretty useful metadata. So, for example, you can ask for the source location, which is a string that tells you which file defined this method and which line number defined this method.
29:20
Or you can ask for the owner, which is the module or the class that contains this method that you're looking at. If you add the method source gem to your gem file, which, by the way, will be a part of Rails 5, it will be in the default gem file. If you have this gem, then you can even ask
29:41
for the source of this method. So, if you type method compute type dot source, it will literally print out the method definition in your debugger for you. You can even get the comments that goes before the method, so perhaps that would help you understand what the method is intended to do.
30:02
So, with that information, let's say we got to this method somehow. It looks like a lot again, but once again, we need to stay laser focused, so we quickly eliminated one of the branches, and now we're left with this. Unfortunately, after reading the code a few times,
30:21
you still have no idea why the code is written in this specific way. In particular, you might think that something is fishy in the three lines that I pointed out, and unfortunately, there are not a lot of comments around it to help you understand what the code is supposed to do. What do you do then? Well, at some point in time,
30:41
some human being wrote this code presumably with a clear purpose in mind. Usually, we don't just put code in Rails for reasons. So, one thing you can do is you can probably go back in time, look at the initial implementation, and go through the incremental changes that it's been through,
31:00
and perhaps that would help you understand the current implementation and the rationale behind it. And this is exactly what git lock will tell you. It will tell you all the commits on this file. You can get the same thing on GitHub by using the history view. But what is even cooler is git blame. So, git blame basically tells you who touched the last,
31:21
who is the person that touched each line in the file last. And more importantly, it tells you the commit that touches that line. And with the SHA, you can do a git show, and it will show you the commit, and it gives you the full context of the change.
31:41
And you can obviously do this on GitHub as well. There's a blame button that does the same thing. But unfortunately, this commit turns out to be a refactoring commit that basically just moves a few things around, so it doesn't really explain anything about the purpose of the method. So, what you actually want to do is you want to see the second most recent commit
32:01
that touched the line that you're interested in. And to do that, you can run git blame with the SHA and the caret after it. The caret is very important, so I would like to highlight that. And if you can't see it from the back, I will zoom in for you and zoom in a little bit more. So yes, this is how you tell git blame
32:21
to start from the parent of the SHA you have given. And that basically achieves the result of you want to blame the second most recent commit that touched that line. And if you prefer to do this on GitHub, I wrote a Chrome extension to make it easier. Unfortunately, there's a bug in there I need to fix.
32:42
But hopefully, it will be fixed by the time you have a chance to try this at home. Or if you are interested in working on this, you can compare with me later at the conference. Okay, so after all the work, you have established a pretty good understanding of the problem. But with everything else that's going on in your app, you have so many gems, you have so many libraries,
33:01
it could be so many things, too many variables, what do you do? Naturally, one of the solutions is to generate a new Rails app and see if you can reproduce a problem there. And if you can, then it's probably a Rails bug. And if you cannot, then it's probably some other gems that you use in your app. You might not know this,
33:20
but if you do specify the def flag when you generate a new Rails app, it will set it up to point to your local checkout and a few other nice things like a disabled spring and stuff. So basically, it's a more convenient way for you to do some of the stuff that I mentioned earlier. Sometimes you don't really need
33:41
a full-blown Rails app to reproduce a problem. For example, if you're having an active record issue, all you need to do is set up a model, connect to the database, and then you can test that problem without being in the full context of a Rails app. For that, we have these bug report templates on the Rails repository.
34:01
It's in the guides folder, and then there's the bug report template folder. They're basically minimum boilerplate code required to run the test case against the Rails libraries, and there's one for active record, one for action pack, and we just recently added a generic template for you to test everything else.
34:22
So with your problem reproducing a fresh application in an isolated test case, it's very easy for others to help you. So you can probably, if you can consistently reproduce your problem, it makes it very easy for others to investigate and maybe fix the problem for you. So being able to reproduce a problem on a fresh Rail apps
34:43
or in one of those bug report templates and attach that to your issue would greatly increase your odds of getting helped. Or with everything you've learned from this talk, you probably know enough to nail down
35:01
where exactly the problem is happening, and you can probably just fix it yourself, and you can send a pull request for that. At this point, you might be like, wow, I already know all these stuff. I did not learn anything new from this talk. I already use all these things to talk about in my own app, and you are 100% right.
35:20
You probably know these things already, and you're probably debugging your applications every day at work, and that's kind of the point. This Rails thing, it turns out, is just Ruby, and when things doesn't work in Ruby, well, it just quickly turned into Ruby. And it turns out that Rails is just another big
35:41
legacy code base, which is probably not that different from all the other code bases that you have to work with. So you probably know how to deal with this already. And if you would like to practice any of these things or if you would like a refund because you tried these
36:00
on your app and it doesn't work, we are hosting a Rails core community office hour on Wednesday during the happy hour at the Heroku booth, so you can bring your app and you can come talk to us, and then we can probably help you with that. Or you should probably do this if you haven't already. Eileen, one of the Rails contributors,
36:20
is running a lab later this afternoon on contributing to Rails, and she is going to cover a lot of the things that I didn't have time to go into. So if you haven't already, sign up for the lab. It's this afternoon. That's all I have prepared for you today. Once again, you can find me on the internet as changing code.
36:41
And thank you very much, and enjoy the rest of the conference.