 One for coming into my talk, I'm gonna start off first with a shout out to my son. So my family's watching the live stream. And my 16 month old son, his favorite new word is flowers. So let's him look, flowers. So I have this weird habit of starring GitHub repositories and never looking at the source code. I have like 270 something stars. And I did this with Rails and I even went a step further with Rails. I cloned the Rails repository and never looked at the source code for a long time. And then finally, when I did, this is a little bit of how, when I started perusing the source code, how I was comprehending it. I had these little aha moments and they boost my learning the source code. But I had those over time. And so what I wanna do today is I wanna share with you some of the aha moments I had so that you can get up and running in the Rails source code a lot quicker than I did. There are a few side effects of perusing the Rails source code. Going through thousands of lines of Ruby code, you're gonna learn probably some new methods that you may not have used before. You're gonna learn a lot about optimizations in Ruby. And you might even be introduced to metaprogramming if you've never done metaprogramming. You get to see how Rails uses metaprogramming. And then the source repository for Rails is over 10 years old and it spans over tens of thousands of commits. And so it serves as a good playground for learning some new get methods and also some options for get methods you already know. Just digging through information, you're gonna learn a lot about get. And then there's one thing that I heard a lot when I was getting into Rails is there's a lot of magic in Rails. And it is really easy to get up and running very quickly in Rails with very little code. But it turns out there's no magic in Rails. There's just a really good public API and it does a lot of the heavy lifting for users so that users can get up and running without hitting these implementation hurdles. So to start off, you need a copy of the Rails source and you can get that off of GitHub. And then I recommend setting it up for development. And the Rails guides has a good step-by-step process on how to get it set up for development. There's a couple of dependencies that you need and this allows you to run the test for the Rails source code. When you get the source code, this is a top-level view of the repository. So you have these folders for all the different modules. And then you have some documentation like the license contributing readme as well as the gem files and the gem spec. Now the Rails modules are independent and so they each have their own folder and they each are their own gem. And the reason that the Rails team does this is because they want them to be interchangeable. So if you wanna use a different ORM than ActiveRecord in Rails, you can. And that also means you can take ActiveRecord outside of Rails and use it in another project. And I've done this a couple of times. And then to run through the different modules, I'm just gonna go through a typical Rails request. So you start your Rails app with Rails server and then a request comes in. And that request is gonna be sent to the routes and the routes is gonna parse it and it's gonna send it to a controller. The controller is going to grab usually a model and it's also gonna grab a view and it's gonna go back up to the routes and then you're gonna get a response. Now the routes and the controller, those are both a part of action dispatch or action, sorry, action pack. And action pack is actually made up of two separate modules. There's action dispatch and action controller and the routes is action dispatch, the controller is action controller. And then the models are usually ActiveRecord or ActiveModel if you don't wanna do a database interaction or if you wanna do ActiveRecord even more. And then you view is action view and the initialization of Rails and the command line interface that's handled by rail ties. And then sprinkled throughout the app is ActiveSupport and ActiveSupport it's gonna extend the Ruby standard library classes as well as some add some other helpers. And then there's three other modules that consider these additional modules. So ActionMailer, if you wanted to include mail delivery into your app, so for user registration and stuff like that, you can do that. ActiveJob, that's gonna handle background tasks and jobs. And then ActionCable, that's a newer module and ActionCable is really cool. It integrates web sockets to Rails and so it allows for a lot of real time application uses. So if you wanna add user stories to any of your apps as well as real time chat, you can. So also in the top level directory are the guides and this is guides.rubyonrails.org and you have there the source code for that. So when you clone the Rails repository, you have a copy of the guides with you and if you wanna make changes to it, you can just make changes in here and submit a pull request, pretty cool. And that's actually how I first started in Rails. I found a typo in the guides and so I submitted pull request for that and it got added and I was like, hey, I'm a committer. Okay, so we're gonna look at a module and I'm gonna use ActiveRecord but the things I'm gonna be showing you, you can do them from module to module. So the first level of the module, it's gonna have the lib directory. That's where the code is going to lie and the tests are gonna be there as well as the readme and I think the readme is a good place to start. If you're familiar with the module, you're probably gonna find at least one or two takeaways from it and if you're not familiar with the module, it's a good overview of the module. And then the gem spec I also think is good to look at because you get to see the dependencies of the module. So here you see ActiveRecord depends on active support and active model and then another gem called Errol and Errol does a lot of the SQL generation within ActiveRecord. If we see the into the lib directory, you're usually gonna see a folder with the module name. You're going to see a Rails folder and the Rails folder is going to handle a lot of the initialization or sorry, no. It's gonna handle a lot of the generators. So if you're using ActiveRecord within Rails, this is gonna be where Rails generate model, where Rails generate migrations gonna live. And then ActiveRecord.rb, this is a file with the module name. That's where a lot of the initialization is gonna be configured. So if you've heard terms like eager loading and auto loading, that's where that's, the majority of that's handled. So if we see the into the active record, or yeah, the module directory, this is where you're gonna see the classes for ActiveRecord. And the documentation in these files, that's what makes up the documentation for the API website. And so just like what you have, you have the guides with you, you also have the API website by reading through the different files. Good place. When you are looking through here, you're probably gonna see key terms that you may recognize, like attributes and relation and schema. And then you're probably gonna see ones that you don't recognize, like attribute mutation tracker and persistence stuff. And the ones that you do recognize, that's a good place to start because you're gonna be familiar with some of the things within those. And you get to see how they're implemented. So I did this with find by query method. And find by and where, they're pretty similar. You're gonna be passing in attributes as the parameters. So you wanna find a post by the name title. And they're similar except that find by is gonna be returning one object. And where is gonna be returning an ActiveRecord relation collection of objects. And so I wanted to see how similar the code is. So if we look at find by, you see that find by actually uses where, and then it just takes the first item in that. That's pretty cool. It's sort of a syntactic sugar for where. Now, it's cool to see that, but it's not as simple as saying, I wanna see what ActiveRecord creates doing. So go look in the create file. It doesn't really work that way. You have to do some digging and find out where these methods live. And one of my first aha moments was learning about Ruby's introspection methods. I learned about a lot of these from Aaron Patterson's blog called I'm a Puts Debugger. And he goes over different ways that he debugs with just simple Ruby methods. Ruby has these methods called introspection methods. And they allow you to call them on a class or even a method and learn about that class or method. One that I use very often is method.sourcelocation. And so you can just call, here we have a class called post. We're gonna call method. And then the method we wanna look at, we put it as either a string or as a symbol and then called.sourcelocation. And that's gonna return us where that lives within the Rails repository. And then we can go look at that. And we see here that create creates a new object, saves it, and then it returns it. And that's a pretty straightforward version of this. But sometimes it's not so straightforward with source location. So for instance, save, we're gonna call posts and news and save is an instance method, a method save source location. And it's gonna return a suppressor. What's interesting is if you look at the API website, you're gonna see that it lives in persistence. So why is source location giving us a different version than the API website? Well, it turns out that save has to do some, you know, sort of housekeeping before it actually gets to the core of the method. So I'm gonna sort of run you through what save does. Here's suppressor where it said that save lives with source location. And what suppressor does is if you're trying to suppress these kinds of records, saying you don't want them created, it's just gonna return true. We're not doing that, so it's gonna super. And that supers into a method in transactions. And what this is gonna do is it's gonna save the state of that record. And if something happens within, where something fails within that, it will just roll back the original state of that when you called save. That's gonna super into a class called dirty. And dirty tracks changes, let's see, smiling. It tracks changes to the object since you've interacted with the database. And it's not gonna do anything here, so we're just gonna follow that along to validations. And this is where validations are performed. We don't have any validations here, but if one of them failed, it would return false. Here, it's gonna super. And that's gonna take us to persistence. Now, like I said, we could have looked at the API website and seen this right here, what save is actually doing the core of save. But you have this knowledge gap between what source location is giving you and what the API website has. And I think you're better off by filling that knowledge gap. Now, there is another method called super method that you can call. So after a method save, you call super method and you see here it returns us transactions. But because we have so many supers here, I tend to use, in situations like this, I tend to use Bybug. And Bybug's really cool. It allows you to traverse code as it's executing. And to do this, you need a script to put Bybug in. And the Rails source actually has some templates for creating a script. It's just a minimal version of these modules so that you can play around with them and explore and do some assertions. And so we're gonna look at the Active Record Master script. And what it starts off doing is it, first requires bundler inline. And then it creates an inline gem file. And what this is gonna do if you don't have a copy of these gems on your computer, it's gonna grab them for you. And here you see that we're actually gonna be using the GitHub version. So when you do GitHub like that, it's just gonna grab the master version off of GitHub. And we're also doing with Errol. The reason we're using Errol's master is because usually if you're using Rails master, they're using an unreleased version of Errol since they maintain it as well. And so you need that. And then you also have the gem for the database that you're using and you can change that to whichever one you wanna use. And since we're using the clone version on our computer, you can change that from GitHub to path and you can make little changes to it and it'll, you can see those changes being when you're running through it. Then we're gonna do some Active Record configuration. We're gonna establish a connection to the database. We're going to use a logger. We're gonna define the schema. And here I'm just creating a table called post and I am adding a title attribute. I think it's good to have an attribute in there so you can see how those attributes are passed through. And then we have the, we're just calling the class post. And then it has a mini test set up here. So if you're asserting stuff, you wanna see if something's true or false, you can do that. Usually I just take that out because I consider these exploration scripts. So I'm not gonna assert anything. I'm just gonna do my code inline. And what's cool is if you want to use something similar to a Rails console, you can also, in these scripts, you can require pry. And then you call binding.pry and that will give you an interactive console and you can treat it just as a typical Rails console. Now to use buy bug, we need to require buy bug. And then you call buy bug right before the line that you're wanting to explore. And I'm just gonna run through some of the cool methods you can use with buy bug. So here we're at post.create. And if I wanna step into create, I just type s and that'll take me to the first line in create. Then if I wanna skip over something, I wanna skip over this if statement. I can type in and that stands for next. And I'll take me to the first line in the else statement. Then if I wanna see the local variables, so here we have attributes and a block, either of those are passed. And var local will give me the local variables. Since here we see that title equals hello. Now running through these scripts when you're playing around with it and you're looking at the variables, I've run into what I call hyzen bugs, debugging uncertainty principle. And that's, you know, it can be troubling to know simultaneously the exact value and correct execution of a variable. So what that means is I've seen this happen a lot in active records query methods. I'm exploring in a query method like where? And I wanna see this variable that keeps getting passed through. And so I look at that and the query methods in active record, they do what's called lazy querying. So it's not gonna call the actual query to the database until you really need it. And that's what allows you to chain these query methods like where.order, blah, blah, blah. But when I look at the variable, it's saying hey, I need that. And so it's gonna call that SQL query. And a lot of the internals of the query methods depend on that query not being called. So it's actually gonna take you on a different path than it would had had you not looked at that variable. Now as you're going through here, you're going to see, you're going through the classes you know. And as you're going through those, you're gonna be introduced to the classes you don't know. And this gives you a little context to those so you can start digging into those. And the more you do this, the more you're gonna be acquainted to a larger amount of Rails. Now one thing I like to do, if there is a line of code that I don't understand, what I like to do is I like to change it or delete it and just get rid of it. And after I do that, I like to run the test for the module. And I don't like to see what broke. And I was doing this a couple of months ago with a method called define method attribute equals. And what this method does is it's gonna use metaprogramming in ActiveRecord to create for all the different attributes, it's gonna create the title equals or description equals methods. And just to run through it, what it does is it takes the name, here we passed a name as title, and it's gonna unpack it into hexadecimal. So it's gonna unpack that into the 479 string. And then it's gonna save that as the safe name. Then it does a little bit of metaprogramming and there's this module called generated attribute methods that all these methods live on. And it's gonna create a new method on that. And the way it does that is it first creates a method called underscore underscore temp underscore underscore safe name. So it's gonna have that 479. Then it aliases that to the method name that we're looking for. So it's gonna alias it to title equals. Then it undefines the underscore underscore temp underscore underscore method. And I thought this is weird. Feels like it's going through some extra steps here. Why create a temp method and then alias that and then get rid of it right away. So I decided to change it to what I thought it should be and just run the tests. So I got rid of the temp method just named it name equals. Then we don't need the alias method and we don't need the undefined method. So we can get rid of those. And that just leaves us with name equals. Ran the tests and sure enough some failed. And this is an example of one of them. You see it's trying to define a method called a dollar sign b. And in Ruby there's a limitation to that. We can't use dollar signs in method names. So it turns out what Rails is doing here is it's bypassing that Ruby limitation on method names. The way it does is it first creates a method that it knows is gonna be safe. Hence the safe name. And then it's gonna alias it to what we need it to be and then it's gonna undefine that temp method because we're not gonna use that. And I thought this is a really cool and sort of sneaky way of getting the functionality that we need out of Rails. And so I was interested in how they came up with this. Did this exist very early on in Rails or when did they decide that this should be a part of Rails? And has this code evolved over time? And so my second aha moment was learning how to use get effectively to find the information about or find the story about the code. Because the commits within the Rails repository, they tell a story. They tell you how the repository or the source code has changed over time. And you can follow the get commit messages and hopefully it's a good message and it's explaining exactly why they did this. And so I'm gonna take you on sort of a journey. It wasn't a straightforward journey of finding the original commit for this code but it was some cool get methods that I learned along the way. So I first started off with just get blame and that's gonna return the latest commit hash for each line of code within the file. That returns 2016 by Reuda. And I thought that was a little weird. That's pretty new to have just be added to Rails. And it turns out what it found was an indentation change. And so in 2016, the Rails team, they implemented a Rubikop style guidelines in the Rails source code. And this was part of them cleaning up the source code to make it match those style guidelines. And we don't wanna see white space changes. And so there's an option with get blame that you can pass called dash W and it's ignore white space changes. And that gives us a commit by Aaron Patterson in 2013. But it turns out that's still not the original commit for this. This code's a little different. This code actually existed before. And then Aaron changed it and then he had to revert it back. And get blame is only gonna give you the latest commit. But we wanna see all those. And so I found that get log works a little better with this. Get log has an option that's dash capital S and you can pass in a search string. And what it's gonna do is it's gonna return you all the commits that have that search string, that match that search string in the changes of the commits. And so that's gonna return several commits here. Now I like to clean this up a little so it's easier for me to read. I like to pass in a couple of options. One is dash dash patch and dash dash patch or dash P for short. It shows you the actual changes that happen in these commits. So you can see instead of just the commit message you're gonna see the actual changes. And then dash dash pickax dash all that actually comes along with dash dash patch. And if you don't pass in that option it's only gonna return you the files and those commits that match that search string. So it's only gonna return us right. But you wanna see all the changes that happen to commit because usually those have context of the actual change. And so we're gonna pass it here and you can probably see that that first one is the read file. And then dash dash reverse changes it from being newest commits to oldest commits. Instead we're gonna do oldest to newest. And I feel like this tells a little better story. You get to see it from where it first existed and followed along. And that commit wasn't actually the commit that created the functionality. It was actually the one that created this code. But from here what I can do is I can take the commit hash from there. I can check out the repository from there or from the commit before that. And I can follow that along until I find the commit that added the functionality we're looking for. I did this and I found a commit from 2011. And along the way I learned the original purpose of the code. I learned some optimizations that they made to it and also some bugs that they addressed in the code. There is another option or another feature that's similar to what I just did called reblaming. And then two places I know that have reblaming are VimFugitive and GitHub. VimFugitive is a VIM plugin that sort of wraps Git and it provides some really cool Git functionality within VIM so you don't have to leave VIM you can use it on the command line. I'm gonna show you what reblaming is on GitHub. So here we have the blame view for that write file and you'll see down here you'll see a little icon and it says view blame prior to this change. And from what I can gather, what this does is it's gonna check out the repository to what it looked like before this commit was added and then it's gonna blame it from there. And it's really cool from there you can just keep clicking that link until you find what you're looking for. And Git has a lot of cool features like this. Git sort of serves as an extension to our GitHub sort of serves as an extension to Git whereas Git provides you with a commit message. GitHub provides you with a whole conversation. For example, when I was upgrading one of my Rails apps from Rails 4 to Rails 5 I kept hitting this deprecation in my controllers that said redirect to back was deprecated for redirect back with fallback location. I wanted to see why this change was implemented. So I ran Git log dash s with some of the deprecation string and it returned me a commit from Derek Pryor. Derek Pryor you may have heard his talk earlier today. He, the reason he made this change is he said that when no refer is available on that redirect to back can lead to an application error. And so he provides a great commit message. It was a very long commit message. I wanna see what was also on GitHub what extra information I could find. And so I took the commit hash for his commit and I searched by it and I found his pull request. And in his pull request he has a conversation with the maintainers and other contributors to Rails. And they're asking him like real life scenarios where is this actually gonna happen? And he provides some real life scenarios and he also provides a link to a security site called OWASP about unsafe redirect practices. This information for me, I'd never heard of OWASP but I didn't know about unsafe redirect practices. This information was very valuable to me and a lot of pull requests and issues have this kind of information. So Derek, he works for Thoughtbot. He's a Rails consultant there and he looks at all these different Rails apps. That's his day-to-day job. At my day-to-day job I work on two, maybe three Rails apps. And so I'm not introduced to all these different use cases for Rails, these very unique ways of doing things. Maybe not always great but they're unique. And I sort of think about it in this way. There's this tree and I'm using another tree analogy today. There's this tree and at the trunk of it you have the general Rails knowledge. This is the stuff that every typical Rails app does. It's the active record creates and stuff. And the Rails source has this handled or at least testing-wise. You're not gonna see a whole lot of bugs here but as you're dealing with a larger Rails app as those Rails apps grow or when you're dealing with ones that are doing very particular things you're gonna go up these branches and you're gonna see little issues that most people don't experience. And I'm not seeing that in my day-to-day job and if I'm expecting that it's gonna take a long time before I see all these different ways of using Rails or even the issues within Rails. But with the issues on GitHub I can look at an issue and I can see one with the reproduction script, one of them that we looked at earlier. And this reproduction script is saying there's a bug right here and it's like a little map and I can take that reproduction script, I can run it on my own machine, on my own source of Rails and I can see where that lives. And maybe if it's a feature that I'm not used to I'm getting to see how someone else is using it and I can learn a little bit more about it. I can follow this branch down and add it to my knowledge of Rails. Rails also serves as a forecast to changes and additions being made to it. Eileen was just talking here about how she added system testing and it took her six months from when the pull request was created to when it was actually merged. And this is how a typical pull request goes. So pull request is received. Usually there's a discussion between the maintainers and contributors and maybe we really like this but I think you should make this little change here or I like the idea of it but I think you need to do it in a completely different way. And so more commits may be added to this pull request and it may just build up to several commits. And you can follow along those commits, you can see sort of the thinking process behind the person that's submitted this pull request. And then if they accept it, those commits may be rebased into one and if you haven't been introduced to rebasing, what it does is it takes all your commits and it's going to just turn them into one commit. And so we're gonna lose a lot of that contextual information from following along all those commits. And it'll finally be merged into master. And when it's merged into master, this is where Git starts. So if you were just looking at Git, this is where you first are introduced to this code but with GitHub you're seeing all this other contextual information and you're learning from it. Now, I have really enjoyed reading through the issues and pull requests on Rails because there's all these little nuggets of knowledge in these pull requests. But the problem with it is when I first started doing this, it's not always easy to follow along with what the issues are and what the pull requests are especially if you're not familiar with what it's talking about. And so I read through many issues and pull requests with glazed eyes but over time I would find little nuggets of knowledge, little ah-has that I learned something new about Rails. And as I did this more and more, I found more and more takeaways more frequently. Now, just as we looked at what's familiar to us in the code base, you can also look at what's familiar to you in GitHub by using the labels. And so each module has a label. So you see act to record, action patch, or yeah, action pack. And you can, if you only wanna see issues or pull requests from action pack, you can go look at that label and it'll pull up the issues and pull requests related to that. Then this is more of just a cool thing that I found going through the GitHub. They mark the milestones for the different releases for Rails. So you can see, you go to the milestones, you see like 5.2, 5.1, 0.0, and you get to see what they're working on and what they wanna get accomplished before they release that version of Rails. So just with Ileans, it was six months sitting in GitHub before it was finally became something and I was watching the repository and I saw when she submitted the pull request. And so I knew six months before that they were trying to add system testing to Rails. It's very cool. It's sort of insider knowledge. Now this is my final and probably my biggest aha moment. I decided I wanna start trying to tackle issues or at least get into the nitty-gritty of issues. And so what I recommend is when you start getting comfortable with the issues and maybe seeing some in areas that you're comfortable with in Rails, find an issue that has a reproduction script and maybe even attached PR, and the maintainers won't let me say that, but, look at this issue and don't look at the pull request yet. Take that script, run it on your machine, see if it fails, but fails, see if you can find the issue and if you find the issue, see if you can make the test pass, change the code and see if you can make that reproduction script pass. Then once you do that, look at that PR and see what you did versus what the person that submitted that PR did. I bet you you're gonna have taken different ways of making that PR or making that reproduction script pass. Now if you can't solve the issue, which I'm just gonna tell you, it can be hard. I looked at lots of issues, try to dig in and I was okay, I don't know what's going on here, I'm not even gonna try to fix it. That's fine, the time you have spent in the code and the code that you've been introduced to, you'll understand it a little more and then you can go look at that pull request and I bet you'll have a little more contextual information to understand what's going on in the pull request and you'll be like, oh, okay, I remember seeing that. Oh, that's actually pretty simple. Now I'm gonna leave you with some resources that really helped me as I started Peruse in the Rails source code. I found these really handy. First one is the blog by Aaron Patterson, I'm a puts debugger, talked about that earlier. He has a lot of great debugging methods that he uses. Then Eileen gave a talk in 2015 on contributing to Rails and she goes into a lot of really in-depth things like get bisacked and it's an hour and 20 minutes and so she has a little more time to go into more of the details on contributing to Rails. I definitely recommend checking that out and then check out her pull request for system tests. Her pull request has 37 commits on it. They didn't rebase them when it was merged and so you can start from when she first submitted that pull request and you can follow along and see her thinking process behind adding this feature. It's really cool. And then check out, if you're looking for a good podcast, check out the bike shed. So Derek Pryor, he's one of the co-hosts and Sean Griffin, he maintains ActiveRecord. They both tackle Rails issues and Rails features and a lot of the episodes, either Sean saying hey or Derek saying hey Sean, I have a question about Rails and they go into something with Rails or Sean says I'm working on this ticket or I'm working on this feature in Rails and it's sort of like sitting in at a developer lunch and like he said, I live in the middle of nowhere and so I don't get to sit in on these kinds of conversations every day so it's cool. Every Thursday I get to listen to their podcast. Then another good book is Crafting Rails for Applications. It's written by Jose Valin. He was a Rails member. He starts off the book by talking about how to create a renderer plugin within Rails and as he's doing that, he goes into how rendering works within Rails. So that's just the first chapter. It's a really good book. And then last, Xavier Noria, he's another one of the core members. He gave a talk last year about everything that Rails does in the boot process. So I definitely recommend checking that out. And then if you need to find the slides, they're on my website, AlexKitchens.net slash RailsConf. Thank you for coming to listen to my talk. I'll be out here taking questions. I'm not sure if I've gone over time or how I'm doing so if you wanna ask me any questions or talk to me I'll be down in the audience. Thank you. I'll see you guys next time.