Breaking Down the Barrier
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 |
| |
Subtitle |
| |
Title of Series | ||
Part Number | 17 | |
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/30644 (DOI) | |
Publisher | ||
Release Date | ||
Language |
Content Metadata
Subject Area | ||
Genre | ||
Abstract |
|
00:00
WindowLatent heatSource codeIntegrated development environmentSoftware testingFocus (optics)Confidence intervalProgrammer (hardware)Installation artTwitterLocal ringCache (computing)Revision controlSoftware repositoryComputer animation
01:40
Artificial lifeInstallation artRevision controlMultiplicationComputer fileDatabaseSource codeIntegrated development environmentSlide ruleOpen setSoftware bugOpen sourceBranch (computer science)Multiplication signCodeFiber bundleTraverse (surveying)Local ringBitCore dumpVirtual machineSoftware repositoryScripting languageMultilaterationWindowCoefficient of determinationModal logicGame theoryLibrary (computing)Software developerBookmark (World Wide Web)Food energyFile formatData managementComputer animation
05:59
Scripting languageSource codeMultiplication signSoftware testingSoftware bugContinuous integrationEntire functionCodeGroup actionAdaptive behaviorOnline helpGame controllerMereologyClosed setDatabasePoint (geometry)Information securityOpen setSoftware developerOpen sourceSuite (music)Traffic reportingEmailSingle-precision floating-point formatExploit (computer security)Touch typingNumberReflection (mathematics)Buffer overflowComputer fileEndliche ModelltheorieRevision control2 (number)Stack (abstract data type)Core dumpProjective planeDirection (geometry)Integrated development environmentSubsetCASE <Informatik>Noise (electronics)Error messageFiber bundleSoftware repositoryInstallation artDirectory serviceAcoustic shadowSlide ruleMathematicsCorrespondence (mathematics)1 (number)Template (C++)Different (Kate Ryan album)Disk read-and-write headModal logicElectronic mailing listComputer animation
15:53
Local ringEndliche ModelltheorieRevision controlScripting languageSoftware testingDatabaseIntegrated development environmentSemiconductor memorySoftware developerTable (information)Computer fileVariable (mathematics)Connected spaceIn-Memory-DatenbankMaxima and minimaAuthenticationModal logicCartesian coordinate systemSubject indexingData structure
18:19
Integrated development environmentFiber bundleMathematicsMessage passingScripting languageSingle-precision floating-point formatRevision controlPoint (geometry)CodeSweep line algorithmValidity (statistics)Branch (computer science)Directory serviceComputer filePlanningCode refactoringSoftware bugRule of inferenceComputer animation
20:14
Inclusion mapCodeMathematicsMessage passingTraffic reportingRepository (publishing)EmailCASE <Informatik>Software developerCommitment schemePatch (Unix)1 (number)Programmer (hardware)Multiplication signOnline helpComputer animationLecture/Conference
23:18
CodeMilitary baseLine (geometry)MathematicsServer (computing)Multiplication signMessage passingQueue (abstract data type)Revision controlOpen setBenchmarkIP addressScripting languageNumberIterationStandard deviationComputer animationLecture/Conference
24:58
Traffic reportingStandard deviationBefehlsprozessorBenchmarkNumberDivisorScripting languageSampling (statistics)Semiconductor memoryMultiplication signIP addressDifferent (Kate Ryan album)MathematicsMeasurementCodePhysical systemPairwise comparisonComputer animation
26:32
Set (mathematics)Multiplication signSoftware testingEndliche ModelltheorieDifferent (Kate Ryan album)MathematicsTable (information)IP addressSoftware bugPower (physics)Linear regressionCartesian coordinate systemScripting languageGreatest elementMessage passingSuite (music)Directory serviceCodeBenchmarkProof theoryComputer animationLecture/Conference
28:58
CodeElectronic signatureCartesian coordinate systemCycle (graph theory)Social classMetaprogrammierungSoftware bugUniform resource locatorGroup actionSource codeFunction (mathematics)Computer fileLine (geometry)NumberComputer animationMeeting/Interview
30:17
Computer fileSlide ruleNeuroinformatikScripting languageDirectory serviceSource codeUniform resource locatorSystem callLine (geometry)Computer animation
31:58
Fiber bundleComputer fileLine (geometry)Scripting languageNumberCache (computing)Slide ruleUniform resource locatorProxy serverAssociative propertyCodeSource codeComputer animation
33:15
Cursor (computers)Maxima and minimaCodeWindowInstallation artSubject indexingTwitterRevision controlDirectory serviceSoftware repositoryUniform resource locatorVariable (mathematics)Point (geometry)IdentifiabilityComputer animation
34:55
Directory serviceMilitary baseSubject indexingType theoryCartesian coordinate systemGoogol1 (number)CodeCursor (computers)NumberElectronic mailing listMatching (graph theory)Computer fileGame controllerDifferent (Kate Ryan album)Line (geometry)Right anglePoisson-KlammerSocial classAssociative propertyKey (cryptography)Inheritance (object-oriented programming)Scripting languageModule (mathematics)Function (mathematics)Point (geometry)Kernel (computing)Stack (abstract data type)Computer animationLecture/ConferenceSource code
38:38
Computer fileDirectory serviceBookmark (World Wide Web)Scripting languageText editorOpen setPoint (geometry)CodeSystem callComputer animation
39:49
Scripting languageFiber bundleSource codeLambda calculusUniform resource locatorAttribute grammarLine (geometry)Multiplication signSoftware developerComputer animation
41:27
Point (geometry)Tracing (software)Functional (mathematics)Kernel (computing)System callBlock (periodic table)Parameter (computer programming)Software frameworkAssociative propertyCodeFunction (mathematics)Type theoryLine (geometry)Event horizonAttribute grammarResultantComputer animationSource code
43:05
Text editorOpen setScripting languagePoint (geometry)Bookmark (World Wide Web)Social classAttribute grammarFiber bundleAvatar (2009 film)Parameter (computer programming)Tracing (software)System callComputer animation
45:33
Scripting languageFiber bundleAttribute grammarLine (geometry)NumberCodeRight angleSoftware bugBlogPoint (geometry)Traverse (surveying)Power (physics)Revision controlRootDirectory serviceSoftware testingBranch (computer science)Software repositoryProjective planeRemote procedure callLinear regressionType theoryMathematicsGoodness of fitNP-hardWritingTraffic reportingInteractive televisionBookmark (World Wide Web)MereologyUniform resource locatorTerm (mathematics)Computer animation
52:38
Traffic reportingSoftware bugTemplate (C++)Connected spaceDatabaseSocial classSoftware testingRevision controlSelectivity (electronic)Software repositoryMessage passingBit4 (number)Type theoryArtificial lifeError messageData managementSheaf (mathematics)Scripting languageRadical (chemistry)Branch (computer science)Computer animation
55:09
Point (geometry)ExistenceSheaf (mathematics)Branch (computer science)Goodness of fitComputer-assisted translationScripting languageDisk read-and-write headCodeGreatest elementRevision controlCommitment schemeSoftware repositoryComputer animationLecture/Conference
59:52
MathematicsDisk read-and-write headMereologyBookmark (World Wide Web)Multiplication signSheaf (mathematics)Branch (computer science)Commitment schemeComputer fileText editorNumberMessage passingComputer animation
01:01:30
Commitment schemeSheaf (mathematics)MathematicsComputer fileComputer animationLecture/Conference
01:02:39
MereologyMathematicsObject-oriented programmingBranch (computer science)Revision controlRemote procedure callLevel (video gaming)Disk read-and-write headInteractive televisionMultiplication signState of matterNP-hardComputer animation
01:05:33
Multiplication signMessage passingDefault (computer science)Analytic continuationComputer animation
01:06:38
Interactive televisionRadical (chemistry)Forcing (mathematics)Software repositoryMathematicsWordCommitment schemeComputer animation
01:07:52
Message passingAnalytic continuationInteractive televisionAuthorizationComputer animationSource code
01:09:41
Computer animation
01:10:48
Message passingSoftware repositoryRepository (publishing)Branch (computer science)BitMultiplication signSoftware developerOpen setForcing (mathematics)Bookmark (World Wide Web)Data miningWeightComputer animation
01:12:52
Bookmark (World Wide Web)Electronic mailing listGroup actionType theoryMathematicsDisk read-and-write headNumberMultiplication signBranch (computer science)CASE <Informatik>Commitment schemeComputer animationSource code
01:14:41
Revision controlMereologyState of matterPoint (geometry)Branch (computer science)Disk read-and-write headNumberData mining
01:16:55
Insertion lossLinear regressionOpen setSoftware testingCodeMobile appStandard deviationMultiplication signSheaf (mathematics)Electronic program guideTemplate (C++)Electric generatorProcess (computing)Web 2.0Video game consoleGoodness of fitProjective planeFocus (optics)Source codeGroup actionFront and back endsView (database)Software bugSpacetimeOpen sourceMathematicsError messageConfidence intervalMereologyAssociative propertyCASE <Informatik>Computer animationLecture/Conference
01:20:51
Slide ruleSoftware repositoryScripting languageBlogComputer animation
Transcript: English(auto-generated)
00:01
Who here has Rails source actually installed and tests running? Okay, everyone who doesn't,
00:22
who isn't sitting next to someone who does, you should sit next to somebody who does. So we're not gonna use Rails a lot, but if you wanna see how the tests look when they run, you should sit next to somebody who does have it installed, but. Or you can run it later when you do get that installed. Okay, once I have USBs if the WiFi is not working,
00:45
but it seems that everyone else doesn't need them and is not having trouble, you can use bundle install local so you don't need to hammer the WiFi to install a bunch of gems, because I have a cached version of gems in the repo for everybody. And if you're using Windows, be sure to check out the Windows branch,
01:03
because SQLite and Nopogiri have specific gems for Windows. Today we're gonna talk about how to contribute to Rails. We're not going to talk specifically about getting, how to get your environment set up to run Rails source, but rather we're gonna focus on guidelines and advanced technical knowledge you need to know
01:20
to have the confidence to contribute to Rails. I'm Eileen Uchitel, and I'm a programmer at Basecamp, or as you might know it better, the place Rails was created. You can find me pretty much anywhere online at the handle EileenCodes. I'm also on the Rails committers team, which means I can push directly to master, but I'm not on course,
01:40
so I'm not allowed to have access to the Twitter account. I'm from a small city called Kingston, New York, which is about two hours north of New York City. It was the first capital of New York in 1777. This is our dog Aria. Yes, she is named after Aria from Game of Thrones, and you can follow her on Twitter, at ariadog.
02:05
There are a few requirements for this workshop. Although I would love to help everyone get their environment set up, we don't have time for that, so we're going to focus more on advanced Git and code traversing tools that you don't use every day. This isn't a beginner course in Rails, and I'll be assuming you know how to debug environment issues
02:21
and install multiple versions of Ruby. You should also know how to install the required databases and be comfortable with Git and GitHub and know how to create branches, rebase, push, and clone. The goal of this workshop is to get you comfortable enough to contribute to Rails. I started contributing to Rails in March of last year after speaking at Mountain West,
02:41
where I gave a talk in active record. Aaron Patterson was there, and it turned out I had discovered some bugs in Rails. We worked together to fix that bug, and it made my introduction to Rails a lot easier and less intimidating. I want to help you feel as comfortable and confident as I do contributing to Rails, so we're going to focus on debugging issues,
03:04
traversing source code, and learning advanced Git so that when you're asked to defend a change or change your commit history, you're confident enough to do that. I'll be posting the slides from everything we learned here today, so don't worry if you miss something. You can always go back and do it later.
03:22
I've had many people tell me that contributing to Rails is inaccessible because the issues tracker is difficult to parse. There are so many open pull requests. It's hard to tell what's worth working on and what's really an issue. It takes a lot of experience with the Rails team and the code base to understand what's a desired feature and what qualifies as a bug.
03:41
To be honest, even I have trouble finding things to work on, but it's not just Rails that's hard to contribute to. Open source in general is pretty intimidating. You can put in a lot of time and effort, and sometimes the payoff is unappreciative users. But most of the time, developers are grateful for your time and your energy. They're so happy when you fix a problem for them.
04:01
It's amazing to be able to help an entire community by fixing documentation or squashing a bug. You're literally saving other people hours of time. Although this talk is going to focus on specifically contributing to Rails, I assure you many of the techniques you learn can be applied to any open source project.
04:22
The format of today's workshop will be a little bit less hands-on than other workshops you may have done in the past, especially because we have a lot of attendees here. I formatted it so that it works as a talk and a workshop where you'll be following me and doing hands-on stuff as I go through the slides. And we'll do some live coding.
04:40
In between topics, I'll pause for questions so you can try out what we talk about. If you haven't done so already, clone the repo I provided. This contains script for debugging Rails problems and setup for practicing Git later. You should do bundle install local to install the gemcache instead of using the Wi-Fi to bundle.
05:00
If you're using Ruby on Windows, use the VM, and you're not using the Rails VM, you need to check out the Windows branch and do bundle install local after that. The gemcache requires Ruby 2.2.2. If you have a problem, if you don't have Ruby 2.2.2, try changing the Ruby version file to a Ruby version you do have if you're having a problem.
05:30
I'm going to touch on setting up your environment really quickly, but we're not going to talk much about this. If you want to contribute to Rails, you likely already have the necessary libraries and databases installed, or you at least know how to get them running.
05:42
You probably already have a favorite Ruby manager like RBM for JRuby. Rails Master requires Ruby 2.2.2. Rails also provides a VM but the majority of core members and contributors run Rails locally on their machines. If you use Windows, then it might be better that you use the VM because none of us have any idea how that works.
06:06
Additionally, you'll need the necessary databases, iSQL, Postgres, and SQLite. There are tests and adapters for Oracle and a few other databases, but those aren't run as part of the main test suite, so you don't need to worry about them unless you're specifically working with that database.
06:21
And of course, you'll need Git because GitHub doesn't exactly work without it. In fact, I'm not really sure how you've survived up until this point working with Rails without having Git installed, so this should already be set up. A GitHub account is required so that you can open issues and send pull requests. If you've ever checked out the Rails source and tried to run the entire test suite,
06:41
you know that it takes forever and you're probably like, no, I don't have time for this. Running the entire test suite takes a really long time. I actually am not sure I've ever done it. But you don't need to worry about that because that's why they made continuous integration and Travis CI is going to run for every single pull request you push and every time they merge something into master,
07:01
so you don't have to worry about something getting missed. Well, unless it's not tested, then it can get missed. Generally, I only run tests for the part of Rails that I'm touching. If you're changing action pack, run action pack test only. If you're changing active model, I recommend running both active model and active record test because they're tightly coupled.
07:21
Just cd into library, you want to test and run rake test. Travis CI is running, so when you push a pull request, you can always depend on it to run your pull request with all supported versions of Ruby. For active record, if you run rake test, you'll be running the test for MySQL, MySQL 2, SQLite, and Postgres adapters. To run tests for a specific adapter,
07:40
you can use the rake test with the adapter name command. Generally, databases behave the same across, behave the same unless you're touching the adapters, so running just SQLite and MySQL should generally be fine. To run a single test file, you can use Ruby dash ilib and the path to the test file.
08:00
These tests will default to using the SQLite adapter. To run a single test in a file, you can append dash n and the test name to the previous command. Again, this will default to using the SQLite adapter. If you want to run a single test or single test case using a specific adapter,
08:20
you can use the arcon method to change the database adapter. In this example, the test will run using MySQL 2 instead of SQLite. You can also run a single test with all adapters with bundle exec test and the test name. I want you to try running some of the Rails tests if you have Rails installed. If you don't have Rails installed,
08:40
sit next to someone who does and look over their shoulder. CD into the active record directory and run the above commands. I'll be posting these slides later on, so if you don't have a chance to run these, it's okay. So the first one will run all of the tests in active record using the SQLite adapter. The second command will run just the reflection test.rb file
09:04
in active record using SQLite. And the third one will run the same reflection test file, but it's running a specific test in that file with the MySQL adapter. I'll give everyone five minutes to try that out and let me know if you have any questions.
09:22
Yes. Apparently it takes 17 minutes to run the entire Rails test suite. That's good to know because that's fast. I mean, probably compared to Ruby, right? Yeah, Rails size takes like 10 minutes by itself.
09:56
No, you shouldn't have any errors. You might need to bundle your Rails
10:00
if you haven't ever tried running the test before or if you recently pulled changes from Rails. A lot of times the gems change and you'll need to bundle right after a pull.
10:23
Oh, okay, yes. So if you see notifications while you're running and it's not an E or an F, that's a warning. And sometimes it's just that there's a... A lot of times you get a warning if you have a shadow variable, if the variable name is the same as another variable somewhere else,
10:42
Rails will warn you about that. We try to remove that from the running test, but sometimes they get missed. Oh, those are tests that are for specific adapters.
11:00
So if you are running the SQLite, those might be... I don't know off the top of the head which ones got skipped. Those might be Postgres tests that are getting skipped.
11:30
You can always go back and look at the slides later. I'll post them right after, especially because we got good wifi. Every open source project has their own way of doing things. To learn more about this, you should read the contributing guideline on that project.
11:43
Generally, opening an issue is the same across repos, but there are a few things that I want to go over that may be specific to Rails. When opening an issue, it helps to explain the problem as clearly as possible. There is a lot of code in Rails, and it's hard for us to know exactly what's happening. Cryptic titles and missing reproduction scripts won't help get your problem solved,
12:01
and instead your issue will get closed. Rails contributors understand your frustration, but we can't help you if we don't understand or can't reproduce your issue. Never, ever open a security report on the issues tracker. Doing this could result in someone without your best interest in mind getting ahold of an exploit. Security issues should be kept between you and the Rails security team
12:21
to maintain the safety of everyone who uses Rails. To report security issues, always email security at rubyonrails.org or a core team member directly. Rails doesn't accept issues on GitHub that aren't a bug in Rails itself. Any issue pertaining to how do I do this or why isn't this working
12:41
is usually related to a gem you're using or code that you wrote and won't be discussed on the issues tracker. This is to keep the number of open issues down so that you can get the help and attention you need. The community is huge and there are a lot more developers on Stack Overflow that can help you debug your environment problems than there are on the Rails GitHub issues tracker.
13:03
If you already have an open pull request, there's no reason to open an issue. Some projects may prefer an issue to be paired with a pull request, but on the Rails repo it's not necessary. This will just create excess noise for Rails core and committers. Pull requests don't need corresponding issues because searching issues on GitHub reveals both pull requests and issues.
13:22
It's easier to have one place to discuss a bug or feature than two, but of course if there's already an open issue, feel free to send a pull request to fix that bug. A big difference between Rails and other projects is we don't accept feature requests on the issues tracker. Don't get me wrong, we love new features.
13:40
It's just that we have so much on our plates already that if you want to see something new in Rails, you either have to convince us to write it or be willing to write it yourself. If you already have a pull request, it's better you just send it than ask for permission or if we want the feature. If you don't have a pull request and you're in doubt, you'll be accepted and you don't want to work on it until you have approval,
14:00
then you can bring it up on the Rails core mailing list for debate. Including a test script can help immensely when opening a Rails issue. It's pretty much required for any active record or action controller bug. It makes it easier to isolate your bug and to be sure that it's not another gem causing the problem. And now we're gonna take a look at how to create
14:21
a runnable active record script. You can find examples for other executable bug report scripts in the bug reports templates directory on GitHub in the Rails repo. To follow along with your own copy, cd into your railsconf scripts directory and open the script called ar-script-examble.rb with your favorite text editor. I'll give everyone a minute to do that.
14:58
Yes?
15:00
Yeah, that was on the first slide. I also have, or USBs that have this repo on them. They're just like small scripts. Does anyone else need a, ooh. Does anyone else need a USB?
15:23
Okay, pass them around if anyone else needs them. Because I only have 10.
15:54
This example shows the bare minimum of what you need for a self-contained active record script.
16:00
First we add the required gems. You'll see some of the scripts include a gem file at the top, but because I run all of my scripts against my local checkout of Rails, it's not necessary here. It's also not necessary for you because I provided the gem file and bundled the gems for you ahead of time. You can include the active record gem with the version of Rails you're testing
16:21
if you have a specific problem with a specific version. When you open your issue, you should include the version of Rails that you've seen the problem with. We then establish a connection with an in-memory SQLite database. Using the in-memory database has a lot of benefits. For one, it's a lot faster, and two, you don't need to worry about
16:40
authentication or the intricacies of other databases, like MySQL. The data is created and destroyed in IO while the script runs. No data or tables are left behind to interfere with future runs. Next we set the logger to standard out so that we can easily see the SQL generated by each command in the script when we run it.
17:02
Then we define the schema of the database. There's no need to create or run migrations. The SQLite memory database will apply the structure from the schema. Here we can easily add columns or tables for our script. Anything that gets generated in your schema file in your Rails application can be put here, like foreign keys and indexes.
17:23
Then we establish the models required to reproduce the problem. I recommend using as simple an example as possible. You don't want other developers misunderstanding your problem because they can't parse the relationships between your models. The more mundane your example, the easier it is to understand.
17:40
Of course, not all problems are simple. I merely mean to pare down your example as much as possible with as few models and relationships as necessary. If it only takes two models to reproduce your problem, don't include all 10 from your application. Lastly, we write a test. As long as your script outputs an example of what's happening versus what's expected,
18:02
that's good enough for anyone trying to figure out what's going on with your issue. This helps us also eliminate the possibility of environment variables and outside gem dependencies. If you can't reproduce an active record problem in an active record script, we can't either, and your issue is likely not with Rails itself.
18:20
You can run the script from inside your RailsConf scripts directory with bundle exec Ruby and the path to the file. Depending on your environment setup, bundle exec may be required here because we want the script to use the cached versions of your gems from the directory, not the version of Rails installed with your version of Ruby. When run, you should see a validation failure in the script. Try out running the script and let me know if you have any questions.
18:41
I'll give everyone a couple minutes to try that out.
19:09
Everyone see that validation failure? Now we'll discuss guidelines for opening a pull request on the Rails project. Always open your pull request pointing to master
19:22
unless your change affects a specific release. Don't point your branches to release branches because your pull requests will get automatically closed when a new version of Rails is released. That's just a GitHub thing. Not, we don't do that. Rails does not accept cosmetic changes to the code base. This means we won't merge in changes
19:40
that change all the double quotes to single quotes, remove white space, or otherwise are refactorings that don't improve the readability of the code. The reason we have this rule is to keep git blame clean. We don't want to have to chase down a code change among cosmetic sweeping edits. Detailed commit messages help us and future contributors understand what and why you're changing something.
20:01
Imagine that GitHub disappeared tomorrow but your commit messages live on forever. Sometimes I'm on a plane and I don't have Wi-Fi and I'm working on a Rails bug anyway. I don't want to have to wait until I land to go to GitHub to understand why you changed something. Don't assume that everyone knows X does this and should be avoided. Explain why X should be avoided in detail
20:21
in your commit message. A good commit message includes a summary of the changes, 50 characters or less, and a more in-depth, detailed description below. Feel free to include bullets, code samples, anything that can help someone understand why you made a change. Often we'll ask programmers to squash their commits.
20:40
This makes it a lot easier to backport changes with cherrypick and keeps the git log clear and concise. Generally, if your change is small with a test, that should be just one commit. If you spent months on a feature and have clean history, you're likely to get all your commits merged in without squashing into a single commit as long as your history is clean. Later on, we'll go over how to squash commits.
21:03
Rails gets a lot of pull requests and sometimes we fall behind reviewing them or aren't sure they should be merged in as is. Sometimes we just don't have time to review them. Unless you have a good reason, don't constantly ping members of the team asking for a review. That said, smaller, concise changes are easier to parse and maybe faster to get merged in.
21:21
Please don't plus one issues you want fixed or pull requests you want merged in. Only comment on a PR issue if you have added insight. For example, you've run the patch and confirmed that it fixes the original issue. Be sure to read all of the other comments first. Often they point to why a proposed fix won't work and can't be merged in. It's not uncommon for original reporters to become too busy to remain involved.
21:42
Be proactive, not reactive, when commenting on Rails issues. Yes?
22:03
There's a way to say that you want things without just plus oneing. Plus oneing sends every single person who watches a repository an email. And that's kind of why, and sometimes you'll just see issues that have lots of plus ones, but if you read the beginning of it, you'll see why it's not, either it's not as simple as just fixing it.
22:23
And what I mean by be proactive is if no one's fixing it, then ask for help how to fix it, rather than plus oneing it, because it's usually not a case of we don't care. It's a case of either we don't know how to fix it, or we'll see in earlier comments,
22:41
maybe it can't be fixed for some reason. Our documentation always needs work. Sometimes documentation is missing, or code is changed and it's wrong. Occasionally it's just grammatically incorrect even if the content isn't. We love documentation pull requests, and I personally feel like
23:01
it's one of the best contributions you can make. It's a great way to gain understanding of the Rails code base and the contribution process. Making sure documentation is correct prevents tons of old and new developers from having a bad day. If you see incorrect documentation, you should send a pull request as soon as possible. When sending a documentation pull request,
23:20
make sure you use CI skip in the first line of the command message. This makes sure that Travis CI doesn't run on your documentation pull request. Rails is one of the largest and most contributed to code bases on Travis CI. We try to do our part so that their CI server isn't running when necessary, and so that we can keep the queue open so that actual code changes can run,
23:42
because it actually takes a really long time to run pull requests with all the supported versions of Ruby. This won't work all the time, because issues aren't always simple. But the simpler you keep your code, the faster it is for us to merge it in. If you're working on a yak shave, it's better to send a bunch of smaller pull requests if possible, because it's easier to review
24:02
a small change over large hundreds of lines of code. If you work on a pull request and you want to prove that you've made the code faster, you should use benchmark IPs. Benchmark IPs measure the number of iterations per second the specified code can run. This means that the higher numbers with lower standard deviation means the code is faster.
24:23
This really takes a lot of guesswork about whether or not your code is sped up Rails. You should include these benchmarks in your commit message if you're sending a performance-related pull request. Now we're going to look at how to write one of these benchmark IPs script. You can follow along by opening benchmark IPs example.rb
24:42
script in your RailsConf scripts directory. I got this specific example from a pull request that Eric Obermeichel sent to Rails. So this is an example of a benchmark IP script.
25:01
It defines two methods that demonstrate two ways of sampling an array. As far as benchmark IPs go, this is a very simple script. Sometimes you can't have the old slow method and the new fast method in the same script because they require too many changes to the internals of Rails. So you'll have to write two scripts and compare them yourself.
25:20
For this case, we are simply comparing two ways of sampling an array outside of Rails so we don't need two scripts. First we require benchmark IPs. Then we define the two methods we need to compare for speed. The first slow method shuffles the array and takes the first item. The second fast method uses the sample method
25:41
on the array. Then we invoke benchmark IPs in a block and use the report method to run each command and record the time spent. The compare method will report the number of times slower the slow method is in the fast method.
26:01
First the script calculates the number of records it can run, it can iterate in 100 milliseconds, and then calculates the differences with standard deviation telling us how far the measurements are from the average. A high standard deviation means that the code is varying too much. Remember that your system memory and available CPU
26:20
and other factors will affect the results, so you need to focus on the standard deviation and the comparison. Here we can see that on my machine, array.shuffle.first is 18 times slower than array.sample. I want you to practice running the script with Ruby. Go into your RailsConf scripts directory and run the benchmark IPs example. Your times will not be exactly the same as mine,
26:41
but you should still see that there's a big difference between the slow and the fast methods. And I'll give everyone a minute to try that out. This particular one was to change places in Rails that used the slow version of array.
27:04
I think it was array.sample that first to replace that with array.shuffle and using that as proof that it made it faster.
27:27
I've seen it run when it's in the bottom of the commit message. I'm not sure exactly where it has to be. I know that it definitely doesn't run when it's in the first line, but I've seen people put it in the body and it will still run. I don't know, maybe there's something in our settings
27:41
that is causing that. It also makes it clear from the very beginning that it's a documentation pull request rather than having to read through it, not that that's a reason. I don't know, it didn't work one time when it wasn't anywhere, when it was anywhere.
28:02
Anyway, it doesn't matter. Just, I always forget to put it in there anyway, so. I just have the power to stop Travis from running. Writing tests is not always fun, especially when you aren't sure what models and tables there are in the Rails test suite.
28:22
If you find a regression or bug, you must add a test. Fix a regression or bug, you must add a test. If you're adding a new feature, you must add a test. The only time you don't need to add a test is when you're refactoring existing code and not altering the behavior of Rails, but in that case, no test should fail. Your bug fix or feature request will not get merged without test,
28:42
and because tests help us protect against regressions in other people's applications. When writing tests, try to use existing models first. Don't add new models or tables unless it's absolutely necessary. This is somewhat of an aside, but I wanted to briefly talk about deprecating methods in Rails. If a method has a nodoc signature next to it,
29:01
it does not need to be deprecated if you want to remove it. This means that the method is private and Rails applications should not be using it themselves. Nodoc means that methods are not documented and will not be included in the Rails docs. This example shows how to nodoc an entire class. You can also nodoc globals, adder accessors, and methods as well.
29:23
If a method is not nodoc'd and you intend to remove it, it needs to be deprecated and cannot be removed from Rails until the next cycle. To write a deprecation warning, you can use the active record deprecation class and the warn method. There are many examples of this throughout the Rails code base. Now we're going to learn some tools
29:41
that will help you in finding your way through the Rails code base. Between metaprogram methods and mysterious errors, sometimes it's hard to find the code that's causing a bug. I know that you're skeptical that I can make this easier. Finding your way through any new code base can be irritating and frustrating, but there are a lot of methods and tools that can help us find our way through any Ruby code base.
30:02
The first we're going to talk about ships with Rails source itself and is called source location. Source location's method is to find an action view. This code will basically output the file name and line number of the method you're calling it on. Let's take a look at how to use this. Follow along with the slides on your own computer.
30:21
I want you to cd into your RailsConf scripts directory and open the source location file with your favorite text editor. I'll give everyone a minute to do that.
30:56
Find the line that says post.comments.deleteAll. We're going to use source location
31:01
to find where the deleteAll method is defined in Rails. Wrap your call to deleteAll in method and append source location. Add puts to the front so that it outputs the source location when we run the script. I'll give everyone a minute to get that set up.
31:23
Can you see that?
31:59
Now run the script with bundle exec Ruby
32:01
and the script name as we did before. Remember, you need bundle exec so it runs against your cache copy of Rails in the RailsConf scripts directory. And you should see the path, and I'll go to the next slide that'll show you what it looks like.
32:20
You should see the path to the file and the line number among a bunch of other SQL. It should look like this. There's a bunch of other stuff there, but it should be on in collection proxy. The line number may vary, depending if it changes as I wrote these slides,
32:41
which it probably didn't. And so now we know where deleteAll is defined on a collection proxy in Rails. And if we look at that file, we can see that deleteAll method is calling deleteAll on the association. So we're gonna need to find the definition of deleteAll on association to figure out what the code is actually doing,
33:02
because this definition doesn't really help us a lot. In this case, you could continue using source location with inside Rails to find the definition, or you could use something like ctags instead. I'm not gonna have everyone kill the wifi by installing ctags right now,
33:21
so just don't do this yet, and you can do it later. I promise you can ask me questions on Twitter if you get confused. Ctags indexes your code base, methods, classes, and variables and other identifiers in a tags file. This allows you to put your cursor on a method name and find where it is defined in the Rails code,
33:42
in any code base, particularly Rails for this example. You can install ctags with homebrew on Mac with apt-get or yum, bleh, homebrew on Mac or apt-get and yum on Linux. There's a version for Windows, but it's not as simple as running one command. Does anyone actually have Windows in here?
34:05
I will stop giving you Windows examples. Well, I wanted to make sure if there were any Windows users, they didn't feel unloved. This is the bare minimum of what you need to index the Rails code base,
34:22
is to run ctags-r. in your Rails directory, but a lot of people don't like their tags file to sit in the main directory of their applications, so they put them in their .get directory instead, and you can do that with .get slash tags instead.
34:42
From this point on, I'm only showing examples for vim because that's what I use and I'm familiar with. To use ctags or Sublime or TextMate, follow the instructions at these repos on GitHub, and you can get these URLs later. Actually, if you just search google.com up as the first thing, hopefully those are the right ones.
35:03
If you use vim, you'll want to add the following to your vimrc. This sets your ctags, excludes git directories and skips indexing for JavaScript and SQL. To tag your Rails directory, you can type your leader and rt, and that will tag your copy of Rails instead of running what we showed earlier, and you can use this in any of your applications
35:22
or code bases. Now we are ready to search for definitions. To find a method definition with vim, you type control right bracket with your cursor when your cursor's on that method. If that method has more than one definition, you can see a list of possible matches by typing colon ts, and to choose a different definition,
35:40
type the number of the index file and hit enter. I recorded a screencast to show specifically how this works. So we're gonna open the file we were looking at earlier, collection proxy, and look at line 442, where delete all is defined on the collection proxy, and we're going to put our cursor on the delete all, and we're gonna use control right bracket,
36:02
and it tells us that there is one of five more tags, so with ts, we're going to look at the list of tags, and looking at that, we can see the one that we actually currently are looking at, and then the next one's probably not it, because that's active job, so it's probably number three, because that's in collection association, so we're gonna type three and enter,
36:21
and here we found the definition of delete all, but this doesn't really tell us a lot, because there's another method in there, so we're gonna go look at delete another file records, and see how that's defined, and because there's only one definition of it, it's gonna take us right to the definition rather than having us choose a file first, and with ctags, you can also look up
36:42
how classes are defined, so we can see that has many association here, it inherits from collection association, so we can use control right bracket to find collection association definition, and easily see that that inherits from association, and you can see with this how we can easily move through a code base,
37:01
finding different definitions of methods, classes, whatever we need, rather than using acc or grep to find definitions, because that takes actually a lot longer than moving through the code base with ctags.
37:24
Let's say we know that this method association primary key is in our stack, but we don't know who's actually calling it first. We could raise to find out who's calling it, but that's just gonna stop the execution of our code. Instead of raising, we can use a caller,
37:43
which is a Ruby method defined by Ruby's kernel module. This will output the stack trace at the point the method is executed and won't stop our code. When run, the script returns a path of the file, the line number, and the name of the method that was called for each method in the stack. Your script continued to run without stopping
38:01
because we didn't raise. It just simply outputs the current trace at the point of the code that you're in. Starting at the bottom, you can see that the trace started with our script with delete all, and moved, traveled through, I'd say that's not from our script, sorry. That's from my script that I wrote that we haven't run yet.
38:21
Traveling through up to construct join attributes, and we can see that the association primary key is first called from the through association file on line 48 in construct join attributes, and this is the line that actually calls association primary key in Rails. Okay, let's practice using puts caller
38:40
in one of our active record scripts. Open the puts caller file in the RailsConf scripts directory with your favorite text editor.
39:03
We can see that in this file, there's a callback defined that is run after create, and it just outputs I am a callback. This is very sophisticated. We're going to use puts caller here to find where this method is actually called from inside Rails, because Rails is what's firing those callbacks. We want to know the stack trace at the point
39:21
in which this code is hit. So add puts caller to the top of the call me method and save the file,
39:50
and then run the script like we did before with bundle exec Ruby,
40:05
and you should see a pretty big stack trace like this, and if you go to the very top, you can see that that callback is called from callbacks.rb on line 428 in the method make lambda,
40:24
and if we go there, we can see the real reason why some developers hate callbacks in Rails. I call this method lambda vomit, and every time someone's like, oh, I love callbacks, I send them to this code and ask them to tell me what this is doing.
40:43
Okay, so now we know how to find who's calling method, but what if we need to search for a dynamically created method instead, like ship attributes? Source location and puts caller isn't going to work there. The reason we can't use source location and C tags
41:01
is because ship attributes is not actually defined as ship attributes, and C tags is kind of not very smart about, it doesn't know, it has no idea that that's actually the definition of that method, so it can't find it, and we can't use puts caller because we're not calling a method that will tell us,
41:21
we can't put puts caller inside that method because we don't know what that method is, or we don't actually have that method. To solve this problem, we can use trace point. Trace point ships with Ruby 2.0. Unfortunately, it's not available in 1.9 or lower, but with Rails Master, you should be using Ruby 2.2.2 anyway, so that won't be a problem. Trace point provides the functionality
41:41
of kernel set trace function in an easy-to-use object-oriented API. With trace point, you can specify the types of events you want to listen for and can even filter the results. First, we call trace point and pass call. This will filter by anything calling a Ruby method. We open a block and put the arguments returned.
42:02
That will be our stack trace, and then we enable trace point with TP enable. This will begin capturing our stack trace. We then call the code we want to trace, and finally, we disable trace point, indicating for the trace to stop. Only the stack between TP enable and TP disable
42:21
will be output. I say only, but it's gigantic. Trace point, the output is gonna be really, really long and seems kind of difficult to read, but for our purposes, we only care about the top line where ship attributes is defined, and we can see that that's in nested attributes on line 347, and if we go there,
42:41
we can see why this method in the Rails framework simply can't be found with C tags, because it's dynamically created based on your association name that you give to Rails, and we can see that it's actually defined as association name underscore attributes,
43:02
and association can be literally anything. Okay, now that we understand trace point, let's use it in one of our scripts. Open the script called trace point.rb with your favorite text editor.
43:29
So we have a user class, and that user class has one avatar and an avatar class that belongs to the user. Because of this, we can use avatar attributes to create avatars through that user.
43:40
Let's practice using trace point to find out where avatar attributes is defined in Rails. First, invoke trace point and look for methods that call Ruby by using call. I'll pause while everyone adds this to their script. Again, this is going to just return methods that are called by Ruby itself,
44:05
and then the arguments that will be output, that's our stack trace that's gonna be returned.
44:32
Then put TP enable before the call to avatar attributes and TP disable after. Again, I'll wait for everyone to get this all added in,
44:41
and if you are ahead, you can run it. If you remember, you can use bundle exec Ruby to run the script, and we'll see that on the next slide if you're not ahead.
45:09
There might be, I don't know. I only used this once. I thought it was really cool, though. I wanted to show everyone how useful. Because we only actually really care about the first line, so it doesn't really matter how much it outputs, right? I mean, you could, actually, you could just like,
45:21
you probably could tell it to just return the first one. You could probably just put arguments first and probably get the, I think, I would assume it would give you the first one. Someone try it out, let me know. Now run this script with bundle exec, and you should get a really long stack trace, like I said before, and if you find the top of the stack trace,
45:43
you should, again, see that avatar attributes is defined in the same place we saw earlier, nested attributes on line 347, and after this, I promise we're done with stack traces.
46:04
Yeah, and this is where you should see it defined.
46:23
Again, line number might, I think the line number is correct. Sometimes it changes a little bit. People like to touch the callback code. All right. So, all of these guidelines and code traversing would be useless if you didn't know the powerful git tools to help you send pull requests
46:40
with perfect commit history. Before we start, if you don't wanna lose all of the changes you made to your active record scripts, add your changes and commit them. You won't be able to push because you don't have permissions to my repo, but you won't lose changes either. If you don't wanna save the changes, you can do a git stash or a hard reset,
47:01
and I'll give everyone a minute to commit their changes so they don't lose them.
47:56
Okay, is everybody good? Ready? We're ready to learn some fun git?
48:01
Okay. We're not going to talk about git commands that everyone knows like pull, clone, and push. Instead, we're going to focus on commands that are more complex, but will help you find where bugs were introduced, write concise git history, and even help undo your mistakes. We're going to talk about git bisect, interactive rebase, reset, and reflog.
48:22
If you're using GitHub correctly, you created a fork of Rails in your own GitHub. This is required because you don't have push access to the Rails repo. You'll need to update your master often to be up to date with the main Rails repo. To do this, you'll need to add a remote upstream to your local branch. Technically, upstream can be called anything, but I personally prefer to use origin for my fork
48:41
and upstream to pull from the main repo. First, we'll need to add the remote to our branch with git remote add upstream and the URL to the original project. I actually made a mistake in the blog post about Rails, so if you did that, you should, you're going to need to remove it and redo it
49:00
if you followed my instructions exactly. So to remove remotes, you can use git remote remove upstream. Again, you only need to do the remove part if you copied my blog post exactly.
49:26
And you can do this now if you want, or you can skip it. I was going to skip this because I didn't think we had Wi-Fi, but we appear to have pretty good Wi-Fi, so.
49:43
So this simply just allows you to be able to easily pull in changes from Rails by giving git two URLs, and one of them is your URL and one of them is Rails URL. And you can get changes into your URL from Rails, but you can't push back up to Rails.
50:01
And you can get those changes from Rails master, from GitHub, by doing git pull dash dash rebase upstream master. This command will do a git fetch and then replay your changes on top of upstream master from your origin, on top of your origin master from upstream master.
50:24
Be sure to push this update from the rebase, the pull rebase, to your origin remote because if you reset one of your local branches to your remote master without doing this, you won't have the updates you just pulled from the Rails repo. We're not going to try, oh, yeah, we're gonna try this.
50:42
We're not gonna try this out right now because I don't know if you have your actual Rails repo set up to have origin as your fork, so I don't want you to mess anything up. So, git bisect is one of my favorite git commands. Bisect can seem really overwhelming
51:01
because the documentation is confusing, but it can be really helpful in identifying when a regression was introduced into the code. Git bisect takes two points, a bad point and a good point. Bad and good are really subjective terms here. Bad just means, actually bad can mean anything to you, but usually I, in my case, I believe bad means the bug exists or where code was added
51:22
and behavior changed. Good just means the behavior bug that you're looking for does not exist there in that revision. Bisect takes those two points and starting in the middle, picks a new revision for you to test if it's good or bad. I recommend using an active record script like I talked about earlier when using git bisect because bisect needs to be run in the root directory
51:43
and any test you might be relying on could have changed in the commits that you're bisecting. To start, you need to find a revision that's not broken. You can give git bisect a branch, a commit ref or a tag. Once you know where the bug exists and where it does not, you can start.
52:02
Rails tags every release, so it's pretty simple to check out a tag and see if the bug exists there or not. When you have the ref that caused the bug, you can start a bisect with git bisect start. You then need to give it a bad point where the bug exists and a good point where the regression does not exist.
52:21
To name master as the bad starting point, simply type git bisect bad. To name a tag as good, type git bisect good and the tag name. To demonstrate, I recorded a screencast of me doing a git bisect. In this demonstration, I'm using a script that was provided in a bug report to Rails. So the bug report included this bug report template already
52:45
and it has the required gems, it does the connection to the SQLite database that we talked about earlier, it defines a schema that just has a post table, it has a post class that defines a custom ARL scope,
53:00
and then we finally have a test that is just asserting that the custom ARL scope has the SQL that we expect. So we're going to run this test against version 4.1.8 on Rails and you can see that we have this error that we cannot visit the ARL, whatever, I missed it.
53:25
Then we're gonna check out version 4.1.7 and we're gonna run the script again and we can see the script passes. So the bug exists on 4.1.8 and it does not exist on 4.1.7. So we're gonna start the bisect, git bisect start, and then we're going to name 4.1.8 as bad
53:43
and we're gonna name 4.1.7 as good. And now we can start, and now bisect has picked a revision for us to test from the middle. And we have about five steps before we know where the bug is. So we run the script and because this passes, this revision is good.
54:01
So now bisect has picked a new revision for us to test based on that and because we have the ARL select manager bug, we can say that this is bad and then we're gonna run it again and it picks a new revision and this is good because the test passes. And then a new revision. And it can get a little bit tedious. There's actually a way to automate this
54:21
but we're not gonna go over that today. And you keep running it until it gives you the first bad commit and we can see that it was on September 4th and it's all Aaron Patterson's fault. And you can use git show to see exactly what changed in that commit and when you're done,
54:41
you need to go, if you need to go back and get out of the bisect, you can type git bisect reset and it will return you back to where you started and you're no longer in revision. Okay, because bisect can be kind of confusing, we're gonna do this one together and we're going to live code
55:01
all of the git sections together. So I want you to follow along with me in your terminal as we bisect a branch in the RailsConf script repo. So you guys can all see that, right? You couldn't see it before. So if you got the scripts from the repo,
55:23
from the GitHub repo, you're gonna need to do a git fetch and then check out the practicing git branch. I can't spell practice. All right, so check out the practicing git branch.
55:46
And so what we're gonna do is we're going to use this to find out where in, where in the, so there's documentation in this repo. We're going to use bisect
56:00
to find where the bisect documentation was introduced into the readme of this repo. So first, we're gonna cat the readme and then we're gonna look at the bisect section. Cat readme. And we can see at the bottom there that there is a section about bisecting
56:22
in the documentation. We're gonna go back to master with git checkout master and we're gonna cat the readme again. And we can see that there is no bisecting documentation there.
56:42
So now that we know that we have a good and we have a bad point, the good point is master. The bad point is practicing git because the thing we're looking for exists there. Again, merely subjective terms. They don't really actually mean anything. You just need to keep them separate in your head. So that's why I define it as behavior that exists versus behavior that doesn't exist.
57:01
In this case, behavior is documentation existing. So we're gonna go back to the practicing git branch and we're gonna start our bisect. So git bisect start. Oops, I have two Gs there.
57:22
And we're going to name practicing git as bad by just typing git bisect bad. And then we're gonna name master as good
57:41
with git bisect and the branch name. Bisect good and the branch name. So git bisect good master. And then we're in a, then now we're in a bisect and we're ready to start saying good or bad
58:00
to each revision and find where this was introduced. So now that we've started, we can cat through me again. And we see that there's more documentation than there was on master but I still don't see anything about bisect. So this is a good revision. All right.
58:21
Now bisect has found a new revision for us to test. And cat will read me again. And we see code about bisect. We see documentation about bisect. So this is a bad revision because it has the behavior that we're looking for. So git bisect bad. And this is obviously a very simple example compared to running active record scripts
58:41
but it gives you the idea of how you can separate your subjective knowledge of good and bad and how you can use bisect to find where something happened. And you know that you're almost done because it says zero revisions left after this. So cat will read me again. And we still have bisect code. So this one is also bad.
59:01
So we had a good and two bads. And when you're done with that, you should see this is the first bad commit. And if you found the commit that says add section about bisecting, this is the commit we want to find when you're practicing bisecting. And you have successfully done your first bisect. When you're done,
59:26
you're gonna need to get out of here because this is not where you want to be editing code in the middle of a bisect. So you're gonna do git bisect reset and it's going to return you to the practicing git branch before you started the bisect.
59:56
A useful git command is git commit amend. Amend allows you to edit your commitment.
01:00:00
your last commit message or commit. If you have staged changes, this will wrap up those changes into your last commit and pause for you to edit the commit message. I find this useful for when I know my change was part of the last commit, like a typo in a method name or a documentation. But there are times I've accidentally done a git commit amend because I forgot
01:00:22
what the last commit was, and then you need to undo it. And how are you going to do that? That's really hard. To undo an amended commit, you can use git reset soft head at one. This moves your branch to the previous state, which is before the amended commit. This will undo the amended commit but not the entire commit.
01:00:41
A git status will show you that the files are committed but still staged. If you needed to undo something like an entire commit, you can use git reset soft till the end, where n is any number of commits you want to rewind to before head. This will remove the requested number of commits from head. A git status will show that the files that you changed
01:01:00
are staged but no longer committed. If you want to unstage those commits, you can use git reset head. So let's practice doing some git amends and resets together. We're going to write some commits and then undo them. I want you to follow along in your own terminal with me.
01:01:23
So on your practice in git branch, open the readme with your favorite text editor. And just add a section to the bottom and save it.
01:01:41
And it can be anything because we're going to get rid of this. So don't worry about leaving weird stuff in your readme. And when you're done doing that, we can add the commits with git add. And then we're going to amend the commit instead of writing a new commit.
01:02:05
So git commit dash dash amend. And then we realize, oh no, I did not mean to add a new section to my commit about fixing spacing. That's not OK. Those are not the same thing.
01:02:21
And I don't want to edit this commit to include two changes that are completely unrelated to each other. There's no way to get out of this situation. We're stuck. We're not. What? Well, you could do that. But then you end up with this weird file in your vim. So quit.
01:02:41
And we can easily undo the commit that we did with git reset soft head at one. And again, this is going to rewind our history to the previous state we were in. But it's not going to undo the entire commit. So if you do a git status, you'll see that the changes are staged.
01:03:02
And then to unstage them, you can use git reset head in all caps. And in git diff, I'll show you that we only undid the little part we just added, not the entire commit. It should only be the stuff that you just changed.
01:03:25
And so now we realize that we don't actually want all the changes we made. And we could stash. But we're concerned that we made other changes and we haven't pushed them. And we really just want our branch to be exactly the same as the remote. So we're going to do a hard reset.
01:03:40
Careful with this, because you can lose. Well, we're going to go over how to get it back if you do lose stuff. But you're going to lose anything that's not pushed to the remote. But sometimes you have a staging branch. And you want to reset it to master. You don't need what was on it, what it was on it for.
01:04:01
You want to reset it to master. So in that case, you can use git reset hard origin for the remote. Or that could be upstream if you wanted to reset it to upstream master or something. And we're going to reset it to our practicing git, so that we know that this is back to where it started.
01:04:25
And we don't have any weird changes that we don't want. And git status will show us that it got rid of the changes we had. And we don't need to worry about that.
01:04:41
Any questions so far about that stuff? Sometimes the Rails team will ask you to squash your commits. If you have perfect commit history and are sending a pull request that you spent a lot of time on, you can get more commits for that pull request.
01:05:00
A pull request with lots of oops that was wrong commits isn't going to get merged until those commits are gone. We want to make sure that the git history is clean. In this case, your best friend is interactive rebase. After making sure your master is up to date, do git rebase dash i master on your branch. I recommend doing this after you've already rebased and resolved your conflicts.
01:05:20
Because we don't want to be resolving conflicts while we're editing our branch's history. It can get really confusing if you're trying to change your commit messages and fix your conflicts at the same time. The best part about interactive rebase is you look like a genius. You will always have perfect commit history. And you look like you knew what you were doing the whole time.
01:05:40
No one ever has to know how many mistakes you made. When you start an interactive rebase, it looks like this. Pick just means use the commit as is. This is the default when you start an interactive rebase. Reward stops so that you can update the commit message, but you can't change the commit itself.
01:06:03
Edit stops the rebase so that you can amend the commit. You also need to be explicit about continuing the rebase with git rebase dash dash continue. Squash mashes two commits into one and includes both commit messages. And fixup is like Squash, but instead of including both commit messages,
01:06:20
it combines the changes from the commits and trashes the second commit message. Exec allows you to run commit messages as commands. This sounds absolutely terrifying, and I've never actually used it. So if anyone knows how useful it is, I'd love to know. Now we're going to practice doing
01:06:40
an interactive rebase together. I want you to follow along your terminal like you've been doing before. And to start an interactive rebase, again we do git rebase dash i master, and do this on your practicing git branch, because theoretically you can do this on master.
01:07:02
But then you're going to have to force push. And it's OK to force push your own branch, but it's not OK to force push public repos. So git rebase dash i master. And we've got six commits. And let's change the bottom one.
01:07:21
Let's edit the commit message. So change the word pick to edit on the sixth commit.
01:07:52
Save and quit. And so then interactive rebase stops for us to amend the commit.
01:08:01
The reason that it stops is so that in an edited commit, you can change the commit message. The author, the date, the actual things that are committed in that commit is really useful for just changing. You could just change the entire commit, its entire existence with edit.
01:08:24
So git commit amend, like we did before when we were doing the resets. And just add some text and save it with right quit.
01:08:43
And because it's an amended commit and not a reword, so a reword wouldn't stop like this. It would just actually stop with the commit message and you'd edit it because you're not editing the commit itself. You're just editing the message with reword. So edit stops. And you need to be explicit about continuing the rebase because the interactive rebase doesn't know you want to keep
01:09:02
going just yet because you could, like I said earlier, you could change the author here, or you could change the date. You could change everything. So you're going to have to do a git rebase dash dash continue.
01:09:21
And if you do a git log, you'll see that you should have the edited commit in your history now. And let's practice doing a squash. We're going to see what actually doing a full squash with interactive rebase is like. So start a new rebase with git rebase dash i master.
01:09:42
And we're going to change all of the picks to squash except for the first one. We don't want to change the first one because there's nothing to squash it into and the rebase will error. So if you don't know how to use vim, you need to use colon. You can either change them manually or you can use colon percent s slash pick slash squash
01:10:05
slash gc. This is going to replace pick with squash but pause and ask us first if we want to change it. So you hit Enter, and it's no for the first one. And then yes, yes, yes, yes, yes. So we're going to change all of them except for the first one
01:10:21
to be squash. And the last one is also a no because it's a comment. But if you change it, it's not going to change how git works.
01:10:48
And then save and quit. And squash stops so that if you don't actually want all of these commit messages in there, you could edit it here. Sometimes I will squash and I will completely
01:11:00
change the commit messages because they don't make sense as two separate commit messages. And I will just write a whole new commit message. For our purposes, we'll just save and quit. And if you do a git log again, you can see all of the commit messages in one commit there. It's pretty cool.
01:11:25
When you're done, if you've already opened a pull request to on Rails, you're going to need to force push. You can't do that here because you don't have permission to push to my repo. But I want you to know that it's OK to force push your branches on Rails. If you had a commit bit and were allowed to push to Rails,
01:11:43
you're not allowed to force push. But if you have your own branch on your own repo, it's OK to force push. A lot of times we see developers will close their pull requests and open a new one because they think they can't force push. Don't worry about it. You won't get in trouble. Actually, we prefer you not to open a new pull request because then we have two pull requests instead of just
01:12:02
one. So don't worry about force pushing. And you can always do that on your own stuff. If you're unsure how to do something, ask for help. We're very willing to help anyone, even if you think the question is stupid. We help people squash all the time.
01:12:21
And if you get stuck, we can always do the squash for you. It's not a big deal. Another favorite Git command of mine is git reflog. They should change its name to git rescue me from the stupid thing I just did. It's your safety net. It literally tracks everything you're
01:12:42
doing inside of a repository. It records when you switch branches, perform to rebase, stash to change, reset your branch, everything. Did you do a bad rebase and push after? You can undo that. Did you hard reset your branch? You can undo that, too. You can literally go back in time with reflog.
01:13:00
It's one of my favorite tools, and everyone should know how to use it. In your Git repository, you'll see git reflog. If you type git reflog, you'll see a list of actions performed like commit, rebase, aborting your rebase. On the left is the ref of the change you made and the head number. You can choose any of the number of refs and use a hard reset on your branch to go back in time.
01:13:25
So we're gonna do this one together again. All right, so one of the cases where I've used a hard reset, or not hard reset, a git reflog, is one time I squashed commits that I was gonna send to Rails and realized that they actually should have been two pull requests.
01:13:42
They were not related enough that they should be in one pull request. So I decided to unsquash them, but I had already pushed to my branch, so I couldn't just do a reset to the remote and go back in time. So I had to use reflog to undo the squash. So we can type git reflog,
01:14:00
and we can see the first one is where we finished the rebase, rebase-i finish. The next five are the squashes that we did, rebase-i squash. And then the one last, the sit number six is where we started the rebase, where we did the squash. So that's rebase-i start.
01:14:22
And then the one before that is where we did the rebase, interactive rebase to edit the commit. This is where we wanna go back in time. We don't wanna lose the edit we did, but we do wanna undo the squash. So we're gonna quit reflog with Q. Oops, you're gonna wanna grab the ref
01:14:40
that's next to head at seven. It will be different than mine. You also can reset to head at seven itself, because one of the things that's interesting is reflog actually tracks how similar your branch, the part you are in is. So although we have head at seven, if we looked further down, we'd actually be able to see all the other points
01:15:03
in the history of the branch that was exactly the same as head at seven, because they'll have the same number. And I think I've just totally confused you all. Here, I'll show you. Okay, so the number next to head at seven is five c-f-a-d-e-eight. If we keep going down, we can see that at eight,
01:15:21
head at eight was the same as that, because it has the same number. And there aren't any others right now that I can find. But it actually, so that's why you could use the number instead of using head at seven. So you can either do git reset hard head at seven, or you can use the reference number, the revision number.
01:15:44
And then if you do that, and you do git log, you'll see that you have all of your commits back, but you didn't get rid of the edit you did, because you've gone back just seven points in your history.
01:16:00
Nope, I reset back to where we were at seven. If your numbers may vary, they shouldn't though, like your seven should be the same as mine if you were doing everything that I was doing. But if you accidentally took one that was in the middle of a rebase, you could end up in a detached head state probably.
01:16:24
And it's okay, because if you mess up reflog, it also recorded you messing up. So you can just keep going backwards until you figure out where you didn't mess up. And there is some garbage collection, and you can't go back like 20 days later and get back something that you did probably,
01:16:42
but maybe if it didn't. I think you can control when it does the garbage collection, when it trashes the reflog. It's pretty cool. One of the biggest questions I get is how to find issues to work on.
01:17:02
The issue tracker is difficult to parse. Even with all of my work on Rails, I've actually only ever fixed one or two issues I didn't find or create myself. So what should you work on? One of the best ways to help Rails find regressions is to test the release candidates. Generally, the release hasn't been used in production,
01:17:21
and there are sure to be regressions. Having a small test app that you can easily upgrade to check if everything is working okay is a really good way to test the releases and find bugs that you can fix. As I've said many times before, fixing incorrect documentation is one of the most important contributions you can make. This can save others so much time
01:17:41
if documentation is correct. We have lots of sections of the guides that are a work in progress, and there are always grammatical errors and spelling mistakes that need attention. It's a really, really good way to gain experience in sending pull requests to Rails and getting stuff merged in.
01:18:01
A lot of people are like, oh, documentation's too easy. Documentation's not easy. Documentation is the best part of Rails, and it needs the most help. And a lot of times, people have been working on documentation, they find a bug, because the documentation doesn't match, and that's an easy way to find if something is not right.
01:18:22
You have to ask. Or make a case for which one is right. A lot of times, the code is right because the documentation gets forgotten about. But sometimes, when you're fixing the documentation, you'll find that there's actually something that got totally missed in there.
01:18:43
You should focus on your strengths. If you are not interested in SQL or aren't good at it, focus on something that you're more confident in. If HTTP requests are your thing, work on action dispatch. If frontend is more your thing, work on action view or template generators. There is something for everyone in Rails.
01:19:00
Active Job and Web Console are new gems inside Rails that don't get as much attention as active record. If you're at a loss for what to work on, these two are a really good place to start. Reviewing open pull requests can be beneficial to you and the community. You'll become more familiar with the code base and contribution process, as well as helping Rails maintain
01:19:21
a high standard of code. You may also catch something that didn't get merged in, and then you'll get a pull request. Remember, Rails does not take cosmetic changes, like changing all the double quotes to single quotes, or removing white space. But we do take refactoring changes as long as they make the code cleaner. Aaron Patterson and I spent three months
01:19:40
refactoring association scope just so we could understand what it was doing. It resulted in code that was much easier to read and understand, mostly. Breaking up complex methods can be beneficial to current and future contributors. And although it is a pain, watching the issues tracker is a good way to find an issue eventually.
01:20:02
It is full of lots of stuff that's really hard to work on and it may take a while for you to find one that you can work on. But it can be really rewarding when you find that bug and fix it for someone else. It is possible you'll put a lot of time in and someone will come along and resolve it before you. And that's happened to me, and I'm not going to pretend that doesn't feel awful.
01:20:22
But it's an unfortunate reality of open source. At the very least, you'll have learned something from working through an issue, and you'll gain a greater understanding of the Rails code base. And the next time you have to fix a bug, it'll be faster, maybe. We covered a lot today, getting set up, guidelines for opening issues and pull requests.
01:20:42
We went over advanced Git commands and tools for traversing unfamiliar source code. I hope that this talk has left you with the confidence to contribute to Rails or other open source projects. And thank you for coming to my workshop on contributing to Rails.
01:21:06
Again, you can find me anywhere online at EileenCodes. I'll be posting these slides on the speaker deck later. And of course, you can download the repo at any time. Would it be helpful for me to push the answers to the active record scripts to the repo?
01:21:21
Yes, okay, I'll push those too. I'm also gonna follow up with some blog posts later next week so that if you missed any of the Git stuff and the slides aren't clear enough, you can follow that again. Thank you, everybody.