Garbled

Scenes From the Post-apocalypse

I’m on a bit of a hiatus from role playing because we have a new born at home, now. Until she’s easier to deal with in the evenings, I don’t really want to stick my wife with bed time for the 3-year-old and the 3-month-old all alone while I tell stories with my friends. Seems like kind of a jerk move.

But I’ve been jonesing really hard for it. And since I learned what Apocalypse World was, my group hasn’t actually gotten a chance to give it a good, honest play.

So, since I’m supposed to “daydream some apocalyptic imagery” and be “developing [my] apocalyptic aesthetic”, as well as “to cultivate an apocalyptic aesthetic in [my] players too,” I started emailing random snippets of Apocalypse World inspired imagery to my players.

In an earlier stage in my career running role playing games, I might have hoarded these, worried that I wouldn’t be able to come up with something similarly cool later, and confident, for some reason, that I’d be able to remember this stuff well enough to use it at the table. But, like, what?!?

At any rate, I thought someone on the internet might find them interesting, entertaining or useful. I’ve cleaned them up just a little from the original emails.

The Ghost in the Jungle

The vegetation here is dense. Everything smells like rotting plant matter. The light level varies wildly, based on how much wan, green sun filters through the canopy. Everything that’s not a dark brown is tinted some shade of green. The trees dwarf everyone. They’re definitely taller than any building in the hardhold, and wider at the base than Vee-dubb’s van is long. The air is still as death; the only things moving are the bugs, bzzzing and stinging, nearly invisible to the naked eye.

The lot of you hike on. The heat is oppressive. It’s not like the sun bearing down from on high out in the Tire Wastes. This is a more encompassing, much wetter heat. It is hard to breathe, and sweating does no good at all. Everyone is drenched and gross.

Fleece is the first one to spot it: pale white and hard as rock, covered in fine spiderwork of cracks but feeling no weaker for it. Beneath the turtle shell of ceramic is a mass of black machinery, dead and busted with grubs and mushrooms growing underneath. After that, the frequency of seeing smooth white amid the vines and roots increases steadily; you’re headed the right way.

Your little group walks in silence, minds on your feet and the stifling humidity. No one is in the mood to talk any more. Then there’s a funny snicker-snicker-snicker sound and Jollyby cries out, blood erupting from exit wounds in his chest. He collapses into a giant fern, staining the leaves red and doesn’t even gurgle. Everyone freezes, and you can see a white dome, with black metal peeking out from underneath it swiveling slowly away from where Jollyby was standing, not as dead as you thought.

What do you do?

This was the first one I sent out, and I didn’t explain to my players what I was doing, so one responded with this callousness:

Shit. Not again.

A flare to the “face” always fucks with the heat-sensitive abominations. At least for a few seconds.

Like bouncing a baseball off the wall in the hardhold. Hit the same spot, again and again. Practice makes perfect, they say.

I visualize that spot as bein’ right in the center of that black maw of metal and put the flare right on the money.

Should buy me a few seconds. At least enough time to get under the ferns and start circling my way around to Jollyby.

I like that necklace he been wearin’.

First come, first serve.

Savages, Cannibal Savages

So, Jav, Kartak, you’re out there, now, among the Tire Wastes at mid-day. Sucks for you. The hidden mouth of the tunnel recedes at a pretty good clip, if you do say so yourselves, given your current state of abuse. The heat rolling off the piles of half-melted black rubber starts to get to you real quick and you realize that, while the tunnels were full of murderous, howling savages, bent on eating and cooking you (in whatever order), at least they kept the sun off. That shit is brutal.

Then you hear it: the hue and cry of a cannibal pack calling for your blood. Looking over your shoulders, you can see between mounds of rotten tires a group of a half-dozen or more of the fuckers, armed up with random bits of sharp and heavy instruments of violence.

If you’re quick, you could maybe squeeze in under some of the local “geography” and hide it out, but it means getting in there among all those tires that have been baking in the sun for hours and hours: even if you weren’t dehydrated from your imprisonment, not a pleasant experience. Other than that, it’s mostly either stand and fight, or hope to outrun them to where Vee-dubb’s waiting with her van. If she’s waiting with her van.

What do you do?

Another player responded this time, with this visciousness:

Jav slips a holdout from the small of his back and puts a round through Kartak’s femur while his former friend stares at the hounding madmen. Tears trace ephemeral trails across filthy cheeks as he pushes towards the pickup. With body and lungs burning from exertion (the ambient vaporized rubber helps too), he promises the world will know the noble end of Kartak and how he sacrificed himself to save his dear friend Jav.

The Market

So you’re sitting out there the rest of the night, watching Imam’s store front. Eventually, the angry red circle of the sun starts to creep up into the sky, pouring pink light over everything. Before the sky is much light at all, people start to trickle into the market space in ones and twos. Some are setting up shop, there’s Ula, getting water from the well for her folks; her dad’s been sick recently with a fever. Dustwich rolls his food cart up next to the news board and starts getting it going. Slowly, the market comes to life.

It’s a while before the first strangers show up, mostly folks staying at Chin’s flophouse. The first travelers won’t arrive until late afternoon, generally.Then you spot it: someone you don’t recognize, a scrawny bald someone in a nomad’s poncho, looking around furtively. They back casually down an alleyway next to Imam’s that you know for a fact is a dead end with no doors on it.

What do you do?

The Mead Hall

You open the doors and there Swiss Miss besits her throne: leather clad and radiating danger. At her feet sit two waste hounds, snoring with eyes open. The air is smokey from the torches lining the walls and the large rectangular fire pit that runs the center of the room. At two long tables, her gang sits at their leisure. All are men and women of violence, armed with guns of wide description and pointy instruments of death both vile and various. All eyes turn to you as you enter.

What do you do?

Brushfire

They call it opening your mind, but it’s more like the maelstrom burns the world away around you. Your body turns to ash and blows away in a furnace wind. Everything around smells of charcoal and gasoline, the light is all orange and red with dark, oily shadows.

As smoke billows through your consciousness, you see that Keeler isn’t as alone as she looks. She’s got a line of compatriots lying low just behind the rise she’s standing on, five or six of ‘em, all armed.

And now that the flame has shed some light, you have to feed the fire: When was your first kiss? With whom? Why don’t you like to think about them?

The Settlement

The top of the ridge is hot and dry under your chests. Passing the rifle between you, you can see some better detail about the settlement through its scope.

There’s some amount of walls, but not all the way around: either not finished being built or some damage done. There’s a collection of buildings inside, adobe (the same color as the surrounding wastes) and scrap metal, mostly. Not of uniform heights, but all one story.

There’s a kind of square in the middle of town. Around a well and a market, maybe. A complex arrangement of canvas and plastic sheeting suspended, taught, between ropes and wires like sails provide shade to the square. Or would, except that substantial portions are ripped and busted, hanging down and blowing limply in the hot wind.

And that’s the other thing: There’s no people in sight. Did they see you and they’re hiding? Are they all gone? Did something bad happen here? Is it still happening? If anyone’s left, would they assume you’re here to help or hurt? Would they cower or attack? From this distance, there’s no way to know.

So.

Do you go on down there, or try to work your way around and move on or what? What do you do?

HAL Client Update: Cetacean

After writing my last post, I used the code presented therein in production a few more days and realized I wanted just a smidge more power. Specifically, I wanted it to handle HAL’s embedded resources. So I added that and then the other night, I pulled it out of that project, broke it up into files, named it after sea animals and pushed it to RubyGems.org. Introducing: Cetacean.

Now, I realize my last post was all, “Do we need HAL clients?” and shit. But let’s be real, even 42 lines is a HAL client. Or… whatever, depending on what your definition of “client”. In fact, the design of Cetacean is basically driven by thinking about what “client” means and what I felt like I needed a tool for with respect to HAL documents.

Basically, Cetacean helps you deal with HAL documents, it doesn’t really help you with hypermedia APIs. The general work flow is that you make a Faraday client (configured however seems best to you) and make a request to some URI. You feed the response to Cetacean and then operate on it. You might get a URI out of it (from a link, say), which you can then feed back to your Faraday client, which response you can feed to Cetacean, again, etc.

Perhaps an example would be helpful:

1
2
3
4
5
api = Faraday.new('https://api.example.com/') do |faraday|
  faraday.headers['Accept'] = 'application/hal+json'
end

root = Cetacean.new(api.get)

At this juncture, you can ask root about some stuff. It’s an instance of Cetacean::Responce. It proxies some methods back to the Faraday::Response, and otherwise is mostly sugar for getting things out of the HAL document.

1
2
3
4
5
6
7
8
9
root.success? # => true
root.status # => 200
root.response # => The `Faraday::Response` you passed in.
root.body # => '{"foo":"bar","_links":{"self":{"href":"/"},"users":{"href":"..."}}}'
root.hal? # => true
root.attributes # => { 'foo' => 'bar' }
root['foo'] # => 'bar'
root.links # => { 'self' => { 'href' => '/' } }
root.get_uri(:self) # => A `URITemplate` object for you to manipulate.

So if you want to follow the ‘self’ rel, you use get_uri method to get a template, do whatever you want with it (probably to_s and expand are the most common cases). And then… do whatever you want with that. Make another HTTP request? Get it tattooed on your stomach? Cetacean doesn’t really care.

Continuing on, imagine further interactions with an API. Notice that at each stage, Cetacean deals with the HAL, and then gets out of the way.

1
2
users = Cetacean.new(api.get(root.get_uri(:users).to_s))
user = users.embedded(:users).first

Assuming that the ‘users’ rel was some document that embedded an array of documents under the ‘users’ rel, user is an instance of Cetacean::EmbeddedResource. It behaves mostly like a Cetacean::Response except is doesn’t have a request object to proxy or refer to. Ideally, you shouldn’t have to keep track of which came from where once you’re dealing with a document.

1
2
important_blog_post = Cetacean.new(api.get(user.get_uri(:post).expand(id: 2)))
interesting_blog_posts = Cetacean.new(api.get(root.get_uri(:search_posts).expand(q: 'interesting')))

Just another couple of examples of following different links, both of these requiring expansion.

This is certainly more wordy than using a more featureful library like Hyperclient or whatever. I feel that this gives you a lot more control over how you deal with the documents you get back. If you unexpectedly get back an invalid body, Cetacean won’t barf trying to parse it like JSON, if you get back 'image/jpeg' instead of 'application/hal+json', Cetacean makes it easy to deal with that however is most appropriate. If you need to do some fancy, weird-ass configuration of Faraday that’s super specific to your use-case, then you don’t have to worry about what a middle-man library might do to your connection configuration.

Anyway, I guess I wrote another gem. If you use it, I’d be interested to hear about it. If you want to help, feel free. It’s on Github.

Thinking About HAL Clients

More and more, at work, we’re talking about service oriented architectures. Mostly, these are very small apps that deal with just a few concerns. Since we foresee having lots and lots of these little mini-services, we decided we’d need to make some decisions up front about how they’re inter-operate. This is sort of in the spirit of convention over configuration.

More to avoid having to re-make the decision about what shape responses from these services should take every time we start a new one than for any other reason, we decided that all these services should speak HAL. This way, we can get good at dealing with HAL and once you grok how to talk to one service, that knowledge will transfer readily to others. We picked HAL over other formats we considered basically by typing out an example response off the top of our heads and then seeing which existing format looked the closest. So scientific.

Since that time, I’ve spent a fair amount of time monkeying with HAL and related hypermedia issues. There are a lot of angles, here, but I wanted to start off by writing about the idea of a HAL client.

Hyperclient

Initially, I started using a Ruby library called Hyperclient. It basically abstracts parsing and navigating HAL documents and making requests to the links in them away from the developer using it. At first, I thought this would be great. However, the more I used it, the more I felt like it was doing more to me than for me.

In it’s effort to keep the developer from needing to know the HAL spec front to back, it is pretty complicated and has a lot of corners for edge cases to get stuck in. And, really, since HAL is so readable, it ends up just mapping hash access to method calls in a lot of cases.

DIY

I really hope I don’t have a NIH complex, but… I do use Arch Linux because of the level of fiddling it allows with how my laptop behaves… and I tune and tweak my .vimrc and .bashrc so my environment is just so. Thus, it shouldn’t really be surprising that when I wanted more control, I decided to build something from scratch (sort of).

The other day, after encountering some weird interaction between Faraday, Hyperclient and certain features of WebMock, I decided to see how hard it would be to rip Hyperclient out and replace it with something dumber and simpler. After talking it over with the team, we decided the best course would be to time-box it to a day.

Here’s the 42 lines I replaced Hyperclient with:

hal_response.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
require 'forwardable'

class HalResponse
  extend Forwardable

  def_delegators :response, :status, :success?, :body
  def_delegators :hal, :[], :fetch

  attr_reader :response

  def initialize(response)
    @response = response
  end

  def hal?
    response.headers['content-type'] =~ %r{\Aapplication/hal\+json}
  end

  def links
    hal['_links'] || {}
  end

  def get_uri(rel, expansions={})
    URITemplate.new(links[rel.to_s]['href']).expand(expansions)
  end

  def attributes
    hal.except('_links', '_embedded')
  end

  private

  def hal
    @hal ||= parse_hal
  end

  def parse_hal
    self.hal? ? JSON.parse(response.body) : {}
  rescue JSON::JSONError, TypeError
    {}
  end
end

The way this works, is you build your own Faraday object, you make the requests yourself, then you feed the response into a HalResponse constructor to monkey with it. If you want to follow a link, you call get_uri and feed that result to your Faraday object. A short example:

example.rb
1
2
3
4
5
6
client = Faraday.new('http://example.com')
root = HalResponse.new(client.get)

posts = HalResponse.new(client.get(root.get_uri(:posts)))
search_results = HalResponse.new(client.get(root.get_uri(:search, q: 'Ruby')))
new_post = HalResponse.new(client.post(root.get_uri(:create_post, title: 'Blah', body: 'whatever')))

It’s important to note that my 42 lines don’t deal at all with embedded resources and are tailored to handle cases presented by a specific API of a specific service I’m coding against. But that’s actually part of my point: Do we need HAL clients? Is the document format that hard to grok?

Since HAL (and other hypermedia types) rely on the semantics of HTTP pretty heavily, it seems much more important to have a robust HTTP client. Dealing with the specially-formatted response bodies seems like a separate issue to me. I may expand the above class as I continue to use it in production, but I kind of like the wordy, do-nothing-for-you kind of way it works.

Ben’s Gem Maintainer Handbook

At work, recently, we were discussing internal gems and how to deal with releases and crap. Of course, because this is a topic, I have opinions on it. I can’t help myself.

Actually, someone was like, “Why do we do it this way,” and someone else was like, “I don’t know, ask Ben,” and I was all, “Ranty rant-ra–You know what? I’ll just write a blog post.” So, now you’re all inflicted with this. You have Bob and Ryan to thank for it.

SemVer

So this is pretty simple, and other people have explained it better than I can. You should be using Semantic Versioning for your gem. You can read the full spec, but I’ll break down the general idea real quick.

Version numbers are 3 segments in the format major.minor.patch. You increment the major version if you’re shipping any backwards-incompatible changes. You increment the minor version if you’re adding backwards-compatible new features. You increment the patch version if you’re just doing bug fixes. When you increment one segment, all the segments to the right reset to 0.

This way, a consumer of your gem can tell by looking at the difference in version number whether the changes should be backwards compatible or not (major version changed) or whether that new exciting feature they’ve been waiting for might be in (minor version changes).

Version Number

If I’m in a REPL with your gem loaded, I should be able to ask it what it’s version number is, so put the version number in the code. Ideally, I think, it should be a string of the numbers. Some people seem to like to have MyGem::VERSION be how you get it. Personally, I like to provide MyGem.version, as well.

If you do this, you can then refer to it in your gemspec, where you officially set the version of the gem. You should put it alone in it’s own file, though, so you don’t have to load your whole gem just to interleave your version number into the gemspec.

CHANGES.md

Keep a changes file. There are a few file names that seem to be widely recognized, but I like CHANGES.md the best. I prefer not to keep this information in the README just to avoid cluttering that file for people who are interested in documentation or contribution guidelines.

My CHANGES.md file has a <h1> at the top that just says ‘Changes’. I don’t have strong opinions on that part. However, the following bit I have very strong opinions on.

You have several sections, following the title. Each section is an <h2> that is the version number of a release followed by a bulleted list of the changes since the previous release. Each item in the list should be a brief summary of a bug fix or feature–no reason to replicate your entire commit history here. Personally, at least for publicly available gems, I like to also credit the author of the change by name.

Each of those sections should go in descending order of version number so that the newest stuff is at the top. There’s also a special version: ‘Unreleased’. Between releases, you don’t yet know what your next version number will be. Will you add a new feature? Break backwards compatibility? Who knows. So I log changes as they’re merged to an ‘Unreleased’ section of CHANGES.md. This way I don’t forget what’s in and it’s easy for someone to see what kind of stuff is coming in the next version (or what’s in master that isn’t released).

Rarely do people sending me Pull Requests add their own entry to CHANGES.md, so usually, I’ll merge their code, and then go add an entry for their change myself. However, I would be delighted if a contributer wrote their own entry.

Releasing

The point under discussion at work fits into this category. I always bump the version number a lone commit, apart from any feature branch or other changes. I feel like there are a couple of advantages:

  1. It provides you an opportunity to review CHANGES.md in it’s final state as you decide how you need to change your version number for release.
  2. It means that you can add a feature that, as you write it, seems like it’ll be the last one before a release and then at the last minute think, “Oh, just one more,” and still have the version bump be the last commit before release.

Relatedly, tag your release commit. I just tag mine with the version number, but you can put a ‘v’ in the front if you like. I don’t care. The point is to make it easy for a consumer of your library to go to Github and easily find the commit that matches whatever released version they’re using. Make sure to push that new tag up to Github.

When I’m ready to release, I do like this:

  1. Review CHANGES.md and select a new version number.
  2. Update the version number in the code.
  3. Change the ‘Unreleased’ heading in CHANGES.md to the new version number.
  4. Run gem build my_gem.gemspec. If it doesn’t build right, stop and fix it. Don’t commit the new version number as part of that fix.
  5. Commit the version bump changes.
  6. Tag the new commit with the version number.
  7. git push && git push --tags && gem push my_gem-1.2.3.gem
  8. rm my_gem-1.2.3.gem.

I’m sure the above could be automated, but it never seemed like enough of a pain in the ass to be worth my while.

So them’s my opinions on gem maintenance. If you tweet or email me questions, I’ll update this post with answers.

Never Type Bundle Exec Again

Sometimes people complain about having to type bundle exec before every freakin’ command in a Ruby project. Honestly, I think the benefits Bundler gives you outweigh that downside by a huge margin. However, there is good news: You can use this one weird trick to never type bundle exec again.

OK. It’s actually an option of two weird tricks. And then a bonus trick. This joke is ruined.

Somewhat Involved, Works Everywhere

If you’ve got Ruby installed, you can do this trick. It’s a little hacky and comes with some downsides.

First up, make ~/.bundle/config look like this business:

~/.bundle/config
1
2
---
BUNDLE_BIN: bin

This will tell bundle install to always run as if you passed the --binstubs=bin option. Now, when you bundle up a project, it’ll drop wrapper scripts into the bin directory of your project that ensure the correct Bundler environment is set up before running their normal stuff.

As a courtesy to everyone you share a project with, when you do something like this which will litter your project up with files to do with your personal set up, you should make sure you don’t commit them to anything. So go to your global git ignore file and make sure it includes this:

~/.gitignore
1
bin

Here’s downside number one: You will probably have to override this for specific projects. For instance, gems often ship with a bin directory with files to do with the gem. You’ll want to make sure those aren’t ignored. If you explicitly git add them, they should be tracked by git thereafter, but you have to go out of your way. In particular, a Rails project contains wrappers for rails, rake and bundle in the bin directory and those should be committed to the repo… and not over-written by your bundle install binstubs. So take care, there.

At this point, you could stop, except you’d have to type bin/ in front of every command, instead of bundle exec. Sure, it’s shorter, but still annoying. The next thing to do might be to prepend ./bin to your $PATH so that your command line looks there for commands first. Downside number two is that there are some negative security implications to this, so I for sure don’t recommend it for servers, but I’ll leave it up to you whether you do it on your personal dev machine.

Less Involved, Requires rbenv

“But, Ben,” you say, “I want to be just like you so I use rbenv.” Well, you know, that’s flattering and I have to say you make some good life decisions, friend. Let me tell you about some nice tools.

If you use rbenv (and I like it so far), then you can take advantage of it’s plug-in system. Probably you’re already using ruby-build as a plug-in to install Rubies. I have two more for you: rbenv-gem-rehash and rbenv-binstubs.

You can read more in the READMEs of those projects, but in brief, you install them to your ~/.rbenv/plugins/ directory, then make your ~/.bundle/config look like this business:

~/.bundle/config
1
2
---
BUNDLE_BIN: .bundle/bin

Undo any steps you may have taken above (like ignoring bin) and shit should be taken care of for you. Now you won’t have to rbenv rehash or bundle exec! Rockin’.

Note: The .bundle directory of a project that uses Bundler should already be ignored in git, so tossing your binstubs in there should protect you against barfing them into a repo unintentionally. Rbenv-binstubs handles making sure they’re in your path for you.

Bonus Trick: alias be

I kinda lied to you. I’m sorry. You may still have to type bundle exec on occasion, even with nifty rbenv-related goodness. Things that aren’t gem commands don’t get binstubs from Bundler: notably, the gem command. For me, this most commonly comes up when I want to see what the gem list is that Bundler’s resolving.

Doing gem list will show you all gems installed for the active Ruby. No help. So you can do bundle exec gem list and Bundler will do it’s path-related mojo and then execute gem list for you. Nice, but typey. So the bonus trick is to add this line to your .bashrc (or .bashprofile or whatever madness your system might use):

~/.bashrc
1
alias be='bundle exec'

Now you can just be gem list, which sounds sort of like an existential confusion to me, but involves less typing, so… win!

Final Caveat To All This

One last thing that’s important to remember with all this: whenever you do this kind of optimization of your local system, whether it’s installing vim plug-ins or putting set -o vi in your .bashrc or whatever, you have to keep in mind that it’s not portable. When you shell into your alpha server to tail some logs or debug something, you won’t have this stuff. So while you may never type bundle exec again locally, you should remember that it’s still there in the background, and remember that on machines you didn’t set up, you’ll still need to type it.

Social Justice Is Made of Empathy

I was listening to episode 101 of The Ruby Rogues with Ashe Dryden as the guest. The episode includes some of what social justice folks call “101 work”, which is the sort of entry-level explanatory teaching that it takes to get someone from something like “Isn’t a code event specifically for girls, sexist?” to, “That’s not cool”.

Anyway, I really liked the episode, and I recommend you go give it a listen, especially if you’re new or entirely unintroduced to the topic of social justice. They talk a lot about feminism specifically, since there’s been several high profile events related to it this year so far, but they talk about intersectionality, too (like what is is, if you don’t already know).

In this post, I want to address one specific topic they talked about. One sentence, in a way. As part of a discussion about calling people out on comments that are exclusionary or otherwise inappropriate, Ashe was saying that simply saying, “That’s not cool” can have a powerful effect, sending the message that that kind of thing isn’t socially acceptable within the context it was said and that most people will modify their future behavior accordingly.

As a follow-up to that, Avdi Grimm asked if there was ever a time that you’d say something, someone would point out that it made them uncomfortable (or whatever) and you apologized, but decided that whatever the statement was, it was so much a part of who you are, that you knew you’d say it again in the future. I’m paraphrasing, here, hence the lack of quotes. In answer, they talked about a few things, but someone said something else and the conversation kind of got distracted. However, I’d like to address it somewhat.

The flippant answer to the question is, “Of course.” I mean–if I say something like, “I really, really like wearing argyle socks,” and you’re like, “That comment offends me,” there’s not a whole lot I can do for you. Assuming I don’t just think you’re trolling me, I would probably apologize because I don’t like to make people feel bad, but… I seriously wear argyle socks every day. I love that shit. I am likely to express that idea in the future.

But if we’re talking more seriously, thinking of a comment that actually addresses people in some way (instead of socks), I think the idea becomes really interesting (I’ll leave it as an exercise to the reader to come up with an appropriately offensive remark). If you say something offensive or exclusionary, I’m going to give you (and me) the benefit of the doubt an assume it’s because you didn’t realize it would be so. You’re a good person; you don’t enjoy ruining other people’s days.

After making your comment, someone in the group (or near the group over-hearing) says something to you about it being inappropriate and you apologize. Great. How, though, do you get from, “I didn’t realize that was racist,” to “but that thought it so intrinsic to my being that I don’t care and I’ll say it again later”? The only method I can see to get there is if “I am an empathetic human being who cares about others” isn’t a part of how you view yourself.

Personally, I am bad at empathy. I have a hard time reading people sometimes, but I still like to think of myself that I’m empathic. If I manage to figure out that someone was hurt by me, I feel bad. I want to make it better. And in the scenario laid out above, we’re removing that, anyway. Above, I’ve said something and someone flat out told me what was going on, in case I didn’t pick it up.

So if some aspect of that remark is intrinsic to my self image and empathy is intrinsic to my self image, then they’re in competition now. And, I guess, you have to be real with yourself about which one is actually more important to you. Possibly with observation, not introspection. Personally, I’d like my personal narrative to be more about being empathetic to other people than about protecting my ego or whatever.

So, I guess what I’m saying is: If someone near you points out that something you said is out of bounds, and you find yourself saying, “No, my gay friend always jokes around with me that way and he’s not offended,” then you are failing at empathy. At least from the standpoint of someone who is basically sitting on a mountain of privilege (me), social justice isn’t about gay couples wanting to “ruin marriage” or women wanting to invade and displace all our special boys club professions and hobbies or anything like that: It’s about giving a shit about other human beings.

LOL Civil Liberties

The other day, Carol Nichols linked to an interesting article. It is a transcript of a conversation between John Cusack and Jonathan Turley about politics. We traded a few tweets and I said I’d get back to her, but… tweets are short and shit is complicated and, here’s a blog post. I don’t generally talk a lot of politics here, but, screw it. It’s my blog.

So, before I read the piece, Carol was talking about deciding not to vote at all for the Presidency and some stuff about not letting the good things a person has done excuse the lines they’ve crossed. Hopefully I’m not mischaracterizing her statements due to some misunderstanding on my part. In any case, I’d said something in reply about choosing the lesser of two evils (I don’t by any means consider myself a Democrat, but the Republican party is… way off the rails these days). Then Carol said something I hadn’t really considered: If both options have crossed a threshold of minimum-allowable-bad, then choosing the least-bad rather than demanding better enables increasing badness. So I said I’d read the article and get back to her with my thoughts.

Having read the thing (you did, too, right?), I have to say I see what Carol was saying much more clearly. Surprise, surprise. The thing that stood out to me was that I’d heard about Obama’s whole authority-to-assassinate-US-citizens thing when it came out. I heard about it and thought, “That doesn’t sound right.” And… then forgot about it. Or, more accurately, I filed it under “Bad Shit In The World That, Thank Eris, Doesn’t Affect Me” and then got all riled up about health care and tax breaks for the rich at the expense of the rest of us, etc. How did that happen? How did I let that happen? Talking about how the Whitehouse has sold us ideas is true in a sense, but also false in the sense that it can sound like we are actors without agency. They don’t have some kind of mind control over us. I have to accept that I wasn’t really looking at the world as clearly as I’d like or as I’d been telling myself I was.

Some stuff that’s bad in the world and doesn’t affect me, I can live with ignoring (I think this is only pragmatic). But some stuff should go in the other file: Not OK, Damnit. Things like Sexism, Racism, Child Abuse… and The President of the United States deciding he has the authority to unilaterally assassinate people (whether US citizens or not). Ugh. So, OK. I’m upset about that now. And also upset that I wasn’t appropriately upset about it when I first learned of it. That feels like progress.

That issue when paired with the whole unprosecuted war crimes thing and the implications that has for mediating international interactions and Nuremberg precedents really drove Turley’s question home to me: “Morally, are you comfortable with saying, ‘I know the administration is concealing war crimes, but they’re really good on healthcare?’”

And, you know what? That’s a really depressing question to be in a position to even be asked. War crimes are serious shit, you know? They’re the list of things that we’ve agreed we don’t even wish on our enemies. It’s the list of things that super heroes won’t stoop to because “if we do, we’re not better than them.” They are exactly the stuff that we’ve decided the doing of differentiates the Good Guys from the Bad Guys. So if I’m OK with the POTUS doing them, or allowing them to be done or protecting those that did them, then I’m comfortable being a Bad Guy. And fuck that.

So, I guess we’ve established that I feel like there’s a problem and that I’m not happy with either of the candidates put up by the US’s major parties. The next question is: What do I do about it? As part of this discussion, there is the idea that voting makes you implicitly culpable and that if you refrain, you can be said to be calling for better candidates. The culpability angle, I agree with. But I’m also really wary of casting inaction as activism.

I am not an activist by nature; I’ve never been to a rally or demonstration. I’ve never occupied anything except various chairs and sofae mostly in front of video screens. I am also, by nature, physically lazy. So anything that sounds like something I’d do doesn’t seem like it should count as activism. Like changing your Facebook avatar to reflect some fad cause, or writing a ranty blog post about politics (heh). So on that front, I find the “so don’t vote” thing kind of… dissatisfying.

Also, there’s a sort of game theory issue, here. And this may be an illustration of why we’re all just screwed, rather than a justification for an individual’s actions. But this also bugs me: If I was planning on voting for Obama (I was), and now I don’t (undecided, still), then I am letting someone else decide which candidate wins. If I do vote, then I’m at least increasing the chance that the fate I’ve selected is the one I’ll suffer. It feels very Prisoner’s Dilema-ey to me. That’s not an excuse, but it seems to predict that getting a low enough number of people to vote such that the parties notice there’s a reason is infinitesimal.

Of course, on the other hand, not voting is throwing away a resource in a sort of a similar way as voting for a Democratic Presidential candidate in Texas is, so my vote or non-vote is actually pretty unlikely to affect which way my state’s electoral votes go. If I lived somewhere swingey, it would matter more. I guess the decision comes a little more easily, then.

Anyway, I’d love your (thoughtful, respectful) comments and reactions. Especially, I’m interested in help expanding and deepening my thinking about this stuff. I’m sure there’s prior art on some of these ideas that I’m unaware of.

Install Ruby Enterprise Edition With Ruby-build on Arch Linux

I run Arch Linux on a computer, if I have a choice. I recently installed it on the MacBook Air my employer bought me (which saga is another post entirely). One of the things that I like about Arch is that they don’t do big releases every X-period of time; the package repository is updated on a rolling basis. So I can get the latest version of whatever much sooner than my Ubuntuan brethren.

That’s awesome, but also has some costs. One of those costs is that gcc gets updated for me way sooner than it does for people releasing Ruby versions and sometimes there are weird things that older releases of the compiler were more forgiving about or interpreted differently or whatever. So in order to get our app at work that we haven’t yet ported to Ruby 1.9.2 to run, I need to have REE installed. This is how I got it done. This is one of those blog posts that I hope gets indexed so that the next time I have to do this and I ask Google about it, it will show me my own blog post.

Ruby-build

I like rbenv. A lot of people prefer rvm. I don’t want to get into pros and cons or whatever now, but because I use rbenv for managing multiple ruby versions, I use ruby-build to install multiple ruby versions. The way ruby-build works is by executing recipes, which are pretty simple. Here is the one I wrote to handle the install. It’s just a variation on the stock REE install recipe from ruby-build.

ree-1.8.7-2011.12-stdout_patch
1
2
3
4
5
6
7
8
build_package_stdout_patch() {
  wget 'http://bugs.ruby-lang.org/attachments/download/1931/stdout-rouge-fix.patch'
  patch -p1 < stdout-rouge-fix.patch
}

require_gcc
install_package "ruby-enterprise-1.8.7-2011.12" "http://rubyenterpriseedition.googlecode.com/files/ruby-enterprise-1.8.7-2011.12.tar.gz" stdout_patch ree_installer
install_package "rubygems-1.6.2" "http://production.cf.rubygems.org/rubygems/rubygems-1.6.2.tgz" ruby

I won’t get deep into the details, but let’s start with the last 3 lines. Ruby-build executes each of these directives in turn. The first of the three sets up the compiler and the next two each take a series of arguments. The first two of those arguments are what it’s installing and where to get it. Any after that (you’ll have to scroll right) are telling it what to do with it, once it’s downloaded it. It will run the last arguments in the order given. So that brings us to the function I added at the top: build_package_stdout_patch.

When you pass those ending arguments into install package, it will look to execute a function by the name you gave it prepended with build_package_. So the function I wrote downloads a patch for a bug having to do with creating rogue references to STDOUT, then issues the patch command to work it into the REE source. I don’t know a lot about the patch command, so there’s a good chance this could be done more nicely (see below). After that, it runs ruby-build’s standard ree_installer task wich builds and installs the REE source.

Running It

When you’re using ruby-build and rbenv together, you get a nice command called rbenv install. You can either pass it the name of a recipe that ruby-build already knows about or the path to a recipe on your hard drive somewhere. So, in the directory where I had saved my recipe, I ran:

1
$ CONFIGURE_OPTS="--no-tcmalloc" rbenv install ./ree-1.8.7-0211.12-stdout_patch

Note: There’s some kind of problem with tcmalloc and the newest gcc. Or something. I don’t really understand, but since this is just for local development, I decided not to worry too much about performance and skip it. If you set the environment variable CONFIGURE_OPTS, ruby-build will pass those options along in it’s build process. So off it goes to the races. Then, I get this output:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Downloading http://rubyenterpriseedition.googlecode.com/files/ruby-enterprise-1.8.7-2011.12.tar.gz...
Installing ruby-enterprise-1.8.7-2011.12...
--2012-02-03 12:07:35--  http://bugs.ruby-lang.org/attachments/download/1931/stdout-rouge-fix.patch
Resolving bugs.ruby-lang.org... 210.251.121.216
Connecting to bugs.ruby-lang.org|210.251.121.216|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 719 [text/x-patch]
Saving to: `stdout-rouge-fix.patch'

100%[======================================================>] 719         --.-K/s   in 0s

2012-02-03 12:07:36 (68.9 MB/s) - `stdout-rouge-fix.patch' saved [719/719]

can't find file to patch at input line 5
Perhaps you used the wrong -p or --strip option?
The text leading up to this was:
--------------------------
|diff --git a/lib/mkmf.rb b/lib/mkmf.rb
|index c9e738a..7a8004d 100644
|--- a/lib/mkmf.rb
|+++ b/lib/mkmf.rb
--------------------------
File to patch: source/lib/mkmf.rb
patching file source/lib/mkmf.rb
Installed ruby-enterprise-1.8.7-2011.12 to /home/ben/.rbenv/versions/ree-1.8.7-0211.12-stdout_patch
Downloading http://production.cf.rubygems.org/rubygems/rubygems-1.6.2.tgz...
Installing rubygems-1.6.2...
Installed rubygems-1.6.2 to /home/ben/.rbenv/versions/ree-1.8.7-0211.12-stdout_patch

Pay particular attention to the last half of this. After the progress bar, patch gets confused. That’s because the patch is really for Ruby 1.8.7 MRI, not REE. So it complains about not being able to find the file it wants since the projects have slightly different directory structures. You can see where I entered the correct path (basically, I just prepended the source directory). With that information, the patch applies cleanly, it builds REE without tcmalloc and now I have a ruby called ree-1.8.7-0211.12-stdout_patch. Hopefully that’s helpful to someone besides me.

Changems

The other day, I was listening to the Ruby Rogues podcast (which I recommend). The episode was number 36, about Ruby Gems and they had Nick Quaranto on as a guest. For those of you who don’t know, Nick is the originator of the whole GemCutter thing which eventually became what is now RubyGems.org. So he knows a thing or two about gems and, in particular, about the servers that host them all. When you type gem install bundler or whatever, RubyGems.org is where it’s (generally) downloading it from.

I digress. At one point, Nick mentioned that he’d like to see more projects using RubygGems.org’s API and specifically one doing something interesting with gems’ change logs. That, I thought, didn’t sound like a terribly complicated app. So I asked him about it on Twitter, and he pointed me to a GitHub Issue on the topic. You can read the discussion for yourself, but the short of it is that no one was working on a site yet (as best I could tell), so I decided to, and over the 3-day weekend, I banged out Changems.

Right now, there’s fake data in the DB just to give an idea of what I’m thinking. The actual task of getting change logs into the app is not even remotely addressed right now. I’m hoping someone else will at least partially solve that problem, since it’s really hairy. How opinionated do you get? How much freedom do you allow an author before you throw out their log? Should you go so far as to parse Markdown and try to retain code samples and such? Should you only accept plain text (like my fake data) and blow off people who want to get fancy? Then there’s the matter of what people want to call the file (or whether they want to put their change log in the README). Anyway, once those questions at least have rudimentary answers and the site has some real data, I’m sure the community will drive whatever change they feel is appropriate.

Right now, the app is based on the idea that each bullet point in a change log for a version stands alone and is an equal peer with the others from the same version. That might be foolhardy. Maybe each version should just have one big block of data for all the changes; if parsing Markdown or allowing a lot of freedom to make subsections or whatever is important to folks, that would probably be the best bet. But I don’t know yet what folks want. So this post is sort of a plea for help, or at least feedback.

Anyway, it’s 3 evenings of work from one rubyist, so I’m hoping to get people’s thoughts on the topic and maybe some pull requests. If you’d like to talk about it, hit me up on Twitter, or open an Issue on the GitHub repo or, you know, leave a comment here. Also, I threw together the current design, but I am not a designer, so I’d love someone with some actual design chops to send me a pull request. So lemme know: Seem useful? Off to the wrong start? Totally boring? Totally awesome?

The Parameter Object Pattern

I have been paying more attention to software design patterns recently. It all started with my noticing the Null Object pattern and the Ruby Rogues talking about Smalltalk Best Practice Patterns. My most recent discovery is of the Parameter Object pattern. Thanks, by the way, to @timtyrrell for telling me the name of it.

As I’ve mentioned before, I’ve been spending some time at work with a search engine. It works sort of like NewEgg’s search in that you might type a string in (“desktop ram”) and then narrow your search by clicking on links in a side bar (DDR3 or Corsair). The search engine in question powers a product called SubjectLin.es (it’s in beta; you can sign up for a free account to try it out, if you like) where you can search for words that appear in an email subject and then further limit by, say, who sent it (“sender”), what kind of email it is (like coupon or receipt, we call it a “tag”) or what business the sender was in (“market”).

To date, I’ve rewritten the search engine a few times and refactored it a few times. It and one other area of the code base are, by far, the most complex bits of the application, so it has gotten it’s fair share of attention. And it’s gotten more recently when an exception brought our attention to something: We don’t have one search engine… we have four. It’s just that they’re all in one class. Finding the email subjects that a user is interested in is not really related to finding the senders who sent them except that the user’s parameters are the same. So I thought what we’d do is factor out our current search object into 4 smaller ones (subject, sender, tag and market) that each centers around the object it’s pulling out of the DB. Besides code clarity, there are some other benefits we get from this modularity, but I don’t want to get into that in this post.

So now we’re faced with the fact that we’ll have 4 objects we want to create that all depend on the same parameters to build themselves. Add to that the fact that we do some fancy Google-style keyword parsing (you can type “some key words sender:Company” and we pull out the company name) and the fact that if the user is interested in limiting by sender, we want to display things differently than if they aren’t. Now, I thought, it looked as if we should have an object just about the user’s search parameters and that each of our search engines should take only that as an argument.

This way, our view (or presenter… whatever) can ask the search parameter object if the user limited based on sender or not. We can build the one object and then pass it to each of the four engines. We can put all the keyword parsing logic into the search parameter object, too. When I had it, it seemed like such a good idea that it had to have been thought of before. And, lo, it is called the Parameter Object pattern. Or, anyway, I think this is a case of that pattern.

What do you think? Is this Parameter Object? Is it something else? Does my example make any sense at all (I honestly have no idea, since I’m so deep in the system; I tried to balance high-level with need-to-know)? Note: as of this writing, none of this is implemented yet. This is all just design work with @marcosacosta, so far. If anything interesting crops up while we’re writing it, I’ll try to remember to update this post.