00:00:12
Hi everybody! Who here has Rails source actually installed and running? Okay, everyone who doesn't, who is sitting next to someone who does, you should sit next to somebody who does. We're not going to use Rails a lot, but if you want to see how the tests look when they run, you should sit next to somebody who has it installed.
00:00:30
But, you can run it later when you do get that installed. Okay, once I have a moment—USBs and the Wi-Fi are not working, but it seems that everyone else doesn't need them and is not having trouble.
00:00:41
You can use 'bundle install --local' so you don't need to hammer the Wi-Fi 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 because SQLite and other components have specific gems for Windows.
00:01:06
Okay, today we're going to 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 going to focus on guidelines and the advanced technical knowledge you need to know to feel confident contributing to Rails.
00:01:31
I’m Eileen Uchitelle and I'm a programmer at Basecamp, or as you might know it better, the place where Rails was created. You can find me online at the handle 'E Codes'. I'm also on the Rails committers team which means I can push directly to master, but I'm not on core so I don’t have access to the Twitter account.
00:01:50
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 Arya—yes, she is named after Arya from Game of Thrones, and you can follow her on Twitter at @AryaDog.
00: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 the time for that. Instead, we're going to focus more on advanced Git and code traversing tools that you don’t use every day.
00:02:25
This isn't a beginner course in Rails, and I'll be assuming you already know how to debug environment issues and install multiple versions of Ruby. You should also know how to install the required databases and be comfortable with Git and GitHub. You should know how to create branches, base push, and clone.
00:02:50
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, where I gave a talk, and Active Record's Aaron Patterson was there.
00:03:12
It turned out I had discovered some bugs in Rails. We worked together to fix that bug and it made my introduction to Rails much easier and less intimidating. I want to help you feel as comfortable and confident as I do contributing to Rails.
00:03:50
So we’re going to focus on debugging issues, traversing source code, and learning advanced Git so that when you're asked to defend a change or modify your commit history, you're confident enough to do that.
00:04:03
I will be posting the slides from everything we learn here today, so don't worry if you miss something; you can always go back and do it later.
00:04:18
I've had many people tell me that contributing to Rails is inaccessible because the issue tracker is difficult to parse. There are so many open pull requests, it's hard to know what's worth working on and what qualifies as a bug.
00:04:44
It takes a lot of experience with the Rails team and the codebase to understand what's a desired feature and what qualifies as a bug. To be honest, even I have trouble finding things to work on, but it's not just Rails that's hard to contribute to.
00:05:06
Open source, in general, can be 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.
00:05:26
They're so happy when you fix a problem for them; 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.
00:05:43
Although this talk is going to focus specifically on contributing to Rails, I assure you many of the techniques you learn can be applied to any open source project.
00:06:04
The format of today's workshop will be a little less hands-on than other workshops you may have done in the past, especially because we have a lot of attendees here. I've formatted it so that it works as both a talk and a workshop.
00:06:24
You'll be following me and doing hands-on activities as I go through the slides, and we'll do some live coding in between topics.
00:06:40
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 scripts for debugging Rails problems and setups for practicing Git later.
00:07:03
You should do 'bundle install --local' to install the cached gem instead of using the Wi-Fi. If you're using Ruby on Windows and you're not using the Rails VM, you need to check out the Windows branch and do 'bundle install --local' after that.
00:07:32
The gem cache requires Ruby 2.2.2. If you have a problem and do not have Ruby 2.2.2, try changing the Ruby version file to a Ruby version you do have.
00:08:04
Okay, 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.
00:08:31
You probably already have a favorite Ruby manager like RVM or rbenv. 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.
00:09:01
If you're using Windows, it might be better if you use the VM because none of us have any idea how that works. Additionally, you'll need the necessary databases: SQLite, Postgres, and MySQL.
00:09:25
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.
00:09:44
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 until this point working with Rails without having Git installed.
00:10:16
This should already be set up. A GitHub account is required so that you can open issues and send pull requests.
00:10:37
If you've ever checked out the Rails source and tried to run the entire test suite, you know that it takes forever. You're probably thinking, 'No, I don't have time for this!' Running the entire test suite takes a really long time.
00:10:59
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. Travis CI will run for every single pull request you push and every time they merge something into master.
00:11:30
You don’t have to worry about something getting missed, well, unless it is not tested. In general, I only run the tests for the part of Rails that I'm touching. If you're changing ActionPack, run ActionPack tests only.
00:12:02
If you're changing ActiveModel, I recommend running both ActiveModel and ActiveRecord tests because they're tightly coupled. Just set the environment to the library you want to test and run 'rake test'.
00:12:38
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 ActiveRecord.
00:13:06
If you run 'rake test', you'll be running the tests for MySQL, MySQL2, SQLite, and Postgres adapters. To run tests for a specific adapter, you can use 'rake test' with the adapter name command.
00:13:41
Generally, databases behave the same unless you're touching the adapters, so running just SQLite and MySQL should generally be fine.
00:14:04
To run a single test file, you can use 'ruby -I lib' and the path to the test file. These tests will default to using the SQLite adapter.
00:14:31
To run a single test in a file, you can append '-n' and the test name to the previous command. Again, this will default to using the SQLite adapter.
00:15:06
If you want to run a single test or single test case using a specific adapter, use the 'AR' method to change the database adapter. In this example, the test will run using MySQL instead of SQLite.
00:15:39
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.
00:16:02
If you don't have Rails installed, sit next to someone who does and look over their shoulder. Change directories into the ActiveRecord directory and run the commands I just mentioned.
00:16:36
The first command will run all of the tests in ActiveRecord using the SQLite adapter. The second command will run just the 'reflection_test.rb' file in ActiveRecord using SQLite.
00:17:05
And the third command will run the same 'reflection_test' file but is 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.
00:17:29
Yes, it takes minutes to run. 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 running Ruby.
00:17:57
Yeah, Rails tests take like 10 minutes by themselves. You shouldn't have any errors. You might need to bundle your Rails if you haven’t tried running the tests before, or if you recently pulled changes from Rails.
00:18:21
A lot of times the gems change, and you'll need to re-bundle after a pull. Oh, okay, yes. So what if you see notifications while you're running? If it's not an error, that's a warning.
00:18:45
Sometimes you get a warning if you have a shadow variable, meaning the variable name is the same as another variable somewhere else. Rails will warn you about that. We try to remove that from the running tests, but sometimes they get missed.
00:19:07
Yes, those are tests that are for specific adapters. If you are running SQLite, those might be and I don’t specifically know off the top of my head which ones got skipped. Those might be Postgres tests that are getting skipped.
00:19:34
Alright, is everybody ready to move on? You can always go back and look at the slides later; I'll post them right after, especially because we got good Wi-Fi.
00:19:49
Every open source project has their own way of doing things. To learn more about this, you should read the contributing guidelines for that project. Generally, opening an issue is the same across repos, but there are a few things I want to go over that may be specific to Rails.
00:20:14
When opening an issue, it helps to explain the problem as clearly as possible. There's a lot of code in Rails and it's hard for us to know exactly what's happening. Cryptic titles with missing reproduction scripts won't help get your problem solved.
00:20:39
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.
00:20:58
Never open a security report on the issues tracker; doing this could result in someone without your best interest in mind getting a hold of an exploit. Security issues should be kept between you and the Rails security team to maintain the safety of everyone who uses Rails.
00:21:20
To report security issues, always email [email protected] or contact 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?' is usually related to a gem you're using or code that you wrote.
00:21:59
This 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.
00:22:08
The community is huge and there are a lot more developers on Stack Overflow that can help you debug your environmental problems than there are on the Rails GitHub issues tracker.
00:22:39
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.
00:22:56
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.
00:23:23
It's easier to have one place to discuss a bug or feature than two, but if there's an open pull request, feel free to send a pull request to fix that bug.
00:23:45
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.
00:24:07
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.
00:24:36
If you already have a pull request, it's better to just send it than to ask for permission or if we want the feature. If you don’t have a pull request and you're in doubt if it will be accepted and don't want to work on it until you have approval, then you can bring it up on the Rails core mailing list for debate.
00:25:12
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.
00:25:27
It makes it easier to isolate your bug and ensure that it’s not another gem causing the problem. Now we're going to take a look at how to create a runnable Active Record script.
00:25:45
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, change directory into your Rails repo and open the script called 'AR_script_example.rb' with your favorite text editor.
00:26:05
I'll give everybody a moment to do that.
00:26:24
Yes, that was on the first slide. I also have USBs that have this repo on them. They're just small scripts. Does anyone else need a USB? Okay, pass them around if anyone needs them because I only have 10.
00:26:56
Alright, okay, this example shows the bare minimum of what you need for a self-contained Active Record script. First, we add the required gems. You'll see some of the scripts include a Gemfile at the top, but because I run all of my scripts against my local checkout of Rails, it's not necessary here.
00:27:38
It's also not necessary for you because I provided the Gemfile and bundled the gems for you ahead of time. You can include the ActiveRecord gem with the version of Rails you’re testing if you have a specific problem with a specific version.
00:28:03
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.
00:28:26
Using an in-memory database has a lot of benefits: for one, it's a lot faster, and there's no need to worry about authentication or the intricacies of other databases like MySQL. The data is created and destroyed in I/O while the script runs, and no data or tables are left behind to interfere with future runs.
00:28:47
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. Then we define the schema of the database.
00:29:03
There's no need to create or run migrations since the SQLite in-memory database will apply the structure from the schema we define. We can easily add columns or tables for our script.
00:29:27
Anything that gets generated in your schema file in your Rails application can be put here, like foreign keys and indexes. Then we establish the models required to reproduce the problem.
00:29:52
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.
00:30:26
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 ten from your application.
00:30:42
Lastly, we write a test as long as your script outputs an example of what's happening versus what's expected—that's good enough for anyone trying to figure out what's going on with your issue.
00:31:02
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.
00:31:22
You can run the script from inside your Rails comp 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.
00:31:48
When running the script, you should see a validation failure. Try running the script and let me know if you have any questions. I’ll give everyone a couple of minutes to try that.
00:32:10
Thanks! Did everyone see that validation failure? Cool! Now we'll discuss guidelines for opening a pull request on the Rails project.
00:32:51
Always open your pull request pointing to master 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.
00:33:09
That’s just a GitHub thing; we don’t do that. Rails does not accept cosmetic changes to the codebase. This means we won’t merge in changes that change all the double quotes to single quotes or remove whitespace or otherwise do refactorings that don't improve readability.
00:33:31
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.
00:33:52
Detailed commit messages help us and future contributors understand what you're changing and why. Imagine that GitHub disappeared tomorrow, but your commit messages live on forever.
00:34:10
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 understand why you changed something.
00:34:45
Don't assume that everyone knows 'X' should be avoided. Explain why 'X' should be avoided in detail in your commit message.
00:35:01
A good commit message includes a summary of the changes (50 characters or less) and a more in-depth detailed description below.
00:35:18
Feel free to include bullets or code samples—anything that can help someone understand why you made a change. Often we'll ask programmers to squash their commits.
00:35:54
This makes it easier to backport changes and cherry-pick and keeps the Git log clear and concise. Generally, if your change is small with a test, that should be just one commit.
00:36:12
If you spent months on a feature and have a clean history, you'll likely get all your commits merged in without squashing into a single commit, as long as your history is clean.
00:36:38
Later on, we'll go over how to squash commits. 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.
00:36:53
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.
00:37:16
That said, smaller, concise changes are easier to parse and may be faster to get merged in. Please don't '+1' issues you want fixed or pull requests you want merged.
00:37:39
Only comment on a PR or issue if you have added insight—for example, if you've run the patch and confirmed that it fixes the original issue. Be sure to read all of the other comments first.
00:38:03
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.
00:38:29
Be proactive, not reactive when commenting on Rails issues. Yes?