Trevor Hartman's shared items
|
For many developers getting started with Git on Windows, one of the confusing features of Git is that the default editor for commit messages is Vim. While Vim is a great editor, many folks would prefer something a bit more user-friendly.
For those folks, we've created a great getting-started resource, GitPad. This is a portable, single-EXE program that will configure Notepad as your default editor for commit messages and other features such as interactive rebase, which lets you reorder and combine commits before you send them to others.
If you're interested, grab GitPad.exe from the Download page and run it, then restart your CMD / Bash shell window.
|
It’s International Talk Like A Pirate Day today, so you might want to add a custom validation to check if comments submitted in your application actually sound like they were written by a pirate. Right? Right. I thought so. Anyway, let’s create a validator with specs that don’t need to require the model every time they run, allowing them to be blazingly fast. Or, at least faster than what you did before.

Since we care about keeping our test suite nice and fast, we’ll try not to load the Comment model and anything else we don’t really need. Instead of throwing the tests for our validator in the Comment’s model spec, we’ll create a new one in spec/validators/pirate_validator_spec.rb and put a mock model named Validatable in there to test with:
class Validatable
include ActiveModel::Validations
validates_with PirateValidator
end
Running it right now (yes, without any actual tests) would end us up with a NameError, telling us ActiveModel is uninitialized. We’ll need to require it:
require 'active_model'
When running it again, we quickly find out the PirateValidator is uninitialized, since we didn’t create and require it yet. Let’s put an empty validator in app/validators/pirate_validator.rb (and don’t forget to require it in the spec):
class PirateValidator < ActiveModel::Validator
end
Now the spec actually runs without stumbling on any errors, so we can start writing our first test:
describe PirateValidator do
subject { Validatable.new }
context 'with a comment that sounds like a pirate' do
before { subject.stub(:comment).and_return('Ahoy, matey!') }
it { should be_valid }
end
end
Running the spec again, we get a NotImplementedError:
NotImplementedError:
Subclasses must implement a validate(record) method.
Ah, our PirateValidator doesn’t have a validate method yet, so we’ll just add an empty one:
class PirateValidator < ActiveModel::Validator
def validate(document)
end
end
Wait, what? Our first spec passes, since it asserts the Validatable object to be valid and our validator doesn’t do anything yet. Let’s add another test to give it some actual functionality:
context 'with a comment that sounds like a dinosaur' do
before { subject.stub(:comment).and_return('ROOOAAAR!') }
it { should have(1).error_on(:comment) }
end
Which causes another NoMethodError:
NoMethodError:
undefined method `error_on' for #<Validatable:0x007faa43462ec8>
That’s because we use should have(1).error_on(:comment) in our spec, and error_on comes with rspec-rails and we haven’t included that yet. error_on is in RSpec::Rails::Extensions, so let’s just require that:
require 'rspec/rails/extensions'
If we run our tests again, we notice that they’re quite a bit slower now. We could solve that by not using the error_on method and not requiring RSpec::Rails::Extensions, but I prefer using error_on instead of having to do assertions on the subject.errors array, but that’s completely up to you.
After requiring RSpec::Rails::Extensions, our spec starts running again and fails, because we haven’t implemented the actual validation yet. So let’s do that now:
class PirateValidator < ActiveModel::Validator
def validate(document)
unless document.comment.include? 'matey'
document.errors[:comment] << 'does not sound like a pirate'
end
end
end
And our test passes! We successfully implemented a model validator without actually loading the model in the specs. Now, getting it running in your model is up to you, but that shouldn’t be more difficult than getting it to run in Validatable.
If you have any questions or suggestions about this approach to test validators, be sure to let me know in the comments.. Matey.
It’s right there in the docs but I didn’t notice it until recently:
heroku pgbackups:restore DATABASE `heroku pgbackups:url --remote production` --remote staging
Boom! It transfers the production Postgres database to staging.
It’s much faster than db:pull, then db:push, which is what I used to do (like a sucker).
Setup:
git remote add staging git@heroku.com:my-staging-app.git
git remote add production git@heroku.com:my-production-app.git
heroku addons:add pgbackups --remote staging
heroku addons:add pgbackups --remote production
Create a database backup at any time:
heroku pgbackups:capture --remote production
View backups:
heroku pgbackups --remote production
Destroy a backup:
heroku pgbackups:destroy b003 --remote production
This is — by far — my favorite aspect of working at GitHub. Everything is asynchronous.
Chat
GitHub didn’t have an office for the first two years. Chat rooms (in our case, Campfire) is where things got done. Today we’ve moved into our second office, and Campfire is still where we get things done. There’s a reason for that: chat is asynchronous.
Asynchronous communication means I can take a step out for lunch and catch up on transcripts when I get back. Asynchronous communication means I can ask my coworker a question in-chat and not worry about bothering her since she’ll get back to me when she’s available. Asynchronous communication means I can go to rural Minnesota and feel like I’m working from the office like normal.
Pull Requests
The majority of our development workflow involves Pull Requests. I’m going to be going into a lot more detail about this in future blog posts and talks but in the meantime let me say this: living in a pull request world is sublime. Gone are days at companies with complicated branching strategies, with in-person code-on-a-screen code review.
If I want to add a new feature or impact the codebase, I’ll push a new branch, create a Pull Request for it, and my coworkers will review it 1) if they’re impacted by those changes, 2) interested in the subject, or 3) when they have ample time to check out my changes. At that point, we can run a partial deploy of that branch on different subsets of machines and try things out in production, and if everything looks good, merge into master.
With Pull Requests, I don’t have to drag anyone into a meeting that’s inconvenient for them and for me. There’s a good reason for that, too:
Meetings are fucking toxic
37signals originated “meetings are toxic” in Getting Real. I tend to loathe meetings even more than 37signals. I despise them.
Meetings are usually called when you need to hash something out. They tend to invite more people than necessary, and even if you’re pretty interested in the meeting topic, you’re still going to be frustrated because meetings pull you from doing actual work in order to talk about doing work. It’s easier to push a branch up, check out the diff, and then iterate on that diff rather than assuming you’re going to perfectly whiteboard system design ahead of time.
Beyond that, meetings are utterly forgettable. Even if you take meeting notes, you can’t capture them all. You make a judgement at that point in time as to what to write down for later. Then three weeks later you try to remember what wasn’t written down when it becomes apparent that that discussion was more important. You don’t have this problem with chat transcripts. Forcing people to reduce their otherwise rambling thoughts into concrete sentences helps focus discussion, too.
We’ll have meetings at GitHub, but I can count the number of full “meetings” we’ve had in the last year and a half on one hand.
The Zone
This all goes back to what I was writing about yesterday: you want your employees to be in “the zone”. Putting people in an atmosphere where they can only work for an hour before a team meeting pulls them out of that flow.
We’ve found that if you let responsible people handle their own priorities on their own timeline, they’ll end up getting the important stuff finished and still be able to work productively on other work.
Prompted by a passing thought about TextMate, I thought I’d make a comprehensive, accurate, unbiased, and irrefutable survey of text editors by way of comparison to locations in The Lord of the Rings.
TextMate: Minas Tirith

A once-great but now decaying city. Only the King has the power to renew it, but he is a long absent, indeed half-legendary figure—though there are persistent rumors that he is alive still in some distant land. In his stead, the city slowly falls in upon itself, kept in some sort of working order by its melancholy people. They can repair but not truly rebuild it, and they pray daily for the Return of the King.
BBEdit: The Shire

A quiet, long-overlooked land populated by simple folk who keep mostly to themselves. They are somewhat set in their ways, awkward in their manners, and superficially incapable of apparently simple tasks. Yet they hide deep roots and unexpected strengths.
Emacs: Fangorn

Vast, ancient, gnarled and mostly impenetrable, tended by a small band of ancient shepherds old as the world itself, under the command of their leader, Neckbeard. They possess unbelievable strength, are infuriatingly slow, and their land is entirely devoid of women. It takes forever to say anything in their strange, rumbling language.
vi: Moria

Like Fangorn, ancient and deep, with hints of the long labor of a great people. There is, supposedly, a monumental city of stone down here somewhere but it’s so dark I can’t see a damn thing. No, wait! A shaft of light illuminates some runes! They read as follows:
^C^C^X^X^X^Xquit
qQ!qdammit[esc]qwertyuiopasdfghjkl;
:xwhat
The Wizard translates: “We cannot get out! We cannot get out! They are coming!”
Microsoft Word: Barad-dur

No need to explain this one.
Scott Chacon (@schacon) has written a fantastic post regarding how we develop GitHub using GitHub itself. Do yourself a favor and head over to his blog:
http://scottchacon.com/2011/08/31/github-flow.html
If there's only one thing you take away from his post, understand that Pull Requests are not only useful when your code is ready for review, but can also be used as an extremely effective collaboration tool while features are being developed.

This graphic was inspired by this article written by Josh Wright who is a economic writer at EMSI (Economic Modeling Specialists, Inc - Moscow, Id.).
Epic comic version of all eight of the Happy Potter movies by Lucy Knisley.

Knisley is also offering large format images of the comic for personal use...for a limited time only.
Tags: books comics Harry Potter Lucy Knisley movies