terrbear.org
ruby! rails! kids! oh my! … and other fun from terry heath-
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.
-
Love/HATE on Heroku
Posted on February 23rd, 2010 No commentsI played a lot with Heroku yesterday, and after a good fight, got Love/HATE running on it.
I’ve talked to people about making a public Love/HATE site, using groupings or something, but I’m not sure if I like that use case. Someone also suggested making a way to enter feelings through a webform, which I outright rejected – that you have to know how to make an SSL key (or at least follow instructions) and put a binary on your system I think are good requirements for the users I want.
Anyway, if you want your own Love/HATE instance now, it’s easier than ever. Here’s how to do it:
- Sign up for Heroku
- Clone the Love/HATE repository
- Put all your users’ public keys in the public/keys directory
- Deploy to Heroku
- Done
If you want to add more keys, you’ll need to add them locally and then re-push the application.
-
Heroku Notes
Posted on February 22nd, 2010 1 commentI played with Heroku a good bit today, and noticed a few hiccups. It’s entirely possible that one of these issues is due to my misunderstanding, but I figured I’d at least note them here.
Overwriting Installed Gems
I needed a newer version of DataMapper than was available on Heroku, so I put that in the .gems manifest. That failed spectacularly at first, because as soon as I said “require ‘dm-core’,” I got the fantastic “cannot activate dm-core [0.xx] because [0.yy] is already activated.” [Sidenote: is this something Bundler solves? Because that'd be painfully hilarious]
But I still needed the require statements in my environment.rb, at least for local stuff. Solution? Wrap every require statement in a rescue block:
Require statements case sensitive
Two issues came from my magic_key_auth gem, and this was the first one I ran into. I was doing “require ’ssl.rb’”, essentially, and the file was named SSL.rb. This works on my machine and on my work’s instance of lovehate, but doesn’t work on Heroku.
I changed it to SSL.rb, and the file was found, and I was onto my next issue.
Items required in your app aren’t necessarily visible in your gem
I think this is something Heroku does to keep gems well isolated and from interfering with other gems, and all it really did was reveal a bug in magic_key_auth, but again, worth noting.
In Love/HATE I was requiring ‘ezsig’ (from EzCrypto), and then called out to MagicKeyAuth, which didn’t require that library (even though it uses EzCrypto::Verifier). This resulted in that module not working, and authentication always being false. I bumped magic_key_auth to 1.3 and now require ezsig at the top of the SSL module.
I figure I’ll be playing with Heroku a lot over the next few weeks, so I’ll keep things posted here.
-
Bling Bling gem management
Posted on February 20th, 2010 9 commentsWith Rails 3 and 2.3.5, I’ve been trying to use Bundler, but it’s been pretty painful so far. It’s not lightweight, and the only problem I really had with config.gem was that it had to load up the Rails environment to run, which meant if you had some code that was out in the open referencing a module or class in a gem that wasn’t yet installed, it borked (AASM did this to us). This made rake gems:install useless for lots of things.
After jumping through the bajillion hoops and kludges to get mongomapper working, RSpec started giving me some problems with bundler, so I set out last night to make something really simple, just to manage gems, Bling.
It’s not nearly as feature-rich as Bundler. It won’t unpack your gems or cache them, and it wants to install all gems to your system. So if those features are important to you (and they probably are to a lot of people), bling isn’t for you.
Bling just uses a yaml file (in Rails.root, for Rails projects) to keep up with gems, and lets you specify gems, their versions, their sources, and what lib to require (if not easily guessed as the gem name).
I bet I’ll have to add features to it as I go, but it’s solved the few problems I’ve had so far.
To get started, just do a “(sudo) gem install bling” and then in your Rails directory to a “bling init”. Once you’ve set up your bling.yml how you want, if you have any new gems, just do a “bling install”.
-
Scheduling Jobs with DelayedJob
Posted on February 19th, 2010 3 commentsFor a new project at work, I was tasked with reevaluated our async worker system. Previously we’d been using beanstalkd with a jobs model that used AASM for persistence and kept up with when something should be scheduled (and was scheduled with a rake task). After looking at the different things available, I decided DelayedJob was a better way to go, because it involved fewer dependencies (no more cron-rake work, no more beanstalkd) and had the persistence built in, instead of our custom code.
One shortcoming, though, seemed to be scheduling jobs. After thinking about different ways of keeping up with what jobs could be scheduled, I figured it’d make the most sense for jobs to just re-schedule themselves before execution.
That said, I didn’t want to put that in every class that had a perform() method as a boilerplate, “reschedule myself for 24 hours,” because it’s harder to maintain and grok what jobs are scheduled, and because it’s not nearly as readable.
Enter ScheduledJob, a mixin that gives you a run_every method on your class:
With this, you can create a class and include ScheduledJob, and then just say “run_every 24.hours” or whatever. Like this:
Hopefully this is helpful. I’ll need to write some tests, and see if the DJ guys want to use it on GitHub.
-
Magic SSL Key Auth Gemified
Posted on February 18th, 2010 No commentsMy boss told me he really liked posting to Love/Hate using the private-key-signing authentication method, and suggested I extract it to a gem. So I did.
You can find the gem here, and the GitHub repository here.
In addition to the authentication block (which just traverses a directory full of keys and checks if any of them match the signature), I added a Message class which makes it a little easier to sign a request (and by “little” I mean just that – it’s probably only saving you 3 lines of code).
I’d like to find a way to make it work with SSH-style keys as well, but this is a nice v0.1.1.
-
Spamming your IRC with Profane Weather
Posted on February 10th, 2010 No commentsAt work, we’ve gone to the newest technology: IRC. I like it for a lot of reasons, like the public conversations that (ideally) make everyone, and recently we’ve started letting bots tell us things in the channel. Any time anyone checks anything into GitHub or a build happens, we get a friendly message from GitHubBot or IntegrityBot.
Well, in a joke (and an attempt to make our workplace safer – Austin sucks when things freeze!), I decided we needed a WeatherBot. And where better to get the weather than, say, thefuckingweather.com?
So, if you use IRC (or really whatever, and this isn’t a hard script to write at all, but it’s hilarious, so I’m posting it anyway), just change the variables and you’re all set. Here you go:


