-
Sometimes I get carried away…
Posted on July 2nd, 2010 No comments -
Cap Release Notes
Posted on May 24th, 2010 No commentsOne of the really good things I learned from some guy, we’ll call Donkey, is to have everyone write down deployment dependencies in a file, so if someone goes on vacation or whatever during a deploy, you at least have an idea of what you should do.
I put it in /README, and separate everything by sprints. It looks something like this:
Even though everyone tries to remember to put things in there, there’s still a single point of failure, when the idiot who deploys it forgets to check the readme.
So, to prevent future self-indictments, I put a task that runs at the end of our cap script that prints the current release notes.
Ideally all of these are handled with a comprehensive deploy script, but that’s not always feasible/doable. Here’s the cap task, and if you make it the last thing that runs, you’ll get a friendly reminder at the end of every deploy for things you need to do.
-
Quick Tips
Posted on April 20th, 2010 2 commentsChrome view source
I ran into an incredibly confusing bug last week where I had some fields named user[field_x], but they were being posted to my Rails server as user[field_y]. I started to blame all sorts of crazy things (becoming superstitious in not knowing wtf could be happening).I pulled my field-level identity map (another blog post). I wrote some Rack middleware to intercept the parameters before Rails’s ParamsParser could touch it and make sure they were good. Fail. Nothing worked. After 2 hours of fighting with it, unable to reproduce in tests or anything, I realized I wasn’t viewing the source of the content I was actually viewing.
Chrome sends another, new request to the server when you say view source. This means that you’re not viewing the source from the page you’re viewing. If the pages are static or if there’s no way server state affects your page, then you’re good. Otherwise you might lose 3 hours.
This bug was painful enough that I’ve dropped Chrome as my default browser and am back on Firefox. I hope that by reading this you’ll think of it when you do view source on Chrome and nothing makes sense.
Git stash
I learned about git-stash over the weekend. It allows you to stash your changes on a stack, make some other changes to the codebase, do what you want with them, and then pull those stashed changes back out.Example use case: I branch before everything I work on, but eventually I have to merge stuff back in. So I branch to make feature X, get it written, then merge it back into HEAD. Unfortunately, tests are failing. I’m not going to push my changes yet, but something needs to be changed for another developer who wants something to run locally. git stash –keep-index; do changes; git push; git stash pop. Done and done, and no broken builds!
Timecop
A developer at our office was working with some relative time methods. These are inherently tricky to test, because if “next week” means “next business week”, you can’t just willy-nilly add 7 days to a day and do tests. Same with “this week”, etc.Instead of doing a bunch of complicated date math that would arguably make the tests just as scary as the code, we found Timecop, which lets you freeze time for your tests. You can say, “I want Date.today to evaluate to 20Apr2010″, and it will. This allowed for significantly simpler tests and saved a ton of time.
Avoid toggle actions
Even on some of the more popular sites on the internets, there are a lot of AJAX actions that don’t handle network failures well. Backpack (at least on my iPhone) just keeps the in progress icon going forever. We’re not doing anything super-critical with AJAX on our app, but we’d like to at least handle timeouts or failures gracefully.The simple solution is to check for the HTTP response code and act appropriately (2xx? Yay! 4xx? BOO!). We decided to do this, but realized that it’s possible that your request makes it through to the server, then your network fails, and you get a timeout. What do we say happened on the client side?
If they’re single-direction actions (e.g., marking something done), then you can just say “Something went wrong,” and not worry about changing it back or anything. If it’s a toggle, though, you can’t make any guarantees. “Something went wrong,” sure, but should the user try again? What if it only went through for the first 3 items?
As such, we’re no longer writing toggle_x actions. Now we’ll handle that on the frontend, and have negative_x and positive_x methods.
-
DelayedJob scheduling improvements
Posted on April 20th, 2010 No commentsLast week I talked with a guy who noted that the scheduling patch I’d blogged about for DJ was insufficient for scheduling something every day at 8AM. This is because running a job and then scheduling the job again after a success pushes the job out a little bit each time (maybe in a week or so it runs at 10AM, e.g.)
I thought about trying to make a run_at class method that would let you specify it, like “run_at ’8am’”, but that quickly fell through when I realized ’8am’ is ambiguous – 8AM every day? Every Wednesday? Every 4th week in July?
I fall inline with Brandon Keepers when I say that I don’t want to re-implement cron, because (imo) cron is one of the best scheduling tools out there already, and it comes packed onto every Unix distribution that ends with x.
Instead, I changed the run_every method to now accept a block, so you can pick the new best time to run if you’d like, or just keep using the same old (8.hours) syntax.
Think something like this:
If you like it, here’s the GitHub Repo.
-
My Vim setup
Posted on March 21st, 2010 No commentsMost people who’ve worked with me know that I really love my editor, Vim. I use it for pretty much everything. I don’t have a super customized setup, but I have a few plugins, and some of them got to be incompatible as they matured, so I’ve stuck with the less mature, super awesome ones.
This won’t be very helpful to most people, but in case you want a fuzzy file finder that works or an already-installed rsense, or you just want a bunch of themes, here you go (github link).
-
PeepingTom now ogling your Campfire
Posted on March 11th, 2010 No commentsI’ve been using Campfire at my new place, and decided PeepingTom needed to be included. So, now you can say:
And you’ll get Campfire notifications. New gem is out, so you should just need to update to 0.7. and install the broach gem.
-
DSLs and a ‘with’
Posted on March 3rd, 2010 No commentsYesterday I wrote PeepingTom, a RubyGem that lets you write a script in PT’s DSL to monitor different servers.
I was happy with it, but wanted to add a verify method that let you pass in a regex to see if things were (somewhat) rendering as expected. Unfortunately, this made the DSL a little harder to maintain.
Up until that point, everything was a single method, and nothing was chained together. My first solution was to change verify and ping to be methods on Site, which would make code look like:
Unfortunately, now things look like Ruby, and not like my oh-so-fun PeepingTom. After talking with my boss about it, we decided it should look something like:
This poses a little problem, because I already had a site method. Also, just a sidenote, Ruby parses these things right-to-left, so that statement is equivalent to verify(site(with(/hello/))).
So the first thing I needed was a with method. It turns out this is really easy to write, and isn’t even necessary, but it makes the DSL a lot more readable:
But then I needed to do something with my site method. The existing site method creates and registers a new site with PeepingTom. Watch out, here come the aliases:
Note that this means new watch blocks need to get rid of the |site| part. That’s now a method that proxies things out to the site that you expect to be iterating over. It makes it look a little more like English, too. Win-win.
I’m pretty happy with PeepingTom now; I think the only addition in the next few days will be a Campfire channel.
-
Flickr Screen Saver
Posted on March 2nd, 2010 3 commentsSeveral months ago I wrote an app that scrolled the last 500 Flickr pictures from our account across the page, using jQuery.
I did it as a good way to send out pics from our trip, and because jQuery makes things like that ridiculously fun.
Anyway, I had the source closed, because there were API keys and things on it. I decided tonight to buckle down and read about how to permanently delete things from a repository (hopefully successfully!), and open sourced it.
Here’s my instance of the application, and you can find the code to roll your own version on GitHub.
-
Peeping Tom: A free (open source) site pinger
Posted on March 2nd, 2010 11 commentsThere are a lot of services out there that ping your site and alert you when it’s down. Unfortunately, most are free only for 1 site or server. They do provide nice things like metrics and whatnot, but I don’t really care about that (we have other tools that measure performance and analytics); I just want to be woken up if a server goes down.
So this morning (ironically, without internet access), I wrote Peeping Tom. I’m planning on adding a few more checks, like looking for a special string or whatever, but right now it just makes an HTTP GET request to a URL you specify, and can alert you over different channels (right now IRC or email) when something screws up.
It’s the first DSL I’ve written, which might be my biggest reason for writing it and not just writing a quick script to ping every site.
You can install it and get started just by doing a gem install peeping_tom, and check out the source at GitHub.
-
Migrations with Mongo (and MongoMapper)
Posted on February 26th, 2010 7 commentsI’m working on an application (which you’ll get to see soon) with another guy, and he introduced some timestamps to a MongoMapper model after some of those models had already been coded. As a result, the first time I tried to visit a page with my user, I got a sweet NoMethodError, because apparently nil doesn’t implement strftime.
There are lots of ways to solve this problem, but it’s one that doesn’t arise nearly as frequently on SQL databases (I hypothesize…) because you have migrations where you can set default values for the schema.
When we decided to write our new app in Mongo, one thing that worried me would be data transforms down the road. How do we keep up with those? Do we just create rake tasks and run each one, noting them somewhere in a textfile? That sounds kind of awful:
8.3
* run rake:transform_user_emails to downcase emails
* run rake:default_user_nicknames8.4
* run rake:user:canonicalize_phone_numbersThis gets out of hand in a hurry.
Anyways, in my MO of looking on the first page of Google, not finding my answer, and writing something that does mostly what I want, I give you Mongrations.
Before I say anything else, I’ll tell you that I would love forks and fixes and bug findings and I know I need to write tests – but I’m pretty sure no matter what anyone does, Mongration is going to stick.
If you install the plugin (it needs to be a MongoMapper backed application), and change your vocabulary to use “mongration” and “mongrate” instead of “migration” and “migrate,” respectively, you have pretty much what you had with ActiveRecord’s migrations, only instead of schema changes, you just manipulate data.
I think this is actually a fairly pure solution. While there were problems and gotchas with integrating schema changes and data changes in the same set of migrations, I think MongoMapper skirts that with the schema being solely defined in the models.
It’s entirely possible I’m overlooking something ridiculously easy, so feel free to tell me as much if you think so.


