I checked out the blog (yeah, the one you're reading) today, and what do you know? I was greeted with Passenger's generic "Rails just spewed chunks all over your good tablecloth" message. Nothing works. Awesome.

Why does nothing work? Considering I've been too busy with Real Life for about the past six months to even think about blogging (not exactly true; I manage to at least think about it a couple of times a day), I wanted to know the same thing!

So, straight into an SSH session, which promptly warned me that the host's RSA keys had changed, and I was probably being hacked. It was a false alarm, of course; I'm on a shared host, and that means more likely than not, they must have upgraded something.

Now, something as minor as a shared host installing an upgrade or two shouldn't normally bring down your server in a catastrophic way. Unfortunately, I've been kind of busy lately. The Rails app running this blog isn't the newest. It's running Rails 2.3.8, to be exact.

For the record, checking the production logs indicated the last request before downtime was received around December 18th. At least that's not too ancient, but it's been almost a month so I imagine Google's already scoured me from the face of the Net. Too bad, that.

This was just the beginning of my headache, unfortunately. Passenger was claiming I was missing all kinds of gems, but I wasn't. Something had screwed with the run environment. That was when I got an amazing, groundbreaking idea. Why not take the opportunity to actually update something?

I started with Bundler. Yeah, my app predates Bundler! I did some googling and promptly turned up the "how to use Bundler with Rails 2.3" article. I copied and pasted the source code from there into its relevant destinations, and then the server started!

But now there's something else going on. The app itself is failing -- I'm getting nil errors in weird places, and my RDoc formatter (I like to use RDoc behind the scenes) seems to not be working at all now, so I've dropped down to pure HTML in this post. I guess, most likely, one or more of the freshly-installed gems is too new.

But the blog is online, at least.

Now that my content is again available, I'm going to go back to what I was doing before all this madness started: writing a brand-spanking-new blog engine to replace this one! If I can just keep this one barely running a bit longer, I should be able to push up a its successor, Mist, which takes the form of a Rails engine that can be dropped into any Rails 3 project.

Mist isn't finished yet, but as soon as it's release-worthy I'll be swapping this blog for Mist and migrating the content.

Mist brings some really cool features to the table. First of all, it's powered by git instead of MySQL, so can run with no database at all (if that's your thing). Also, because it runs via git commits, it will be able to clone a git repository from anywhere and immediately start blogging to it, and pushing up to the repository's remote (for instance, sitting on GitHub) will effectively produce instantaneous, ongoing, distributed backups of the entire blog!

As if that wasn't cool enough, Mist also processes each commit using Markdown, and replaces each code snippet with an embedded Gist. Using Gists for code examples is really sweet, because it means that if your actual blog post doesn't come up in Google (or if your blog is down like mine...), then maybe the relevant source code (and a convenient link back to the article!) will instead!

Mist isn't completely dumb about Gists, though. If a Gist can't be loaded (you delete it by mistake, for instance), it'll fall back to the standard Markdown code examples instead. The drawback to this is no syntax highlighting, but the benefit is that your code still looks like code. Fair trade. :)

I haven't even finished brainstorming all of the cool possibilities that Mist is going to offer. Somehow I'm sure the ability to diff, fork and branch the blog itself are going to produce some very awesome features indeed -- but for now, my primary objective is getting the core component online, so I can say goodbye to this obsolete code base!

What gives?

So, have you ever needed to tar something up in one of your Ruby apps? Sure, the following will work if you're on Mac or Linux:

output = `tar -cfz filename.tgz *`
if $?.success?
puts 'all done'
raise 'whoops, bad stuff'

But what if you want to create a tar (and/or gzipped) file in memory, without creating a temporary file? Even more difficult, what if you want to do so in a cross-platform sort of way, so that your code could run reliably, even in Hell?

The Search

If you're like me, the first thing you'll think of is Google. Certainly, someone out there must have done the same thing! And sure enough, someone out there has. The problem is, quite a few people have suggested simply copying the example above. Not what we're looking for.

I also searched for tar implementations on RubyGems. There are a few, and the one I initially settled on was Minitar. It worked all right, and that was that -- until I pushed my source code to Github.

The Dilemma

When I did that, things got hairy. I use Travis:CI to test my sources, and the project I was working on needed to work in a multitude of different Rubies. Try as I might, I couldn't get around a NonReversableStream error being raised by Minitar when run under Rubinius.

So, using RVM, I loaded up my own Rubinius. Sure enough, it failed on my Mac identically to the failure emailed to me by Travis. At first I thought it was because I was passing StringIO to Minitar in my test suite, instead of an actual File. (Hey, I've had problems like that before.) So I did a few bundle exec's to test the code "in the field" under Rubinius. Verily, it crashed. It wasn't a StringIO problem.

Light Bulb!

After some purposefully perplexed pondering, something quite interesting popped into my head. I knew from past experience, RubyGems packages are glorified TGZ files. So it was back to Google, looking for the details. But alas, the RubyGems documentation is sparse in this area, and though I did find a few class names that looked interesting, I couldn't find any easy-to-follow examples or even a high-level paragraph or two. I guess the only people using the RubyGems internals are people who already know how to use it.

Resolution, At Last

Well, after a few hours of this I got disgruntled and said, "To hell with it! Where's the source?" Off to Github I went, and I cloned the RubyGems project into my local machine, where I started grepping away like a madman!

Eventually, after tinkering with RubyGems code for awhile, I hacked out a solution. It worked, so I tested it under Rubinius. Still working! So I hammered out something more robust (and thoroughly tested, of course). Here's my result: a module that can be included into any Ruby project.

Cross Platform

Remember, this snippet uses code directly from RubyGems. That means any Ruby with RubyGems installed (which is the vast majority of Rubies, not to mention RubyGems being integrated into the 1.9 releases to begin with) can run this code out of the box. No dependencies to deal with, and a considerably wider known testbed to boot? Sounds like an Epic Win to me!

We've got some common code that's been duplicated between various Rails apps here at work, and I wanted to see about extracting it into a gem. The gem wouldn't have much pertinence in the Rubygems world, so I didn't really want to publish it there. This meant I needed a gem server, and a means of publishing the gem.

I wanted a modular solution, one that I can plug into other gems as the need arises. I started considering whether Capistrano would be a good match for this, and with some research, I decided it couldn't hurt to give it a shot. As fate would have it, this was a great decision! Once I knew how to make Cap do what I wanted, the whole set-up was up and running in a matter of minutes!

The Gem Server

There are a number of options for setting up a rubygems server. For one, you could just clone the Gemcutter code base. You could also just run

  gem server

on one of your boxes, though that wouldn't lend itself well to publishing and maintaining the gems made available on the machine... (Read More...)

Mon, May 23, 2011

I love Autotest -- or rather, I love the premise behind Autotest. I tried to actually run it today and got slapped in the face with the Control-C bug.

Autotest is kind of advanced in that it will figure out which file you're working on and monitor just that file, testing as you make changes. This is faster than rerunning the entire test suite, but the drawback is that, during this time, if you make changes to a file that Autotest doesn't think you're working on, it won't be detected and the tests won't run... (Read More...)

What, you thought I’d given up on this? Yeah, right!

I’ve just released the first version of Jax, a Rails-like framework for WebGL and JavaScript. It puts a great deal of emphasis on productivity, and makes it possible to code WebGL applications in a fraction of the time it would take using other frameworks or, God forbid, not using a framework at all... (Read More...)

I’m talking to all the Ruby gem publishers out there, myself included. There’s a problem that seems to be present in far more gems than I like to think about. A lot of them – and I’m talking about a lot of my own old code too, as well as some of the more popular gems like rspec – have set up their gem versioning to require dependencies (like, say, Rails) in the wrong way.

Here’s how most gems have historically pulled in dependencies:

s.add_dependency "rails", ">= 2.3.2"

This ensures that the ‘rails’ gem is activated, and that it is at least version 2.3.2. The same holds when using Bundler to manage dependencies:

gem 'rails', '>= 2.3.2'

The problem with this approach is that it will take any version equal to or greater than the specified version 2.3.2... (Read More...)

Sat, Feb 19, 2011

== WTF?
Holy hell, it's February already! Almost March! Well, you most certainly deserve an update concerning what's been keeping me so quiet. So here we are.
This isn't going to be a technical article, though I am cooking up a few of those.
On January 11, 2011, I officially became a father, which is pretty cool. It's also thrown my schedule, or what passed for one, into complete disarray as I've finally started to understand just what parenthood brings with it.
Now, normally it would only take a week or two to at least get some semblance of normalcy back. Unfortunately, the new addition wasn't without a few complications. I won't go into all the technicalities  here, but essentially my new daughter, Lauren, was born with some defects in her heart -- the most important of which is called {Tetrology of Fallot}[http://www.ncbi.nlm.nih.gov/pubmedhealth/PMH0002534]. Without modern medicine, she would likely not have survived more than a few hours after birth. As luck would have it, the drugs they gave her would keep her kicking for as long as a few weeks.
== Complicating Factors
This all came to fruition at the same time as the big (by local standards) ice storm here in Georgia. It probably wasn't a huge deal to the rest of the nation, but we're woefully unprepared for more than half an inch or so of snow in this state, and we had well more than 4 inches. When that was covered over by half an inch of ice, it was good-night for our infrastructure.
So yeah, there wasn't a lot of driving going on. The nurses couldn't get home, and their counterparts couldn't get to work, so they all stayed on the clock for 5 days. They slept in shifts in some of the empty rooms, some on couches, some on examination tables.
As far as food goes... The hospital had a McDonald's in it, an irony I just can't resist pointing out. It also had a cafeteria, which promptly ran out of food. McDonald's is _not_ tasty after about the third breakfast, lunch and dinner, and it didn't take me long to start skipping meals. I have an entirely new respect, now, for {Morgan Spurlock}[http://www.imdb.com/title/tt0390521/].
So it was in the midst of all of this that my newborn daughter was kept in the intensive care unit. She was moved there a few minutes after birth, after my wife had a very brief chance (about a minute and a half, I'd guesstimate) to hold her. To be honest, taking Lauren out of her mother's arms remains one of the most difficult things I've ever had to do.
She was intended to be transferred to {Children's at Egleston}[http://www.choa.org/] within a day or two for heart surgery, but due to the weather it was about 5 days before they could accept her. They just didn't have enough staff.
When the time finally came, I rode in the ambulance while my wife checked out of the first hospital. This was my first time leaving in 5 days. I hadn't showered for most of that time, so I smelled pretty horrible. It was also cold, about 25 degrees (give or take a few; I wasn't really paying attention to the weather reports). I had forgotten my sweatshirt. With the sheer magnitude of what was going on, I didn't miss it until hours later.
== Admittance
After arriving at Egleston, Lauren was taken to their intensive care unit, where she would wait for several days longer.
Now, let me explain something. Each unit in the ICU is just a large, open room with lots of doctors and nurses milling about, and about a dozen patients more or less side-by-side. It's not cramped by any means, but there's no privacy. If a new patient is admitted, or if Something Bad happens to one of the patients and they need to do something fast, they clear the floor of any visitors. So we could only really expect to stay with our daughter for a few hours at a time, and we most certainly couldn't sleep there.
Moreover, it was flu season, so they were limiting the number of visitors. We were allowed to make a list of 4 people, aside of myself and my wife, and those 4 people were the only visitors Lauren was allowed to have for the duration of her stay in the ICU. We also couldn't _hold_ her. The drugs -- as well as her sustenance -- were administered through the umbilical coord, and some of the lines delivering the drugs went straight into (as I understand it) her heart. So they were super-careful about moving her at all, and it was a huge no-no to let anyone other than a nurse do any more than touch her.
It's a pretty helpless feeling, sitting in a chair next to her bed (or whatever that thing was), unable to do any more than hold a hand not much larger than the tip of your thumb.
The cafeteria was a lot better, though. And the parents get discounts!
== The Plan
Before the surgeon could do his thing, he had to discuss with us exactly what it was he intended to do. There were two options open to him.
The first option was to add a shunt, which would divert the bloodflow and keep her alive long enough for her tiny heart to grow larger. This is generally the preferred way to address her condition, because the heart is so tiny that the risk of causing more damage is considerably greater. Unfortunately, because of the way her arteries had grown (non-standard), he couldn't quite tell from the echocardiogram whether a shunt was going to be viable.
The other option was to go for the complete repair. This has the upshot of not needing a follow-up surgery six months down the road. The downside is that the risk of causing more damage is much higher, and there's the real probability of needing a pacemaker for the rest of her life.
The problem is, there's a line in the heart effectively similar to an electrical wire. It keeps the heart in time, so that it doesn't beat erratically. But the heart at this age is so tiny that the wire is literally microscopic. The surgeon can't see it. He knows where it _should_ be, but if anything at all is not laid out as expected, there's a possibility that he could put a stitch in this wire. If that happens, (and remember, he can't see it so there's no way to know until it's too late), then a pacemaker is necessary. Damage done to this line is apparently permanent, and the pacemaker stays in for life.
A further complication, though relatively minor compared to everything else, was that she had some blood vessels wrapped around her esophagus. While this was not an issue yet, as she and her esophagus grows, the vessel would begin to constrict and choke her. So this vessel had to be rerouted.
Going in, because the echocardiogram was basically inconclusive, our surgeon did not know whether he could go for option A, the shunt, or option B, the complete repair. He definitely preferred the former, but he was unsure whether he could add a shunt at all because of the layout of her arteries. So he just had to wait and see.
Even after hearing all of this, I was happy. An operation at birth and potentially another at six months -- either way, she won't remember it. That's what I cared about.
Then he said something that let _all_ the air out of my bubble. You see, part of her condition includes her pulmonary artery -- one of the two the major vessels leading out of the heart -- being too narrow. It needs to be widened. In Lauren's case, it was so thin that it was nonexistent. To fix this, he would have to use a pig vein. The problem with this is that, since it's not her own tissue, the pig vein would not grow in proportion to the rest of her body. The best he expected, then, would be to use a slightly too-large vein that she could "grow into" over time. That would buy years. In the end, though, she'd need many follow-up surgeries to replace this vein as her body outgrows it. This would go on until her body stopped growing -- that is, she'd be in and out of heart surgeries until she became an adult.
That was pretty much the worst of it, in my mind, because it took away the one advantage I thought we would have. I didn't know how to respond to this, or what to think. I was left speechless, in a very bad way.
== Surgery
On January 18th, one week after she was born, Lauren had heart surgery. We were allowed to go as far as the operating room doors, but no further. After they took her in, I grabbed one last picture before they showed us where the waiting room was.
It was a long wait. At all times, one parent had to be present in the waiting room. Periodically, one of the nurses in the operating room would call a phone in the waiting room with an update. So someone had to be there to answer the phone.
Roughly an hour or two into the procedure, we got a call. He had decided to go for the complete repair. Riskier, but the shunt was, indeed, not viable due to the placement of her arteries.
We killed time. Our families came, and that made it easier. Actually, we crowded the waiting room because there were so many of us. Their presence made the wait far less painful.
Finally, we saw the doctor coming. Months of tension, weeks of stress and sleep depravation all came to this moment.
== The Verdict
He said that he had unwound the vessel that was wrapped around her esophagus, so that was no longer an issue. The rest of the surgery had gone well, too. He had, indeed, opted for the complete repair, which at least meant she wouldn't need another surgery six months later.
"Does she need a pacemaker?" my wife asked almost immediately. He said that it was too soon to tell; they would keep Lauren in the ICU for a few days, with a pacemaker hooked up, just-in-case. If the heart started beating off-time, they'd switch it on -- and it would stay on.
Then he said something really unexpected. He told us that he'd repaired her pulmonary artery using Lauren's own tissue, rather than using a vein from a cadaver or a pig. The reason this matters is because Lauren's tissue is still alive. The cells are still reproducing. The tissue will grow as she does.
I was walking on air after hearing this news. To be honest, I really can't remember what all he said after that. It was important, but my wife will have to remember it. She won't need a surgery every few years throughout her life. The doctor warned us that she may need one as she reaches adulthood, because she is now missing a valve that she will need in her later years. But that's just one surgery, and not five. Given the circumstances, this was the best news we could have possibly hoped for.
A few days later, I was driving home from a quick run into work (I was still trying to make the occasional guest appearance), and I heard an ad on the radio for Children's Healthcare. They're saying that they can now replace heart valves without surgery. After that, I talked to one of the nurses while we were at a post-op checkup. She said, "Yeah. We've done 5 or 6 so far, and all of them are doing great."
Fast forward technological development another few decades, and it's quite likely that Lauren will be able to get her valve replaced without any surgery. Too good to be true.
== After
The first few days after the surgery were the worst. We could barely even touch her, and holding her was still out of the question. I've lost track of all the tubes and wires going into and out of her. A chest tube, for drainage. Umbilical lines, for the pacemaker and blood pressure sensors. IVs for painkillers (morphine, mostly). About a dozen others that I can't remember the uses for. It was hard to look at, and sometimes it was difficult to remember that this was actually _better_ than before.
Every day brought another improvement, though, and on day 3 (I think) they moved her to a recovery ward. We were allowed to have all the visitors we wanted, there, and we had quite a few. We could come and go as we pleased, and we could hold her whenever we wanted. (My wife still hasn't put her down.) Another 2 days after that, we were being sent home with a plethora of instructions.
While she was recovering, the doctors noticed that she has a cleft palate. She loves her pacifier, but because of the cleft, she can't get enough suction on the thing to hold on. So we prop it up for her a lot, and she learned amazingly fast how to hold her hand against her mouth to keep the pacifier in (though she's not really all that good at it, yet).
Since she was fed directly (without using her mouth) since the day she was born, she apparently doesn't know how to swallow. The specialist we saw a few weeks ago said that this is a use-it-or-lose-it thing: it's initially instinctive to swallow, but if you don't do so, then you forget how. This is where Lauren is at, and we're working on teaching her how to do that all over again. Apparently, this is compounded by the cleft palate, since that prevents her from getting the suction she needs on, say, a bottle.
So we're still feeding her by NG tube, which is a line that goes into her nose and directly down to her stomach. That's a small price to pay, however, and all the other tubes and wires have been removed. Her scar is already healing up nicely. In fact, it's a bona-fide scar, now -- not a scab and certainly not an incision.
She's going to need another surgery at about 9 months to address the cleft. They don't want to do it too soon after a heart surgery, so it's likely going to be a while. It's possible that we can use specialized bottles to feed her with, though, and once she's doing well with those we might just be able to ditch the NG tube. After that, she'd be just like any other kid. Just, with a lot of history.
== To Be Continued
This isn't a conclusion, because Lauren's story isn't over. It's only just begun.
In any case, there you have it. There have been other things demanding my time, but this is the heart of what's kept me busy. I've got a lot of projects that I want to jump into, and I've had a lot of articles I wanted to write and never had the chance. It's a fair trade, to be sure, but just the same...
I'm back.


Holy hell, it's February already! Almost March! Well, you most certainly deserve an update concerning what's been keeping me so quiet. So here we are... (Read More...)

Thu, Jan 06, 2011

I’m mostly putting this here for my own reference. Now that I’ve just had to hunt the information down a second time, I’d rather not condemn myself to a third.

The Ruby gem I like to use for generating UML-style diagrams and flowcharts is called ruby-graphviz, and here’s a code sample. It relies on dot... (Read More...)

The easiest and probably safest extconf.rb file supporting SDL looks like this:

require 'mkmf'
$CFLAGS << " " << `sdl-config --cflags`.chomp
$LIBS   << " " << `sdl-config --libs`.chomp
create_makefile 'extension-name'

Note that calling sdl-config returns a new line as a part of the result, which causes mkmf to be unable to generate the Makefile. You can verify as much by checking ‘mkmf.log’ in the extension directory. To get around this, we remove the newline by calling chomp on its output. Job done. Of course, this assumes the user has sdl-config installed. If not, Bad Stuff will follow.

As for why I’m doing this… Well, that’s another article for another time – to come when I have said time.

I’ll preface this article with a note about Rails 3 and UJS (Unobtrusive JavaScript). I was skeptical at first, but I have to say I’m really impressed. It turns out that UJS is nothing new, (it’s simply the idea of registering event handlers programmatically, via window.onload and friends, rather than placing your event handlers directly into the HTML code), but Rails does some nice abstraction that lets you get right down to the important stuff.

The code structure is a bit of a change from Rails 2; suddenly the application.js file is way more important, so there’s some getting used-to ahead of you if you’re firmly planted in the Rails 2 way of doing things, but if you approach it with an open mind you’ll probably end up liking the Rails 3 style a lot better.

So, what’s up?

I’ve spent the last few days working on the next version of my WebGL space-based game. Things have gone well overall; Rails’ productivity lends itself well to mission editors and the like, especially when JavaScript and AJAX are heavily employed... (Read More...)

WebGL is just about all I’ve been able to talk about lately, and I don’t think I have to say again why that is. My opinions of it are already scattered about, so suffice to say that I think it’s going to be a Big Deal.

I’ve been working on my WebGL libraries (nearly all JavaScript at this time, but with a growing Ruby-based counterpart) for a few months now, and so it should come as no surprise that I’d begun to wonder just how far I was from a Real Game... (Read More...)

Sat, Nov 06, 2010

I’ve been spending virtually all of my spare time on this project, and I decided it’s probably about time to update you on the goings on.

I still don’t have a name for this project, so I’m still going around calling it “My WebGL Tests.” However, don’t be fooled – this project has now evolved into much more than a collection of tests. It’s still not the Rails-based framework I want to turn it into, but it is quickly growing a number of Ruby libraries to help get it there. (For the record, I’m still accepting suggestions regarding how to name this project. Right now I’m thinking of either Rails3D or RailsGL – but both of them sound kind of “weak” to me.).. (Read More...)

A few days ago, I was idly picking through my site statistics (being the numbers junky that I am). I tend to do this pretty frequently – sometimes several times in a day – but it had been some time because I’ve been so distracted with my WebGL tests lately.

So there I was, skimming through the list of HTTP referrers. I do that periodically, and it shows me where traffic is coming from. If there’s a blog post, for instance, and I don’t get a pingback from it, then this is another way for me to pick up on those posts, head over to the other site and see what I said that someone actually found interesting... (Read More...)

Mon, Oct 25, 2010

Most languages support ternary operations, and Ruby is no exception. If you don’t know what the term means, you’ll almost certainly recognize the syntax (even if you don’t understand it):

a ? b : c

Ternary operations are a more concise form of conditional statement. They essentially roll the following into one line:

if (condition a)
  (result b)
  (result c)

In Ruby, I commonly find myself using ternary operations to return one value if something is nil, and another value if it isn’t:

x = nil
x ? 1 : 2
#=> 2, because x is nil!

This is quite useful when you need to perform an operation on a value that is non-nil and raise an error if it is nil, because it allows you to do both of these things at once:

instance_variable_name = x ? "@#{x}" : raise(ArgumentError, "Expected x to be non-nil")

But what if you only want half of the condition? It’s still kind of wordy to write:

if x.nil?
  raise ArgumentError, "Expected x to be non-nil"

and this is only somewhat alleviated by its briefer-but-still-wordy cousin:

raise ArgumentError, "Expected x to be non-nil" unless !x.nil?

At first I found myself throwing a superfluous known value into a ternary operation, but this approach bothered me because it makes the code both less legible and more bug-prone:

x ? x : raise ArgumentError, "Expected x to be non-nil"

I was about to type something like “My solution is…” – but I stopped myself, because I wouldn’t really consider this a problem, and therefore what I’m about to say isn’t exactly a solution. This is all just semantics; as I’ve maintained in the past, you use what works for you. So with that said, here is the technique that has evolved for me over time:

x || raise ArgumentError, "Expected x to be non-nil"

The opposite also holds true:

x.nil? && raise ArgumentError "Expected x to be non-nil"

Because and operators bind more tightly than or operators, we can also write the whole ternary operation this way, if we so please:

instance_variable_name = x && "@#{x}" || raise(ArgumentError, "Expected x to be non-nil")

Of course, that last example may be going a little overboard, but it serves its purpose as a demonstration well enough.

There’s one more example I’d like to show you. This is for setting a value depending on its current value:

x ||= 5

In the above example, if x evaluates to false then it will be assigned the value of 5; otherwise, the current value of x will be returned. The opposite holds true:

x &&= 5

Here, if the value of x evaluates to true, then it will be assigned the new value; otherwise, its current value of false or nil will be returned.

A Caveat

Bear in mind that the word and binds more loosely than the && syntax, just as or binds more loosely than the || syntax. Consider:

instance_variable_name = x and "@#{x}" or raise(ArgumentError, "Expected x to be non-nil")

The right-hand side of this assignment will at first appear to do exactly the same thing as the other variants; that is, the return value of the statement will be either “@#{x}” or an error. However, upon closer examination, you’ll see that the instance_variable_name is not equal to that return value. Instead, it was set to the value of x itself... (Read More...)

Fri, Oct 15, 2010

I’ve lost a lot of code over the years. Some of my losses were due to stupidity or blatant oversight, while others came down to a simple flip of the coin. Between Github and the advent of Really Cheap Servers, I don’t lose all that much of my productivity any more, but there are some things that are gone forever.

If there were any aspect of my hobby-code that I could have back, it would without a doubt be my experiments into the world of accelerated graphics. The source code itself may be gone, but it isn’t a secret that this is where I want to be. Of course, there’s a catch. My early work was done in C and C++, and I did some experimentation with OpenGL in Java. These weren’t my cup of tea. I like concise, high-level languages – and that’s why I want to code my games in Ruby... (Read More...)

Fri, Sep 24, 2010

Credit Where Credit is Due

One of the many awesome things in Rails 3 is the new routing DSL. I was pretty attached to the Rails 2.3 style of doing things, and so I was a bit skeptical, but I have to say: the Rails team has outdone themselves.

I’ve been knee-deep in routes for the past few days, picking through the Rails guides as well as the very source code which makes up the routing... (Read More...)

The Reason

I’m going to dedicate this article to getting a Rails 3 project off the ground using RSpec, Cucumber and Webrat. That’s because when I start a new Rails project, that’s generally the sequence I follow. It’s pretty easy if you know what to copy-and-paste, and it’s exactly that information that I’d like to make a note of. You can probably garner most of this right from the cucumber-rails documentation.

The Real Reason (Upgrading an Existing Rails 3 App)

(Scroll down for the meat of the article – this part is only interesting if you’re upgrading, not starting fresh.)

On the other hand, the thing that actually prompted me to write this article is not the fore-mentioned setup process. Actually, it was an upgrade process – a few things that have changed from the Rails 3 Beta now that we’re in Rails 3 official. See, I wanted to make a teensy refactor in Sparkly Auth, so that I could load the routes more than once in a few of my projects under development. (It’s complicated and I won’t bore you with the details – but trust me, my reasoning is sound.) Basically, I just wanted to add an Auth#routes_proc method that would return a proc, so that I could instance_eval that proc at will... (Read More...)

The what’s and why’s of it all

I’m working on a new project. To be more precise, I’m working on deploying a new project. Now, normally I’d just copy and paste my old Capistrano deploy script and change a few options, but I figured, what the heck? I may as well start fresh. Maybe I’ll learn something in the process. Besides, that script has gotten so large and convoluted that there must be a better way.

The Environment


This new project uses Rails 3, and so I wanted to take advantage of the power inherent in managing dependencies with Bundler. One feature that shows a lot of promise is being able to bundle install after a deployment to automatically grab any dependencies that might have changed since the last deploy.


I’ve also decided to use RVM in production. I’m not entirely sure why I’m doing this, to be honest, but it seems to be the new “in” thing, so I figured I’d give it a shot and see if it helps me in the long run. So far, if nothing else, it’s really nice not to have to worry about sudoing everything. Really, it’s like switching from Ruby’s double-quoted strings to single-quoted strings. That extra keypress really makes a difference over the long haul!

I followed the steps outlined on my previous post, Using Phusion Passenger and Apache2 on Ubuntu with RVM and Gemsets, which worked fine, but there was an extra step. The server I’m working on uses cPanel, so I had to make sure Passenger played nicely with it. Luckily, that was pretty easy:

/usr/local/cpanel/bin/apache_conf_distiller --update
  [verify the changes in httpd.conf]
service httpd restart


Finally, I’m also using Git to manage the source code for this project. I’ve used Git for my other projects, too, but I’ve always gone the checkout-and-upload route rather than just updating the version on the server. It’s a slower option, but it was the only way to make it work on one particular server and, because it works, I tend to copy it from project to project. Well, no more! Time to start fresh.

The Code

Time to be honest. What you’re about to read is not the order I tackled this in. I did what anyone would do: started with a clean slate and hacked and Googled my way to a working solution, and then refactored it to make it pretty. I’m going to assume, however, that you’re more interested in Getting Stuff Done and that you couldn’t care less about the play-by-play. So on that note, I’ll talk about the deploy file in what I consider the most logical way to present it: top-to-bottom. (That means you can safely copy-and-paste this in the order it appears, or just skip to the bottom and grab the whole thing.).. (Read More...)

Sun, Sep 19, 2010

If you suddenly start seeing the following error when trying to open an SSH connection:

colin in ~$ ssh user@xxxxxx.com
PTY allocation request failed on channel 0
stdin: is not a tty

Then you may need to run:

root@xxxxxx [~]# mkdir /dev/pts
root@xxxxxx [~]# mount /dev/pts
root@xxxxxx [~]# service sshd restart
Stopping sshd:                                             [  OK  ]
Starting sshd:                                             [  OK  ]

No idea why it happened in the first place, but that’s all it took to make things start working again for me.

Reference (in the comments):

Today, I needed to search for some documentation for Rails routing. I couldn’t quite remember how to do something, so of course I went straight to Google. The Rails Guides were the first match, but it didn’t take me long to figure out that what I was reading from the guides was not remotely applicable to my own project. Turns out, Rails 3.0 has been officially released! And there was much rejoicing!

But that left me with a conundrum. Do I upgrade my app to the latest Rails version, or go with what I already know? The app isn’t finished, but it is becoming a sizeable chunk of code, and I didn’t relish the thought of plunking my way through a bunch of new changes. So I did what anyone with a deadline would do: I kept googling... (Read More...)

I’m not an Apache expert, but tonight I found myself setting up my development box with a pseudo-production environment. Why would I do this, you ask? Well, as overkill as it may seem, there’s just no better way to test AJAX calls, which have a nasty tendency to block in development and hang the server. Besides, it’s nice to have a development environment that closely mirrors production, no? This way, the only difference between my development world and the production one is the Rails environment itself. Not quite sure that’s totally necessary, but it makes me feel better about all of this.

As a side note, if I ever find more spare time, I want to address how we go about testing AJAX in our Rails apps. The process outlined below still feels like way overkill just for setting up a Rails-based JavaScript development world. Seems like there’s a gem waiting to be written, there... (Read More...)

Tue, Aug 17, 2010

As programmers, it's our job to tell computers what to do and how to do it. As it turns out, that's not always easy -- which, of course, is the reason we can turn it into a successful career.

Back in the old days, it was all math. Binary math, no less. I won't argue that it was any easier back then, but it was certainly different. Programmers called themselves 'programmers,' instead of 'software developers.' And, indeed, the job title itself described them perfectly. They moved data from one memory location to another, transformed it mathematically, and then moved it someplace else until it was needed... (Read More...)

Fri, Aug 13, 2010

Whenever I start a new project, there's a sort of thrill that surrounds it. The very thought of coding something new and interesting veritably hums with excitement. If you've ever had this feeling before -- about anything -- then you know that the very best time to get started on that project is immediately.

But what if it's a big project? The longer it takes, the less exciting it becomes. Eventually, if I'm still working on it at all, it's taking a real effort to stay with it. That's because, usually, when the next week or month rolls around, I've already discovered -- and likely started on -- something brand new. Something exciting... (Read More...)

Fri, Aug 06, 2010

I have a lot of groundwork to lay. A lot of coding to do. One thing that I've gotten much better at over the past few years is decoupling that code, and componentizing it. I've come to the point where whenever I start to write a new set of functionality, I ask myself if there's any convincing reason that code just has to be part of the project I'm about to chuck it into.

You know what I've discovered? The answer is usually, "No." Most code, if the author plans ahead, can be reused in other avenues. In fact, taking this approach (with a bit of practice) tends to yield much smaller programs, with much less proprietary code... (Read More...)

I had another article about half-finished, but I got distracted and haven't had time to finish it. In the course of this distraction, I discovered something that I really need to dump somewhere as soon as I can, because otherwise I'll forget about it -- and apparently it's stupidly difficult to find online.

It should be no secret at this point that amongst the myriad of gems that I'm writing is an interactive command line which I'm calling Rink. It's virtually done in that it works, but I want it to do so much more than merely work. I've written a supporting library, sc-ansi, which I'll use to control and interpret ANSI escape sequences for controlling color (for example), among other things... (Read More...)

Mon, Jul 26, 2010

Ruby never ceases to amaze me. Seriously, how many times can I say that? It's just phenomenal in so many ways.

So, I've been laying the groundwork for my game engine, trying to figure out what needs implemented at the most fundamental levels. That process has spawned several new gems and a good bit of brainstorming... (Read More...)

It's good to componentize source code, because you never know when you'll need to reuse the code base. Sometimes, though, doing just that is downright dangerous. Take the case of this blog. The source code is freely available on Github, but when I first started pushing to the public domain it was really nerve-wracking because I grew paranoid that I might push a password file or some such.

The solution that I settled on has served me well, and since I found myself reusing it today for a different site, I decided to publish the technique here. It involves multiple remotes, and it's incredibly easy to set up... (Read More...)

Behavior Driven Development, or BDD, is the concept of driving your application development (coding) with behavior. You should never type a line of code until you've determined the behavior you expect that line (or those lines) to produce. This ties hand-in-hand with Test Driven Development, or TDD, in which you write the tests for your code long before you write the actual code.

This approach sounds great at first glance, but it can be tricky wrapping your head around the actual coding (or should I say, testing?) if you're new to it. To that I can only say, practice. It'll start to click over time... (Read More...)

Sat, Jul 17, 2010

I love to stretch the limits of what's possible. I've never made any attempt to hide my ultimate goal from those who've asked: I want to write a game (or at least, a game engine) in Ruby. I'm not talking about some clunky 2D thing. I'm talking about a mainstream 3D graphics engine with pixel and vertex shaders, complex lighting and shadowing, the works.

Slowly but surely, the pieces to that puzzle are beginning to fall into place -- but they're not all there, yet. There are a lot of things I haven't quite figured out. That doesn't matter, though, because I have my goal. Even if it's only a pipe dream, it's my pipe dream... (Read More...)

Tue, Jul 13, 2010

Yesterday @fabienpenso tweeted me in reference to one of my previous blog posts, Profiling with RSpec and ruby-prof, asking how I ended up running the specs. I said that in the end, I decided to go with the final option in that article, writing a small bootstrap script which then kicked off the spec process.

But it got me thinking. I was never really satisfied with that answer, and I've learned a bit about how RSpec and Ruby-prof work internally since then. So I figured, what the hey... I'll revisit the idea. This resulted in a new gem, rspec-prof. It should be pretty straightforward: install the gem, require it in your spec_helper, and wrap your specs-to-be-profiled in a "profile do ... end" block. The documentation, here, has much more information, but that's basically all you need... (Read More...)

Mon, Jul 12, 2010

There are a number of concepts in Ruby that were new to me when I was learning the language, but perhaps the most foreign in my mind was that of a Symbol. They look like Strings and smell like Strings, but they sure don't feel like them. That's because, obviously, they're not Strings: they're Symbols.

Symbols in Ruby Code

For some reason, a few years ago when I started picking up the Ruby language, the above paragraph just didn't take. It can be difficult to grasp that you can have something like


or even

:"whatever I want!"

and yet it still has absolutely nothing to do with a String. It can be even more difficult to narrow down exactly when a Symbol is useful. Often, Symbols seem to simply be an "extra thing" that serve only to make code more confusing.

Then Again...

There are a few features of the Symbol class, however, that make it really helpful. First of all, a Symbol is only ever instantiated once. Do this experiment in an IRB console:

"hello".object_id  #=> -608697638
"hello".object_id  #=> -608711648
:hello.object_id   #=> 169138
:hello.object_id   #=> 169138

Note that the String version of "hello" is instantiated every time you wrap it in quotes, demonstrated by the different object_id assigned to it. This means Ruby has created two objects, both of which must now be maintained and garbage collected. On the other hand, the Symbol version was only created once, meaning that only one instance of Symbol has to be maintained. This can yield drastic performance boosts in certain applications.

Another thing to take note of is that Symbols are never garbage collected. Once they're created, they stay in memory until Ruby itself unloads. While this is what allows the forementioned performance gains, it is also what makes it extremely dangerous to convert user-supplied Strings into Symbols. Hello, memory leak! This can be a particular source of frustration in a poorly-designed Rails application if it converts some user-supplied data into a Symbol.

A Closer Look

In order to really understand what the deal is with Ruby Symbols, we need to delve deeper into the underlying C code. I'll try my best not to bore you with C excerpts (I'm adding a C Extensions section, soon, for just that; you can find example code there) and instead put this into general terms... (Read More...)

Thu, Jul 08, 2010

This article is not about RubyTML -- nor is it, really, about Ruby. But my path to true enlightenment starts in Ruby, and the vessel that brought me to this revelation was RTML. That means, in order to understand how I underwent this great transformation, this story must begin with RubyTML.

The Background: A Lost Soul

RubyTML is a big framework. I mean, it’s not as huge as Rails or anything, (though that’s largely because Rails is a dependency: standing on the shoulders of giants and all that), but it’s handling a lot of substantial tasks, and it’s making every attempt to bring Rails-style productivity into the TML world. If you don’t know what any of that means, then don’t worry. This paragraph is literally all you need to know in order to understand the rest of my message.

Going back to my starting point, RTML is a big framework, and the first version of this framework was quite successful. We wrote two major payment applications and a number of demonstrations on its back, some of which are now in pilot and seem to be running just fine. This first version was written with absolutely no supporting tests, having been the culmination of my utter disdain for repeatedly writing code that wasn’t even interesting the first time around... (Read More...)

Coding Gems for Rails 3

This article is part of a series. The previous article is Part 2 - Generating the Bare Bones. Source code snapshot: p3-adding-a-generator

Welcome to Coding Gems for Rails 3, Part 3: Adding a Generator! In the last article we got our Rails test environment up and running and built the basic skeleton of our Pingback gem. Today, we'll actually get to see some code, so let's get started!

Let's try to break our application down into its basic components. This will help us decide in which order to tackle them. Rails gives us a good starting point because it recommends three core sections by convention: Models, Controllers and Views. Controllers and views will be easier to design once we have a model to work with, and it's a pretty reliable guess that we'll need a Pingback model to represent, well, Pingbacks!.. (Read More...)

IMPORTANT: This article has been modified heavily since its first incarnation. A lot of things have been made easier and more intuitive, but they also require at least the Rails 3 Release Candidate (rails-3.0.0.rc). So if you're still on a beta version, you'll need to upgrade or else following these directions will not succeed.

CGfR3: Coding Gems for Rails 3! I decided to use the acronym in the title because I wanted to leave room for exactly what it is this part covers: Generating the Bare Bones!.. (Read More...)

Learning To Fly

I essentially had to teach myself how to code plugins and make them work with Rails 2. The information was out there, sure, but most of what I found at the time (in the 2.1 era) was left over from late 1.x or early 2.0, and was largely impertinent. It provided some helpful clues, but little else. In the end, it wasn't all that difficult, but there were some large gaps that could only be filled by literally reading the Rails source code. There were a lot of undocumented methods in there at the time, believe you me, and it took a while to figure out what some of them did.

This process began again when I went to write my first Ruby gem -- and again when I wanted to use the gem within Rails. These days, I consider myself to be an advanced Ruby developer. "Expert" is a word that carries a lot of weight and means a lot of things to a lot of people, so I won't use that word to describe myself -- but suffice to say that I have a firm understanding of the concepts behind Ruby, Rails, Gems and Plugins -- and I'm even beginning to (finally) understand significant portions of the C code that makes up the Ruby virtual machine and garbage collector... (Read More...)

My C is rusty, and my C++ is laughable. (Or is it the other way 'round?) And now, with that minor disclaimer out of the way, I'll tell you about my most recent adventure in Rubyland.

I'm developing a gem which I'm tentatively dubbing "Tomato". This gem has an unfortunate dependency on some C++ code, meaning I have to interface with that C++. Now, I've done a fair amount of coding (most of it experimental) in the world of C extensions for Ruby, and I was hoping to fall back on what I remember of that. It was actually pretty easy, so long as all of your code was in C. C++ has made things a bit more complicated, I'm afraid... (Read More...)

This one threw me for a loop.

I've just installed RVM, which I'd never heard of until yesterday, and I'm absolutely loving it. I'm coding a new gem called Tomato, and this one (unlike most of my others) involves some C extensions that have to be compiled. After getting the bare bones of the thing up and running (yeah, I broke the rules a bit in this instance), I was able to run it from the command line and verify that the Tomato class was loading and doing its thing... (Read More...)

One major aspect of Sparkly Authentication is its generators. There aren't a lot of files, per se, but there are a lot of optional files, and some of those files change depending on how Sparkly Auth is configured. All of this culminates with some fairly complicated generators, and it started to become apparent early on that I was going to need a way to test them.

Enter Genspec. Genspec adds several matchers to RSpec which verify that a Rails generator is, in fact, producing the expected files. You can test different scenarios based on arguments and options; you can also test whether a generator produces a particular set of output (regardless of what files were or weren't actually created); can even check a file's contents by simply passing a block argument to the matcher... (Read More...)

Mon, Jun 21, 2010

Authlogic is cool. Really, it's a nifty piece of work. Unfortunately, it's started to bother me a bit lately. Actually, more than a bit. I've decided to discontinue using it altogether.

Want to know why? Read on.

A few definitions, first

The problem comes down to testing. Thus far, I was able to make myself agree with the crowd that says, "It's a third party component -- it's already been tested, so you shouldn't have to." The falacy in this is assuming that unit tests are the only tests you'll need. A unit test is designed to test one component of an application -- a class is the norm, but it could really be any encapsulation of functionality. The common link is that a unit test will run independent of the rest of the application... (Read More...)

Mon, Jun 21, 2010

Over the weekend, I was finally able to wrap up some improvements I've been working on. For those that don't know, the code base for this blog is an ongoing work in progress, and up until this weekend it lacked some things that most some others might take for granted. Now, it's starting to look a lot more like a blog and less like a collection of form data. (Whether that's a good or a bad thing remains to be seen...)

It's worth reiterating that the code base itself is available at github.com/sinisterchipmunk/blog and you can check that out any time you want. As for what's new, the biggest and most obvious addition is Comments! That's right, now you can finally leave comments on any given article. You'll need to create an account first, which is simple, free (naturally), and only takes a few seconds -- which brings me to New Feature Number Two..... (Read More...)

OK, I admit the name is a little misleading. This isn't really a follow-up to Making Gravatar Work. Instead, it's more of a new post in the same genre. I'm really writing this as an announcement, so to speak, because I've finished another gem. See, I was hard at work on this blog engine (it needed a lot of tweaks), and I thought, "How cool would it be to hook this thing up to my Gravatar account?"

So I was off to rubygems.org to look for Gravatar gems. Unfortunately, the only thing I found (and to be fair, I didn't download them all) were gems that generate URLs for the Gravatar images people use. "Heck," I thought. "That's not even worth the time." No offense to you guys who wrote those gems (anyone who writes free content for ingrates like me is awesome!), but there really isn't that much to sticking an MD5 hash on the end of a URL... (Read More...)

Tue, Jun 15, 2010

This should have been a lot easier than it was. I'm writing a Ruby gem to interface with Gravatar, and while the image generation part is easy, I really wanted to it work with the Gravatar XML-RPC API, since that's something that other Gravatar gems don't seem to be doing.

Unfortunately for me, I'm a newcomer to XML-RPC. I never much cared for the specification, and Web Services didn't enter my world until REST was establishing its foothold. So I haven't had a whole lot of reason to work with it... (Read More...)

I just spent the past hour WTF-ing my way through a major issue that my Cucumber and RSpec tests never caught: in development mode, when my Rails application made use of my not-yet-released Sparkly Auth gem, it'd work exactly once and then croak. The nature of the error?

NoMethodError: undefined method `current_user' for StakeholdersController

Like I said, this worked exactly once, and then blew up. So how does a method go about getting un-defined? My first thought was the second-level modules issue I wrote about in Fun With Metamodules, but my code didn't include second-level modules like that post discusses. After a bit of verification, that was ruled out.

Then I thought, OK, what about second-level classes? The idea being that if a parent class dynamically has a module added to it, perhaps for some oddball reason its children were not getting those methods. So I wrote an inherited_include method to test the idea, which basically worked the same way as reverse_include but worked on child classes instead of included modules... (Read More...)

Are you getting this error? Turns out to be a no-brainer. Seriously, you're going to kick yourself SO hard. I know I did...

Just so we're on the same page here, my Cucumber steps look something like this...

[cucumber]Feature: Go back to homepage
Scenario: Not logged in
Given I am not logged in
When I follow "Go Home"
Then I should be on the homepage[/cucumber]

The "I am not logged in" step does nothing because, well, the user's not logged in. It's just there for clarity... (Read More...)

Real brief. Maybe I'll clean this up and make it into an interesting article, or maybe I'll just forget about it and move on. Either way, if you're having trouble setting up:

sudo gem 

...because it yields...

sudo: gem: command not found

...then the quickest, easiest (and probably least secure but whatever) solution is to add this to your ".bashrc" file:

alias sudo='sudo env PATH=$PATH'

There are better ways to do it, but it appears to be a bug in sudo on SOME versions of Linux. For a more detailed conversation (maybe one of the other options will work for you, but they didn't for me), check out this thread.

This one's pretty weird. If you're using Cucumber to test your Rails applications, you may or may not end up with an odd bug causing all of your step definitions to be undefined. If this does happen to you, it can be quite troublesome to find out what is going on.

I've had this issue twice, now. The first time, I found that I could manually delete the "rerun.txt" file that Cucumber generates, and it'd run all my features properly. The plus side is that it works. The drawback is that this forces all of your features to run every time. That was a minor deal in my previous project, which was relatively small... (Read More...)

Update: If you're interested in profiling RSpec, you should take a look at this follow-up.

 .. (Read More...)

This is a quickie, mostly because I want to get some other stuff done and at least partially because there isn't much to say.

I installed Ruby 1.9.1 from source on Ubuntu 9.10 tonight, because I don't really trust the apt-get repositories where Ruby is involved (it's got a bad track record). When running the "gem" command, I got this:

/usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require':
no such file to load -- zlib (LoadError)
from /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `
from /usr/local/lib/ruby/site_ruby/1.8/rubygems/spec_fetcher.rb:1
from /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require'

from /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
from /usr/local/lib/ruby/site_ruby/1.8/rubygems/commands/update_command.rb:5
from /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `
from /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'

from /usr/local/lib/ruby/site_ruby/1.8/rubygems/command_manager.rb:167:in `load_and_instantiate'
from /usr/local/lib/ruby/site_ruby/1.8/rubygems/command_manager.rb:88:in `
from /usr/local/lib/ruby/site_ruby/1.8/rubygems/command_manager.rb:144:in `find_command'

from /usr/local/lib/ruby/site_ruby/1.8/rubygems/command_manager.rb:131:in `process_args'
from /usr/local/lib/ruby/site_ruby/1.8/rubygems/command_manager.rb:102:in `
from /usr/local/lib/ruby/site_ruby/1.8/rubygems/gem_runner.rb:58:in `run'

from /usr/local/bin/gem:21

Obviously, the issue stems from missing "zlib" files. Not-so-obviously, the name of the "zlib" package on Ubuntu is actually called "zlib1g". So, before compiling Ruby, you need to do this from a command line:

sudo apt-get install zlib1g-dev

Then do a configure, make, make install from the Ruby source directory and you're good to go. At least, I was.

Tue, Apr 06, 2010

So I was idly pecking through the awstats statistics for this site, and I saw that someone found the documentation for my Eve gem by searching for more information about the error this post was named for (KillsPreviouslyLoaded).

Out of curiosity, I googled the same search phrase, and found very few results. Those few results did a really pitiful job of explaining exactly what the error means, so I'm leaving this here for whoever did that search as well as anyone doing a similar search in the future... (Read More...)

Thu, Apr 01, 2010

Yeah, another gem! I'm just knocking these things out left and right! This one was prompted by the very blog you're reading. The next iteration is supposed to bring comments to these posts, so that you can leave feedback (yeah, like you'd be interested in that!). The first thing that came to mind, though, is the threat posed by Evil Spammers of Doom. So before writing even a line of code, I found myself googling, and realized that this is quite the can of worms.

If you don't care about the specifics and just want to make use of the end result, here you go:


sudo gem install bot-away


config.gem 'bot-away'    # in your config/environment.rb file

All done. Easy, huh? Now that that's out of the way, I'm going to ramble for awhile:.. (Read More...)

Mon, Mar 22, 2010

I've released a new Ruby Gem which is designed to assist Ruby developers wishing to interface with EVE Online's In-Game Browser (IGB), the EVE API, or both. It was designed with Ruby on Rails in mind, but works just fine from any other Ruby script as long as the dependencies (actionpack, activresource, hpricot) are installed.

It can be installed like so:

gem install eve

...and the documentation, including usage examples, is available here.

Feature list is as follows:

* Full coverage of the current EVE API
* Controller helpers which help establish trust (either optional or required) with client IGB
* View helpers which help generate IGB-specific JavaScript calls
* All IGB headers processed and made available to controllers and views easily and silently.. (Read More...)

Mon, Mar 22, 2010

A prevailing theme of my Rails application development, lately, has been authentication and authorization. For implementing this, I always tend to follow the same pattern: Get the Rails app working with authlogic, and then get the app working with declarative_authorization. This works quite well for my needs, but also involves a fair amount of overhead as I tie up the loose ends.

So now, finally, I've gotten around to writing a generator to automate the process, which you are free to make use of if you so choose. Installation is simple:

gem install authgen

Usage is also simple. Jump into your Rails application directory (the one you're about to add auth to), and then...

script/generate auth

...and watch the fireworks! It'll ask you if you want to migrate the database, and if you do, it'll then ask if you want to seed the database. Note that a default user is not created when you seed the database; seeding just adds roles. Create a user by firing up your server and then visiting /register. Log in at /login, and log out at /logout. The rest should become pretty apparent after you take a quick look at config/routes.rb... (Read More...)

Mon, Mar 01, 2010

I've had to implement a number of forms in Rails, and everything is just better with AJAX support. I really like the new support for nested forms, but it's somewhat less than intuitive in terms of how to make it work with AJAX.

I've run into this problem more than once, and each time, my first stop is Google. And each time, I'm dismayed with the results. It seems that this is still a considerable black art, and no one is quite sure of the best way to accomplish it... (Read More...)

Sun, Jan 24, 2010

So, I've decided to bring my various programming-related blogs under the same virtual roof in order to ease their content management -- and, of course, just to give me something more to do with my time. I don't necessarily have a whole lot of said time, but if I weren't filling it to bursting with at least a dozen ongoing projects, then I'd be remiss in my duties!

The original locations for the other blogs will remain active. I'm making the most of Ruby on Rails' baked-in Web Service support so that those locations can pull content from this blog without sacrificing the existing look-and-feels of those sites. To see what I mean, simply add a .xml or .yaml extension to this URL. It works for /posts.xml and /posts.yaml, too... (Read More...)

Sat, Jan 23, 2010

CodeRay is a syntax highlighting engine for Ruby. It supports a more-than-adequate range of languages, and I use it to highlight the syntax on this blog. It's been great, but I ran into a minor trouble when I wanted to change the color of Strings (which default to red, which to me implies 'error') -- I didn't know what CSS class to represent the color with!

This is one of those things that just has to be out there. But since I couldn't find it within 2 or 3 googles, I decided to hack it out of CodeRay myself... (Read More...)

Fri, Jan 22, 2010

One major limitation of RubyTML v1.x is in how it deals with TML variables. While it was still many steps ahead of its pure-TML equivalent, making use of the variables has always felt decidedly unintuitive. They are still remote, client-side variables, and in the end I was never quite able to stop treating a variable as a sort of intangible "thing". In my apps, at least, TML variables never quite felt like they were storing any data. Assigning a value to a TML variable in its present implementation feels way too much like metaprogramming: writing a program that writes a program. Granted, that’s what RTML is all about, but it’s supposed to make it easy -- which, in my own humble opinion, the current variable implementation utterly fails at. Since TML variables can’t really be used until the application is on the terminal, any interaction with them has to be treated basically as static chunks of XML at best, and as flat Strings at worst.

Well, no more. RTML 2.0 is almost here, and with it comes the unleashing of a fully armed and operational Widget. This complete rewrite of the core Widget class makes possible what I’d like to refer to as "High Level Processing" -- that is, the ability to treat a TML variable essentially the same as any other server-side variable without losing the subtle reminders that it is, in fact, a remote variable.

Code time! Here’s an example of the current RTML implementation:

# See if we should prompt for cashback. If so, go to :ask_cashback.
doc.screen :check_cb, :confirm_sale do
  next_screen :ask_cashback, :if => 'tmlvar:prompt_for_cashback == 1'

# Prompt for cashback. There are hyperlinks in the display that lead to either
# :confirm_sale (if cashback is declined) or :check_cb_amt (if accepted).
doc.screen :ask_cashback do
  set 'payment.amount_other' => 0

# Validate that the requested cashback amount is no more than the sale amount.
doc.screen :check_cb_amt, :conf_debit do
  set :message => "Cashback cannot exceed sale amount"
  next_screen :enter_cashbk, :if => "tmlvar:payment.amount_other > tmlvar:payment.amount"

# Prompt user to enter a cashback amount, and then go to :check_cb_amt for validation.
doc.screen :enter_cashbk, :check_cb_amt do

# Finally, confirm the total amount with the user.
doc.screen :conf_debit do
  set :total_amount => 'tmlvar:payment.amount + tmlvar:payment.amount_other'

Now, here’s what the same logic looks like in RTML v2.0:

# Check for whether we should prompt for cashback. If so, display the prompt.
# The :ask_for_cashback prompt contains hyperlinks to either
# :validate_cashback_amount if accepted, or :confirm_sale if not.
# If not, then confirm the sale.
doc.screen :check_for_cashback do
  _if tvars[:prompt_for_cashback] == 1
     # We can also use tvars[:payment][:amount_other] = 0 if that's more convenient.
     tvars['payment.amount_other'] = 0
     display :ask_for_cashback
     goto :confirm_sale

# Validate the cashback amount. If it's under sale amount, go to :confirm_debit_amount;
# otherwise re-prompt the user, showing an error message this time.
doc.screen :validate_cashback_amount, :confirm_debit_amount do
  _if tvars['payment.amount_other'] > tvars['payment.amount']
     tvars[:message] = "Cashback cannot exceed sale amount"
     display :enter_cashback_amount

# Enter the cashback amount, and then validate it.
doc.screen :enter_cashback_amount, :validate_cashback_amount do

# Finally, confirm the total amount with the user.
doc.screen :confirm_debit_amount do
  tvars[:total_amount] = tvars['payment.amount'] + tvars['payment.amount_other']

Now, if you have a keen eye, you’ll notice that the RTML v2.0 code is just a few lines shorter (excluding the comments). But that would be missing the point. Readability is the key, here. I don’t know about you, but personally, I find it much easier to make sense of the second code snippet than of its predecessor. The other thing to notice, a little subtler this time, is that we are actually embedding two different "steps" within the initial :check_for_cashback screen. First, we’re checking whether we should prompt for cashback; and second, we’re actually doing it. RTML is going to generate a screen or two for us in the background, totally automatically. You can imagine how, for really complicated pieces of logic, this can begin to generate reams and reams of (necessary) TML with only a few lines of RTML.

And all along, that underscore at the beginning of each condition is a subtle reminder: "Hey, just keep in mind that you’re still working with remote variables." It’s repeating what you already know, just to make sure you know it: even though it’s easier to deal with remote variables, they’re still remote, and while something like:

tvars[:user_id] = @user.id

might just work, you shouldn’t push your luck with something like"

@user = User.find(tvars[:user_id]) # => Oops, error!

And, finally, even though it’s slightly off-topic, notice the names of the screens in RTML 2. They’re longer and more descriptive. Yeah, TML still only supports a 12-character screen ID, but we’ve worked through that on the RTML side. And yeah, the generated TML is still quite readable. But that’s another post for another day.

So I was working on, well, this very blog tonight, and I finally found a solution to a problem I've been having. See, I wanted to be able to sort these posts into Categories, as well as attach Tags to them. I'll focus here on the Categories, because the Tags worked identically (enough so that I was able to copy-and-paste the code, though now I'm considering ways to DRY it up).

Consider the following relationships:

class Post < ActiveRecord::Base
has_many :post_categories, :dependent => :destroy
has_many :categories, :through => :post_categories

class PostCategory < ActiveRecord::Base
belongs_to :post
belongs_to :category

class Category < ActiveRecord::Base
has_many :post_categories, :dependent => :destroy
has_many :posts, :through => :post_categories

I wanted to be able to list the Categories in the view and put checkboxes next to them. If the box is checked, the post is sorted into that Category; otherwise, it's not... (Read More...)

Tue, Jan 12, 2010

Despite my apparent silence, I’ve actually been hard at work on RubyTML 2.0. In this new version of RTML, the Widget plays an even more pivotal role: the entire framework rests on its shoulders, so it’s imperative that it all comes together just right. While writing the new and improved Widget code, I found myself with a strange dilemma. The proxying system that is in charge of adding the Widget entry points (formerly called Accessors) uses modules to mix-in the entry points with its targets. It accomplishes this by maintaining a single Module instance for each target, such as "document", which then includes the proxy modules from individual Widgets. Think of it as a many-to-many relationship for modules.

Herein lies my problem. When a module is included into a Ruby class, the class apparently creates a link to that module. When new methods are added to that module, the class knows to send calls to those methods into that module. So far, so good. In our case, we’re including a module that has included a module, so it’s got to go a step further. When Class C includes Module M1 and Module M1 includes Module M2, Ruby is smart enough to create these links to both M1 and M2. However, when we then add more methods to M2, Class C can’t detect the change because M1 hasn’t actually changed: it still just includes a module, M2. Technically, no new methods have been added to M1, so Class C can’t pick up on that.

To update the class, then, the module must be explicitly reincluded so that new links can be created. This code demonstrates the issue:

m1 = Module.new
m2 = Module.new
class C; end
C.send(:include, m1)
m1.send(:include, m2)
m2.class_eval { def hello; puts 'Hi there!' end }
C.new.hello          #=> NoMethodError!
C.send(:include, m1)
C.new.hello          #=> "Hi there!"

Since Widgets are now included by symbol, it was not possible to track them explicitly. Luckily, Ruby is awesome so it doesn’t matter. We can iterate through objects of a certain type using ObjectSpace, and we can see if a Class includes a particular module using #include?, so we can do something like this:

class Module # Actually, in RTML we subclass Module to avoid contaminating the environment
  def reverse_include(m)
    include m
    ObjectSpace.each_object(Class) do |o|
      o.send(:include, self) if o.include? self

Such a simple, yet effective solution. Still, I can’t take credit. That goes to kch, who had a very similar problem and was able to shed some light on this trick.

Thu, Sep 03, 2009

If you develop TML in the Canadian or European (or most non-US) markets, you’re familiar with EMV processing. You’ve probably copied and pasted that monstrosity from one app to another since you started writing TML. Well, if you’ve moved on to the RTML framework, copy and paste no more!

That’s because the recently-released RTML v1.0 fully supports EMV processing, and has all the necessary code built into a Widget that can be called with a single line of code. Yes, you heard right: Those 300, 400, 500 or more lines of TML that you’ve been dragging around with you have been completely replaced by just one line. Want to see it?

supports_emv :entry_point => :emv_start, :exit_point => :enter_amount

That’s it. Seriously.

The :entry_point represents the start of the EMV flow. This is the first screen in the EMV processing logic, and it’s there so that you have a handle on where the EMV processing starts. I could have saved you another 15 characters or so by hard-coding the "emv_start" screen, but I decided in the end that it was a little more important for you to remember how to kick off that transaction. It’s a compromise, because my strict DRY ideology dictates that since you’ll probably use the same name for every app you write, I should just work it into the EMV processing itself and let you get down to using the code. On the other hand, if I did that, then -- admit it -- you’d be checking the documentation (or this blog) every time you needed to process EMV, because you’d never bother remembering the name of the kick-off screen. This is one of the very rare cases where, in my opinion, you’ll actually be more productive through repetition, because you can type that line a whole lot faster than you can pull up a browser.

The second option, :exit_point, is a whole different story. That one is required, because it tells EMV where to go after processing has finished. The standard application flow for an EMV transaction goes something like: Idle, swipe, [EMV processing], enter amount, submit. So the EMV piece needs to know where to return to after it finishes to allow the "enter amount" piece to run. In fact, you can think of supports_emv as a sort of function definition for TML. To call the function, send the terminal to the :entry_point. When the function returns, it re-enters your main application at the :exit_point you specified.

That’s it. Honest, that’s all it takes to process EMV cards in RTML. Your document layout, if any, will be applied to each of the EMV screens that need to display information, and of course, you can feel free to override any one of those screens simply by redefining it. But that shouldn’t really be necessary, unless you’ve discovered a TML bug I’m not aware of.

If you really want to, you are also allowed to pass two more options into supports_emv: on_abort and on_error. Their names are pretty self-explanatory: they allow you to override the default screens that display when the transaction is aborted or an error is encountered, respectively. You should almost never have to pass these options (and frankly, nothing stops you from simply redefining the default screens in your application, as described above) -- but you can.

That’s it. Short article this time, because there’s nothing more to say. For reference, here’s what the EMV Support Widget takes care of for you:


  • Card detection and reset
  • Candidate list creation
  • Application selection
  • Reading application data
  • Data authentication
  • Cardholder verification
  • Processing restrictions
  • Terminal risk management
  • Terminal action analysis
  • Card action analysis
  • Online offline decision
  • Online processing
  • Second card action analysis
  • Return control to the TML application

Until next time!