Rails Test Prescriptions Blog

Keeping Your Application Healthy Since 2008

Category Archives: Uncategorized

Moving Day

If you are reading this, you are looking at the old, WordPress version of this blog, and you should come visit me at http://www.noelrappin.com.

Sorry for the inconvenience, all of your bookmarks should transfer to the new site in a day or so. However, if you subscribe to this site via RSS feed at the http://railsrx.com/feed address, I’m not sure that one will transfer over, and you should change it to http://www.noelrappin.com/railsrx/rss.xml.

Thanks, and I hope you will come and visit.

Noel

Control Your Development Environment And Never Burn Another Hamburger

Everything I know about the world of fine dining I know from watching Top Chef and from eating at Five Guys. But I do know this: chefs have the concept of mise en place (which does not mean Mice In Place), which is the idea that everything the chef is going to need to prepare the food is done ahead of time and laid out for easy access. The advantages of having a good mise en place include time savings from getting common prep done together, ease of putting together meals once the prep is done, ease of cleanup. Again, I have no idea what I’m talking about, but it seems like the quality and care that a chef puts into their mise en place has a direct and significant benefit on how well they are able to do their job.

You probably know where I’m going with this, but I’m becoming increasing convinced that one of the biggest differences between expert and novice developers is control over the environment and tools they use. I came to this the hard way – for a long time I was horrible about command lines, it was actually something that kept me away from Rails for a little bit. It’s not like I’m Mr. Showoff Bash Script guy these days, but I know what I need to know to make my life easier.

Let me put it another way. Once upon a time I read a lot of human factors kind of materials. I don’t remember where I read it, but I read once about an expert short-order cook at a burger joint. His trick was that he would continually shift the burgers to the right as he cooked them, such that by the time they got to the end of the griddle, they were done. Great trick (though admittedly you need to be a bit of an expert to pull it off). Not only did the cook know when things were done without continually checking, but it was easy to put on a burger that needed a different amount of doneness simply by starting it farther left along the griddle.

What does that mean?

The name of the game in being an expert developer is reducing cognitive load.

Try and list all the things you need to keep in your head to get through your day. Think about all the parts of that you could offload onto your environment, so that you can see them at a glance, like the short order cook, and not have to check. What are the repetitive tasks that you do that can be made easier by your environment? What can you do so that your attention and short-term memory, which are precious and limited, are focused on the important parts of your problem, and not on remembering the exact syntax of some git command.

This is not about which editor you use, but it is about picking an editor because you like it and understand how to customize it, not because all the cool kids use it. If you are going to use Vim, really learn how to use Vim – it’s not that hard. But if you use Vim, and don’t learn the Vim features that actually make it useful, then it’s not helping you, and it’s probably hurting you. Is Vim (or TextMate, or whatever) making your life easier or not? Vim drives me nuts, but I’ve seen people fly supersonically on it.

I’m getting a little cranky about seeing people’s environments – I’m not normally a big You’re Doing It Wrong kind of guy, but, well, I’m getting a little bit cranky.

If you’re doing web development, there are probably three things that you care about at any given time: your text editor, a command line, and a web browser. Every man, woman, and child developer at my fine corporation has a laptop along with a second monitor that is larger than a decent surfboard. If you can’t see at least two of those three things at all times, try and figure out how much time you spend flipping between windows that you could be seeing together. If you are running Vim in a terminal in such a way that you can never see an editor and a command line at the same time, I think you can probably do better.

If you use Git, for the love of God, please put your git branch and status in your shell prompt. RVM status, too. And it’s not hard to add autocompletion of Git branches, too. Or, go all the way to zsh, which has fantastic autocompletion. Again, reducing cognitive load – you can see your environment without checking, you can type complex things without knowing all the syntax.

Use a clipboard history tool. I use Alfred, which is generally awesome as a launcher and stuff, but it’s not the only one.

Use some tool that converts frequently used text to shorter easier to remember text. Shell aliases do this, I also use TextExpander, which has the advantage that TextExpander shortcuts are usable in SSH sessions.

The thing is, I don’t know what the most important advice is for you. You need to be aware of what you are doing, and strangely, lower your tolerance to your own pain. What do you do all the time that is harder than it needs to be? Is there a tool that makes it easier or more visible? How hard would it be to create or customize something? Are you the cook who can look at the griddle and know exactly when everything will be done, or are you the guy constantly flipping burgers to check?

iaWriter and iCloud, You Know, In The Cloud

If I don’t write about iOS editors every few months, then it’s harder for me to justify continuing to mess around with them…

The thing that’s changed my editor use in the last couple of months is iaWriter Mac and iOS adding iCloud support, even more deeply integrated than Apple’s own applications. iaWriter is the first writing program I use to move to the iCloud future (though there are some games and other programs that also sync via iCloud already).

At a technical level, the integration is fantastic. In iaWriter, iCloud shows up as a storage location, on par with internal iPad and Dropbox storage. If you are just using the iPad version then there is not much difference between iCloud and Dropbox. iCloud saves automatically, but Dropbox lets you use subfolders. (As a side note, iaWriter has improved its Dropbox sync from “show-stoppingly bad” to “works with a couple of annoyances”, the main annoyance being that it doesn’t remember your place in the Dropbox file hierarchy.)

Where the iCloud thing gets really cool is if you are running iaWriter on both iPad and Mac. On iaWriter Mac, you get a command in the file menu for iCloud, which has a sublisting of all the files iaWriter is managing in iCloud, along with commands to move the current file to or from iCloud.

When you make a change to an iCloud file (on the Mac side, an explicit save, on the iPad side an automatic local save), it is automatically sent to iCloud and pushed to the other site. No different from Dropbox, you say. True, except that the iCloud sync behaves much better if a file is simultaneously open in both apps. The changes just appear in the other app. You can put the iPad and Mac next to each other and go back and forth between the two with only a very slight pause while they sync up.

I haven’t quite gotten that level of integration from Dropbox. In particular, if a Lion-aware app has Dropbox change the file behind its back, the original Mac file continues to be displayed with a filename indicating that it is a deleted version. You then need to close the Mac file and reopen it. I’m not sure I’ve seen an iOS editor that polls Dropbox for changes, though one of the auto-sync ones (Elements, WriteRoom) might.

This may seem esoteric, but since I tend to have several blog posts on progress in open windows on my laptop, I do wind up regularly using the iPad to edit an open file. The iaWriter iCloud sync is noticeably less annoying.

It’s not all sweetness and light, especially if you are a really heavy creator of text files. There is no such thing as a folder in iCloud land, which will eventually become an organizational problem. Worse, there’s an implied lock-in to using iCloud that seems to miss the point of using text files in the first place.

When you move a file to iCloud from the Mac, it moves the file to the iCloud hidden directory, which I think is somewhere in the library directory. Although it doesn’t technically vanish from your hard drive – if you can find the file, you can open it in another application (for what it’s worth, the Alfred launcher can find the files), the clear intent is that the file is in a place not to be touched by applications other than iaWriter.

On the iPad side, the situation is worse. If a file is in iaWriter’s iCloud storage than no other iPad app can see it. (To be fair, it is relatively easy for iaWriter to move a file from iCloud to Dropbox from either device.) I don’t know if sharing files between applications will be possible when more applications support iCloud, or whether iCloud is strictly sandboxed.

And hey, for a lot of things, this limitation isn’t an issue. If you are using a tool with its own format, then it is less of an issue that other applications can’t see it. Even with something like text, if you aren’t the kind of crazy that needs to open a file in a gajillion different editors, you are probably okay. If you are using text specifically because it’s easy to move around between different programs, and you have a workflow where a file will commonly be touched by different apps, then iCloud is going to get in your way a little.

As for me, the iCloud support has made me use iaWriter more often for blogs and short notes. (Though I still use Textastic for more structured stuff on iPad.) I always liked iaWriter, but for a while it was just really bad at sync compared to other iOS editors. So, despite some quibbles about what happens in iCloud when I have dozens of files that I want to share among different apps, right now, the sync is good enough to make it valuable.

Things that Should Be Metaphors, Part 1

I present to you two things that sound like they should be metaphors for project issues. Except for two things:

  1. They are real
  2. I have no idea what they might be metaphors for

The Library Book Priority Conundrum

I read a lot. In general, I purchase books I’m very excited about reading, and books that I’m less sure about I check out from my local library. The problem is that I always have more books than time to read, and the library books have the nasty property that the library expects them back sooner or later.

The practical effect is that aside from a few books that are “drop everything” when they come out, I’m forever reading library books first, before the books I’ve purchased, because they will go back home, where as the books I own I get to keep.

Since I’ve already said that I’m usually more excited about the books I’ve purchased and get to keep, this is clearly not optimal. But even knowing this problem, I book I actually purchased (Ganymede by Cherie Priest) has been waiting behind a bunch of library books (That is All by John Hodgman, Kingdom of the Gods by N. K. Jemisin, among others). Okay, those books are great too. But still…

The last clementine problem

I go to the grocery store and buy a bag of clementines. Because they are yummy and easier to peel than grapefruits. Every bag has one or two clementines that are clearly a little less good than the others, so naturally I wait to eat those last. However, since as the clementines get yuckier they become less desirable than anything else in my kitchen, I don’t eat them at all. The result is that I don’t eat the last few clementines, because the pretzels are more enticing. I don’t get new clementines, because I already have clementines, and I don’t throw out the bad clementines until they are well and truly no longer food. The upshot is that I can go weeks without clementines, even though I like them.

Ten Things That Drive Me Crazy About Conference Talks, And How To Avoid Them

If I’m counting right, Ruby Midwest is my fifth conference this year, which is I guess one of the perks of having an employer that likes being involved in the community. It’s great – I like meeting all the smart people involved with Ruby, I learn things, and sometimes people ask me to sign my book. (Okay, that happened once. Still, that’s more than zero.)

At the risk of shooting myself in the foot forty-eight hours before I go give my own talk, here’s a list I compiled for a lightning talk at a recent Groupon Geekfest, entitled 10 Things That Drive Me Crazy About Conference Presentations. I offer it with love and respect. I also note that I’ve committed at least five of these, and will probably commit at least one of them on Friday when I go on at Ruby Midwest.

Here’s the big takeaway: if you are going to the trouble of delivering a live presentation, you need to think of it as a performance, and you need to offer something to the audience that they wouldn’t be able to get from watching the slides.

Coincidentally, Merlin Mann covers similar points from a different perspective on a recent Back to Work Podcast. A lot of good advice there.

Hey, I’m not perfect at this, and posting this pretty much guarantees an epic failure on Friday, but maybe this will help you.

Here’s my list:

1. Underprepared

Do I need to explain this one? Generally my marker here is if the speaker seems surprised by the content of their slides, they are probably underprepared. This isn’t just stumbling around, though. To me it also applies to things like not seeming to know why you are giving the talk, or what you want me, the viewer, to understand when you are done.

If you can’t answer the questions “Who am I aiming this talk at”, “What is the one thing those people should leave this talk thinking”, and “Why is this story going to be compelling to those people”, you are underprepared.

Being nervous is a separate, but related issue. The best fix for presentation nerves that I know of is practice.

2. Overprepared

Yes, it is possible to be overprepared for a presentation. The symptom of this is usually a word for word script that the presenter is reading from, and not paying attention to the audience. The problem, though, is that your talk is brittle, and you won’t be able to adjust to an unexpected audience or environment.

3. Hiding

Most of these conferences are in rooms that are not designed for a performance by a single speaker. Think about a comedy club. The stage is small, not very high, and it’s in the middle. The audience is close together and close to the stage. This is a good environment for a performance.

Picture a hotel ballroom. The speaker is often set up in a corner, frequently behind a podium. The audience is often ten or fifteen feet away, and there is often a lot more space than people. That’s a hard way to go.

Don’t hide behind the podium. Move around. My biggest regret of the whole conference year was not insisting on a body mike at a conference, and having to give a talk from behind a podium. Own the space. You want people focusing on you first and the slides second.

4. Not interacting

A related point. Pay attention to the audience. In a tech conference situation, you are competing with everybody’s laptop and phone, which is to say you are competing with the entire Internet. Can you be more interesting than the entire Internet? At least for a few minutes?

People will pay attention to you as a speaker if they think you are paying attention to them. “[Insert Town] audiences are the greatest audiences in the world” is a huge performing cliché. You know why? Because it works. Anything that gets people involved gives them a little investment in paying attention.

When I was in college, I’d start stand-up sets by coming out with a tape recorder holding it up and explaining that I was recording the performance for my mother, and I’d really appreciate it if the audience could give me one big laugh. Cheesy? Practically coated in cheddar. Effective? Yes.

5. “My Tool Is Great”

This is a type of talk that bugs me. I gave one like this once, and it bugged me when I gave it. Define a problem. Don’t talk about any general part of the problem, just talk about your awesome tool that nobody else is using and why it’s awesomeness is overwhelming. Frequently, this involves ignoring any other way of solving the problem.

6. “My Company Is Great”

Oy. This one usually goes like this:

“At my company we have the perfect process. We never have meetings. In fact, if more than two people show up in the same room, we beat them with sticks. We deploy once every microsecond, and everybody can ask for a deploy, including the people at the company across the hall. We exist in a state of perfect harmony. If you are not like us, your company is substandard. Is that why you are sad? Join us.”

It’s a bit much, and I say that speaking as somebody who has generally been proud to identify with the companies I’ve worked for. What’s usually missing is a) the context of why good processes have taken hold at your company and b) what those of us who are not blessed can do to make progress toward Nirvana.

7. Trendy Slides

A personal pet peeve, and I don’t expect this to bother you as much as it bothers me. In a way, this is another standup thing. It’s easy to get a laughter from an audience without actually being clever. You can shock them, you can flatter them.

For me – and I think I may be alone in this – putting the latest meme in your presentation just because it’s there is in the same category. It’s quick, easy, the audience will react, but ultimately it’s a distraction from what you are trying to. Remember, you want the audience to focus on you, not the slides.

That said, it is possible to add a meme or something cleverly. It’s just that the bar is pretty high.

8. Illegible slides

Let’s make this simple: every word on your slides that is communicating information needs to be clearly legible from 50 feet away, period. The body text on the presentation I’m giving friday is 96 points. With the exception of a few code slides, there are fewer than 15 words on a slide – this is a performance, not an eye exam.

Dark text on light background is usually more visible in a projector context than light text on a dark background.

9. Not knowing the audience

This comes in a couple of forms.

  • Not knowing that your audience may have a different expertise or knowledge level than you expect.
  • Not realizing that people in the audience may be different in general, and have different reference points, or different standards of what is uncomfortable or offensive. They may have genders or nationalities different from your own. That doesn’t mean you have to be bland, but it does mean you need to be aware that there’s a wider world out there.

10. Incomplete lists of ten

July 15, 2011: Stale Links

The problem with sitting on these daily link posts is that the links go out of date. Sigh. Here are some links.

Twitter

I found a couple of things about this InfoQ article about Twitter’s infrastructure odd. I was expecting it to be a bit more of a Rails hit-piece, frankly, so it was nice to see a quote like this one from Evan Weaver:

I wouldn’t say that Rails has served as poorly in any way, it’s just that we outgrew it very quickly.

Twitter has unique needs, so it’s not surprising that the Rails stack doesn’t serve them anymore, but they did get pretty far with the Rails stack.

This was interesting – first, from Charles Humble, writing the article:

You might assume that the move to the JVM was largely driven by performance and scalability concerns, but in fact the existing Twitter codebase performs well… Rather, the move to JVM is driven as much by a need for better developer productivity as it it for better performance

And this from Weaver:

As we move into a light-weight Service Oriented Architecture model, static typing becomes a genuine productivity boon.

The author concludes the article with this:

[Rails] does however come with well known costs, both in terms of performance and scalability, and perhaps also the relative maturity of the libraries and tool chain. In addition, the experience at Twitter suggests that the Ruby on Rails stack can produce some significant architectural challenges as the code base grows.

Which strikes me as an overgeneralization of what Weaver said – I’m almost willing to believe that static typing is a benefit if you are doing SOA at Twitter’s scale, but I haven’t seen the benefit on smaller projects in my experience.

Amazon

As somebody who got their Amazon Affiliate account zapped when Amazon pulled the rug out from under Illinois residents, I was following with some interest the similar news out of California. (Although not quite identical, I had several months notice).

There’s been a little bit of confusion on what actually happened – a lot of people seem to think California is trying to tax affiliate revenue (I can’t find the link, but I saw someone argue that their affiliate revenue was already being taxed so shouldn’t be taxed again, which is wrong in a couple of different ways.) Slate magazine has a decent overview, which I’ll note I basically agree with on the substance of the issue.

Current law is that online transactions are only subject to sales tax if the company involved has a physical presence in the state. The California law defines “presence” to include any affiliates who get a payout – the affiliate revenue isn’t taxed as such, but the existence of an affiliate means that other Amazon transactions in California would be subject to California sales tax. Amazon responded to the law by canceling all their affiliates in California, as they did in Illinois, to avoid having to charge sales tax, and also to avoid having to calculate and manage sales tax, and also to avoid a court case that they might well lose.

Anyway, you may agree or disagree with the California law – though it doesn’t seem inherently any less silly than the various state laws that impose income taxes in visiting professional athletes. For my part, I don’t understand why the fact that Amazon has put themselves in a position where paying sales takes kills their business model should be my problem – I understand why there was an initial push not to charge sales tax on the internet, but I think the social benefit of privileging on line sales has probably passed. Even if you don’t agree with that argument, though, it’s hard for me to see how Amazon using their affiliates as pawns is the best or most responsible way for them to be advocating their case.

New additions to the workflow

I’ve got a couple of new writing workflow things to mention. There’s a new app in the Mac App Store called Marked, which is a classic “One Thing Well” deal. For $2.99, it’s basically a Markdown preview window, but has the very useful feature that it will live-update a file you are editing every time you save. So it’s basically adding MarsEdit’s preview window to any editor. It also makes it easy to copy the resulting HTML into the clipboard if you, say, want to post it to WordPress. It also lets you change the Markdown processor if you’d like. It’s nicely handy for $2.99.

On the iPad side, WriteRoom has finally been updated to a universal app. It’s effectively PlainText Pro – the same basic (pretty) layout with a couple of extra features. It’s got an easy to configure extra keyboard row, and a couple of other handy features. My main negative is that, when the app is in landscape mode it doesn’t use all the horizontal space for text, that’d be a useful option. One thing I like about it, relative to other editors is that it live-syncs with Dropbox, giving much more of a feel of directly editing the Dropbox file than the other editors that make you download the file locally and manually sync. Overall, though I like it.

I also tried out an iPad app called Daedalus, which has a very interesting UI metaphor but doesn’t really fit with the way I manage files. If you are willing to do all your notes and writing in it, though, the organization looks like it might be handy.

RubyMine 3.2

Quick mention that RubyMine 3.2 is out, with support for Rails 3.1 features like the asset pipeline and CoffeeScript. Mostly, I’m having some stability problems with it (it tends to freeze up for me), but the editor and its interaction with Rails continues to get better.

Avdi on Law of Demeter

Finally, speaking of things I thought I was going to disagree with, but wound up agreeing with almost completely (and also speaking of week-old links…), here’s Avdi Grimm on the Law of Demeter. Avdi comes down on the side of actually useful guidelines for managing chains of method calls.

June 30, 2011: Among Other Things, Me In Texas

So, as threatened on Twitter, I decided to overreact to Vim users by trying out BBEdit for my Rails development. Expect a write up soon, but the first pass is that it’s clearly a very powerful program, but it also clearly was developed in response to a set of needs that are not completely congruent with my needs.

1. Contains Me

I’m very excited to mention that I’ll be doing a day-long training session at Lone Star Ruby Conf. The session is entitled Being Correct is Only a Side Benefit: Improve Your Life with BDD. Here’s how I’m describing the session:

In this workshop, attendees will build a complex program using the strict BDD process. Along the way, they will see how BDD improves developer speed and code quality, learn the five habits of highly successful tests, and discover how to best leverage existing tools to improve their coding life.

It’s going to focus on the BDD process itself, rather than on specific tools, and on the benefits to your code from writing tests first.

You can sign up for the session at the Lone Star page. Please sign up, it’s going to be a lot of fun, and we’ll all get better at testing together.

2. Ruby Readability Links

Here are a few recent links on readability and Ruby code

Josh Susser would like to tell you that a meaningful symbol is a better argument than a boolean, while Martin Fowler suggests that it’s even better to have separate methods for each flag value.

Meanwhile, Phil Nash wants to be very clear that he doesn’t like the alternative Ruby 1.9 hash syntax y: 3 as the replacement to :y => 3. I have to admit, I’m not sold on it yet either, it still looks weird to me.

3. Postgres

One of my takeaways from RailsConf this year was the idea that the Ruby community is starting to shift toward PostgreSQL as a database, citing PostgreSQL’s superior performance and stability.

Ruby Inside presents a tutorial from Will Jessop about how to install PostgreSQL on OS X systems. It’s nice, though I’d really like to see the grab-bag of Postgres tools alluded to in the post.

4. Verbosity

Meantime, there was another debate going on about Ruby’s verbose mode, including Mislav Marohnic describing how Ruby’s verbose mode is broken, essentially because verbose mode is both verbose, and a code lint, whereas it might be more useful to separate the features.

For his part, Avdi Grimm extends the post and defends verbose mode by describing how Ruby’s verbose mode can be helpful, and providing a different perspective on some of the warnings.

5. Drumkit

Just yesterday, Obtiva’s own Chris Powers presented his nascent JavaScript web framework called DrumKit.js. The goal of DrumKit.js is to provide a framework where as much code as possible can be shared between the server — in this case running Node.js, and the client — running in JavaScript on the browser. So, once the page goes to the client, subsequent requests are handled in Ajax, but the application code remains the same.

It’s a super-cool idea, and I’m looking forward to it getting fleshed out and expanded over time.

June 15, 2011: Six Sigma Tyrannis

Hey, twice in one week. I might be actually getting back on a pattern here…

1. Popular Crime

Catching up on books, I started off last month with Bill James’ Popular Crime. James, known mostly for his writing about baseball, has written a labor of love book about, well, popular crimes.

There’s a whole ‘nother essay to write about how the way James approached both writing about baseball and what you’d have to call the scientific method warped my brain way back when.

Anyway, what I was expecting here was something like James’ book on the Baseball Hall of Fame — a mix of history with a meta-level talking about why things are the way they are. That’s mostly what we’ve got here, it’s a book that careens back and forth from, say, arguing Lizzie Borden’s innocence, to trying to classify types of evidence, to the Lindberg baby, to a taxonomy of what makes a crime catch the public interest. You’ve probably never read anything like it.

I can’t quite say it has the level of insight of James’ baseball books, and judging from the Amazon reviews, it’s clearly not for everybody, but I thought it was mostly riveting. James is great when he gets opinionated and cranky, which is a large part of the book. The biggest failure is a lot of the individual stories kind of end abruptly.

2. Six Sigma, Tyrannis

Excuse me while I giggle over my own obscure headline joke.

Ahem.

Coming from the weird intersection of technogeekery and politics is this item about Republican candidates embracing Six Sigma as a way to cut government spending.

As a former employee of a company intimately associated with Six Sigma, I can have no other reaction but to shudder uncontrollably.

3. Teaching Rails or Off The Rails

I believe this is what they call in the biz a “grabber”, by Steve Coast

Ruby on rails used to be about elegant simplicity, now it feels like it’s about disappearing up its own asshole.

Okay, you have my attention.

Coast goes on to claim that Rails is leaving newbie developers behind:

But it just feels like we’re making this herculean effort to write elegant code and disappearing off on our own cloud of perfection, leaving behind anyone who wants to learn rails…. Rails is busy optimizing for the anal superior coder who wants to learn things for the sake of learning things, which is neat and cool but not worth it if you just want to make a website.

I am of two minds here.

On the one hand, it is objectively true that it is harder to teach Rails than it was in the 1.x time frame. The REST stuff adds a layer of indirection to everything that is not intuitive, there are a lot more library choices, you actually have to know a JavaScript library to get started now, and so on.

I can make that claim because I’ve taught Rails on both side of the divide. I can’t make a strong claim about Rails vs. other frameworks in this case, because I haven’t put in the effort to try to teach them to newbies.

I’d argue, though, that there has been a reason why Rails has gotten more complicated, and I don’t think it’s because the Rails core team likes complexity or because they have let things get away from them.

I think web applications turned out to be complicated.

I think that, although the path from novice to initial website is probably harder than it was four years ago, the path from initial website to good, actually practical website is much, much shorter. There are a lot of things in the Rails ecosystem that are much easier to do in 3.1 than in 1.x, and most of them have to do with the difference between the 15 minute blog app and a real web app that can handle complexity and traffic.

Later update: It wouldn’t be a RailsRx daily update without Yehuda Katz. He explains some of the technical issues behind Rails changes referenced in the earlier article.

4. Pipeline Those Assets

In a related story,
The Flowdock blog has a nice post about the new Rails 3.1 asset pipeline.

One thing to call out for updaters that wasn’t mentioned is this:

stylesheets and asset helpers are broken and should be replaced with call to relative helpers, e.g. image_path /images/subdir/rails.png should be asset_path “subdir/rails.png”.

5. SpiderMonster

And, just ’cause, here’s the Sesame Street parody of the Spiderman musical.

June 13, 2011: The Kathy Sierra Question

1. Annnd… We’re Back

Okay, I’m trying the semi-regular daily links post again. Two changes from the last time I did this: a wider range of links beyond just Ruby, and it probably won’t quite be daily, but more when I build up five things that I have a short opinion on.

Mostly, though, I need to get back in the habit of actually finishing posts, and realizing that I don’t need to write a 2000 word essay on something for it to be posted here.

2. Grantland

Speaking of not linking to Ruby topics, Bill Simmons launched Grantland this week, a new site which intends to put form long-form magazine-style articles on sports and pop culture, featuring Simmons, Chuck Klosterman, Dave Eggers, and then some. I’m excited for a few reasons: not least is that there’s a lot of talented staff involved, and the website doesn’t look like a bunch of ads with a tiny amount of content in the middle.

Whatever else you may think of Simmons, he’s always been respectful of great magazine writing of the past, and if this thing works it’s going to be a constant destination. Highlights of the first week include a very long review of L.A. Noire that turns into a discussion of games, fun, and storytelling, and Charlie Pierce’s’ history of his time at the National Sports daily (especially interesting because Pierce and Simmons have feuded a bit in public..)

3. Kathy Sierra is Back

It’s always a good thing when I’m reminded that my projects need a little more Kathy Sierra, and she dismantles unneeded social networking and gamification in a blog post this week. The takeaway is that you don’t want to be the kind of product that’s
dependent on gimmicks to work, and, as always, the question is “How do I help
my users be awesome.”

4. iOS 5 Thoughts

Just a couple of quick thoughts on iOS 5, iCloud, and upcoming Apple things.

  • I’m already enjoying having apps and things automatically download to
    my device after I purchase them. I can’t wait for the full wireless
    sync. In particular, I hope they fix iBooks, because for some reason, the
    iTunes mediated iBooks sync has a lot of trouble keeping the same books
    on two devices. Especially if they are being sideloaded, and especially if
    they get updated with a new version, like, say, a Pragmatic beta book.
  • I currently have at least four possible sources of truth for my calendars
    (three devices, plus a Google Calendar). I couldn’t tell you on a bet how
    they interoperate at the moment, so some clarity there would go a very
    long way.
  • I’ve seen some reports about the iTunes match service that state that the
    $25 a year effectively protects you against any accusation that your
    music is pirated. But as far as I can tell, they’ve all been second-hand.
    I don’t think we’ve seen an official Apple source confirm that — at the
    actual event, they were careful to say that iTunes Match worked on CD’s
    that you had ripped. (The exact statement on the website right now is
    “including music you’ve ripped from CDs or purchased somewhere other than
    iTunes”.)
  • Seems like everybody is really quick to write off indy apps that overlap
    with new features announced last week (Instapaper, Due, Dropbox, Camera+,
    Sparrow just to name the first few off the top of my head). In, I guess,
    the same way that the weather app killed off all other weather apps, or
    the existing camera app killed off other camera apps or… I could do this
    for a while, the point is that some of these apps are in trouble, some
    are already providing a better experience than the official app, and some
    will appeal to a specific niche. Just like now.

5. Dream of the blue lobsters

Hey look, a blue lobster. Really.

Can I have your attention please?

So, apropos of nothing, and after RailsConf, some thoughts on public technical speaking. You’re not going to read about how to arrange your slides here, not least because I’m pretty bad at the fancy slide thing. Instead, I want to talk about working the room. This is what I try to do when I give a technical talk.

You should think of this kind of presentation as a performance. You have a story to tell and information to share, and you want the audience to pay attention to you. (One reason why I don’t push too hard on fancy slides is that I want the audience to pay attention to me, not the screen.)

The key to a successful performance is energy. Energy means that you come off as excited and happy to be there, and interested in your subject — interested people are (to a point) the most interesting. Energy means speaking with inflection and volume. Energy doesn’t just come from the speaker, it comes from the audience, and their attention to the speaker. Even in a quiet room, you can tell the difference between an audience that is paying attention and one that is not.

Any stand-up comedian will tell you that you get the best energy from a room when people are close together and when you are relatively close to them. Picture your classic comedy club. The tables are close together, the performer is only a few inches higher, at most. Also, everybody is drunk, but that’s generally not an issue at a tech conference. At least not in the morning…

Anyway, picture your typical conference setup. A hotel ballroom, badly lit. The speaker can easily be 10 feet from the audience, and the audience somewhat spread out, and often with computers as distractions. Sometimes the speaker is set up far away from the projector screen and it’s not easy to move around. Granted, you’re not trying to be Bill Cosby up there, but your job is getting and keeping everybody’s attention, and that means fighting the room.

You’ll never have more attention than you will right at the beginning of your talk. Take advantage of that moment. Do something up front to engage the audience. Surprise them a little. This doesn’t mean “open with a joke” — for God’s sake, don’t open with a joke unless you are about 120% sure the joke will land. It does mean starting off by asking a question, or calling out to the audience in some way. At RailsConf, I started with an unrelated slide that was a kind-of-funny session title of a Medical conference in the same building. At RedDirt, Jeff Casimir dared the audience to close their laptops or give him the finger for twenty minutes, which got my attention.

It’s a classic stand-up trick to start with a “Hello, Cleveland” or something to get a cheap applause line up front. (When I was in college, I would go on stage with a tape recorder, and ask the audience to laugh and applaud so I could play it for my Mom. Cheap. Effective.)

The key, though, to dealing with an audience is to both be and appear responsive. Don’t hide behind a podium, if you can help it. Pay attention to whether people look confused. I like allowing questions during a talk unless there’s a really good reason not to, because interactive tends to be more engaging, but you do need to be ready to cut somebody off if needed to get on with your material.

Preparation always helps. It’ll also help you be less nervous. There are three kinds of useful practice for public speaking.

First, of course, is practicing the content of your presentation. I’m not really giving tips here on how to structure a technical talk, but your goal here is to be comfortable enough with your material to remove that as a source of nervousness as you speak. Another way to look at that is the less effort you need to place in deciding or remembering what to say, the more effort and attention you can pay during the presentation to observing the audience and monitoring how things are going.

I will say that I’m not a big advocate of writing down your talk verbatim — my experience is that it’s hard to read something word for word in public and have it sound natural. Normally I write an outline (usually it becomes my slides), and occasionally use brief notes to remind me of specific points I don’t want to forget. The reason for knowing your content well, though is not so that you can deliver it perfectly from memory, but so that you can free yourself up to be flexible during the actual presentation.

I find it hard to do a full-energy version of a practice talk when it’s only me, and I recommend not even trying — fake enthusiasm isn’t helpful. When you practice by yourself, it’s about the content first, and secondarily about the physicality of the performance itself. The actual physical act of delivering a talk is the thing that I suspect people don’t practice enough. Just standing in more-or-less one place is a challenge. Even at home, try to practice in as close to the real setup as possible. Stand up. Understand how far from your computer you can be and still have the remote work. Try not to pace unrealistically (I fail at that, I tend to walk all over when I practice). Try not to stop, so you get used to talking for 45 minutes.

On a related topic, if you get a chance to scope out the actual room before you talk, do that. Being early and making sure that technical stuff is in place will make you less nervous, and give you some time to scope out the audience before you start.

Finally, you want to practice in front of an audience in general. Every chance you get to realize that the audience is unlikely to eat you if things go badly is helpful. There are things you will only learn by getting used to seeing an audience in front of you. Talk to specific people. Try and get feedback. If possible, watch video of yourself, you’ll definitely see something you can get better at. When I was a high-school performer, a director had me watch a fast-forwarded version of a performance, which really exaggerated a habit I had of swaying back and forth. Being aware of these habits will help you get rid of them.

Oh, and that thing about picturing the audience in their underwear… Don’t do that. It doesn’t work.

RailsConf 2011

A quick trip report seems like a good way to break up some weird mutant form of writer’s block that has been preventing me from finishing any of the six or so half-written blog posts I have in my queue.

This was my third RailsConf (not 2010, but the two years previous), and it was pretty easily the most fun. I know more people there now, and more people know me, that’s part of it. But there also was a much different vibe than 2009 — for instance, this year there were a lot more companies looking to hire…

Quick notes and impressions:

The best general talk I went to was the backbone.js talk by Matt Kelly. Not only was it well presented, not only did it compare JavaScript to Ke$ha and end with an impromptu screening of the highly weird and silly “Blow” video, but I actually came out of it understanding how backbone works why somebody would use it.

T-shirt score: 5 — Heroku, Engine Yard, Pivotal, Spiceworks, and the official RailsConf shirt. I did briefly have one of the ping-pong-ball burp guns that Engine Yard was handing out, but I left it in my hotel room because a) it didn’t fit in my bag and b) didn’t feel like becoming random TSA fluke guy for the week.

I was pleased with my IgniteRails talk, though I blanked on a line at one point, which made it more repetitive than I wanted. It was a really good set of performances, and a surprising amount of people.

My main talk went well, I thought. When I asked before I started how many people were there because there was nothing better in the time slot, a lot of hands went up. I laughed, and somebody tried to convince me that was a good thing…

As I referenced in my talk, the medical convention on the next floor had some really amazing sounding talks, like “All knees are not created equal: a global perspective.”

I liked David Chelimsky’s talk on duplication, with the idea being that there is more to duplication than just string comparison — true duplication has to do with each piece of information in the system having a single source of truth. David also made the point that sometimes the cost of removing duplication is higher than the cost of keeping it. This led to some interesting discussions of refactoring, clean code, and what is really too much refactoring.

Rails 3.1 release candidate finally came out. I actually like having a home base for SASS templates and CoffeeScript, and I’m looking forward to giving CoffeeScript a real tryout. The rest of the asset pipeline stuff doesn’t thrill me yet, though I’m sure it’ll be useful. There are a couple of other bits and bobs that I’m interested in trying out — it looks like a solid point release.

The reaction to the Steele and Gabriel 50 in 50 keynote was interesting. Some people seemed to really hate it — I’m guessing that it helped to have a little bit of background in programming language history, since Steele and Gabriel were deliberately elliptical in their descriptions. I liked most of it, and was particularly surprised by my own reaction to the Logo bit. As a former edtech research, Logo was always the grail — there was so much hope in that research that doesn’t seem to have quite been replicated.

I really want to thank the 20 or so people who turned up for the testing BoF session at late O’Clock on Wednesday. I thought it was a really great, respectful discussion of issues surrounding getting started with testing, and I enjoyed it very much.

And this happened. You’ll want to go to about the 39:50 mark.

Great week. Thanks to the RailsConf organizers.

RedDirt RubyConf

I was fortunate to spend this Thursday and Friday at RedDirt RubyConf in Oklahoma City. Here’s a quick conference report, and random thoughts about single-track conferences in general.

This is my second try at writing this post, excuse me if it’s a little disjointed (the first one was eaten by my writing tool — the dark side of continually trying out new writing app, but more on that later…)

I want to make sure I say up front that James and the rest of the organizers did an outstanding job with the logistics of the conference. I’ll talk more about the format later, but there was power and WiFi, they were able to keep the speakers on time, the mix of speakers and attendees was overall great, with a nice range of experience levels and expertise represented. There was plenty of time built in to meet the other attendees — even I, who am by nature not great at this stuff, managed to meet lots of people.

It got me to thinking about what kind of talk works in a single track environment when you are speaking to an audience that is essentially captive, and also has that wide range of interests and experience. For example, the best talk of the day, by general acclimation, was Jeff Casimir and his talk about fat models and Rails code design. Not only was it strong from a presentation or performance perspective — there’s something to be said for “shut up and listen to me” swagger — but it also had something for everybody. The novices could be inspired by Jeff’s examples, and learn something about good practice. The experts could nod sagely, pretend they do all those practices consistently and pick nits.

In contrast, you have talks like, to pick an example at random, mine. Now, I like my talk. I really like the tool I presented, I was happy to be able to introduce a tool at the conference, and I think the talk was a clear introduction. It was also only immediately relevant to a small percentage of the audience, based on show of hands. I’m not complaining, mind you, I think it’s great for people to be exposed to ideas outside their immediate needs. Part of the genius of the RRDC format is that if you weren’t interested in a particular topic, there was only a short wait until the next speaker.

Anyway, it was fun, and I’m glad I got a chance to go.

Summer Breeze Makes Me Feel Fine Blowing Through The Jasmine In My Mind

I just gave my RedDirt RubyConf talk introducing a new gem for JavaScript testing from a Rails app called Summer Breeze. It makes you feel fine, blowing through the Jasmine in your mind.

More specifically, Summer Breeze is a tool for generating fixture DOM output for Jasmine JavaScript tests directly from your Rails Views with a simple DSL for specifying fixtures

Summer Breeze is based on work by JB Steadman and Jonathan Barnes that can be found at http://pivotallabs.com/users/jb/blog/articles/1152-javascripttests-bind-reality-

Please note that Summer Breeze is an early release, with limitations, and will likely change over time.

Why Use Summer Breeze?

Jasmine is a great tool for BDD testing of JavaScript. When testing the JavaScript front end of a Rails project, often the JavaScript functionality will depend on a specific DOM structure being present on the page. Ideally, your Jasmine tests would be written in such a way that if the page view changed, the JavaScript test would fail.

So, Summer Breeze provides an easy way to have your Rails views be generated on the fly and used as input to Jasmine tests

Installing Summer Breeze

Summer Breeze requires Rails 3 and Ruby 1.9. (1.8 support is a future possibility, Rails 2 is less likely.) Jasmine must be installed, and right now there’s a dependency on Devise for authentication.

To install include in your gem file

    gem summer_breeze

After the bundle is installed, use

    rails generate summer_breeze:install

This creates two files, spec/javascripts/helpers/summer_breeze.js which contains JavaScript utilities, and spec/javascripts/support/summer_breeze.rb, which is where you put your Summer Breeze fixture definitions.

Defining Fixtures Summer Breeze

Summer Breeze fixtures are defined in the summer_breeze.rb file. The easiest way is with the fixture command

    fixture "PostsController##index.body_container"

The syntax is the controller name, followed by a ##, followed by the controller action, followed by an optional DOM element. If the element is specified, then only markup inside (and including) that element is saved in the fixture. This allows you to limit your fixture to only the part of the page you care about. If there is no DOM element (delimited by either a ‘.’ or a ‘#’), then the entire body of the page is saved. In any case, at the moment, any markup inside a DOM element called #third-party-scripts is automatically discarded.

Additional options to the fixture can go in an optional block

    fixture "PostsController##index.body_container" do
      params(:id => 1)
    end

These options can take a simple value, evaluated when the Summer Breeze file is loaded, or a block, evaluated when the fixture is run

These options include:

  • action — The controller action, overrides anything that might come from parsing the string argument to fixture.
  • controller_class — The controller class, also overriding anything that might come from parsing the string.
  • filename — the name to save the fixture to, otherwise defaults to the action and DOM id
  • flash — a hash of values in the flash, as in a controller test
  • limit_to_selector — the DOM element to limit output, overriding the parsing of the argument string
  • method — HTTP method of the action to take
  • params — A hash of parameters sent to the controller
  • session — A hash of session values sent to the controller, as in a controller test

You often need to do some setup, such as creating a logged-in user, before running the fixture. These setups can be defined with initialize blocks

    initializer :create_user do
      @user = User.new
      controller.sign_in(@user)
    end
    
    fixture "PostsController##index.body_container" do
      initializer :create_user
    end

The argument to initializer within the fixture block is either a symbol referring to an already defined initializer block, or a block or lambda in it’s own right.

Fixture files are stored in Rails.root/tmp/summer_breeze

Using Summer Breeze in Jasmine tests

Summer Breeze provides a few methods for loading the fixture file:

    sb.loadFixture(fixture_name)
    sb.findSelector(fixture_name, selector)
    sb.readFixture(fixture_name)

The loadFixture method reads the matching fixture file and adds it to the Jasmine DOM for further use. The findSelector method does the same, but also returns the the matching selector as a jQuery object. Finally, readFixture returns the HTML text of the fixture without adding it to the Jasmine DOM.

A sample test might look like this. Note that the jasmine-jquery extensions are very helpful in writing these tests

    it("hides text when asked", function() {
      $form_container = sb.findSelector('login', '.form_container');
      toggle_handlers.init();
      $hide_link = $form_container.find(".toggle_link");
      expect($hide_link).not.toHaveClass("hidden");
      $hide_link.click();
      expect($hide_link).toHaveClass("hidden");
    });

Summer Breeze Limitations

There are two limitations to these fixtures based on how they load data. The main one has to do with event handlers. Any handlers that are loaded as part of the header script on the page, such as application.js in a typical Rails application, will not be applied to the fixture markup even if the JavaScript file is loaded as part of Jasmine’s setup. This is because Jasmine loads those files first before the markup fixture is loaded. Any handlers or such like that you want referred to in the test must either be part of the fixture markup, or the handlers must be explicitly loaded as part of the test, as in the above test, where you can imagine that toggle_handlers.init() is defined elsewhere in the code.

Similarly, stylesheets are not attached to the fixture, so any outcome which depends on style elements defined in the stylesheet will not work.

And In Conclusion, I’m not done

I hope you find this kind of useful, I’ve been using it a little bit, and I like the workflow.

Overriding Refinery, Extending Globalize, and Pow!

Here are a few random tips that have come up while working on an application using Refinery CMS, Globalize, and who the heck knows what else…

Extending stuff from Refinery

Refinery is about as extendable as a Rails framework gets. Although it provides you with a lot of default behavior, it’s not that hard to override.

Refinery is made up of a collection of Rails Engines. For example, the main display of pages is in the refinerycms-pages sub-gem. If you want to override a controller or view element in these gems (which include Page and User), Refinery provides a Rake task refinery:override which copies the file into your main application, effectively overriding the default version.

It’s a little different if you create your own data types. Refinery generates a Rails Engine for each type, which means that all the controller, model, and view files are actually in your vendor/engines directory and accessible to you (although they do require a development server restart when you change them…) However, a lot of the default CRUD behavior is defined by Refinery in the refinerycms-core gem via the Refinery crudify method, so if you want to change some default behaviors, you either need to look up and copy the existing Refinery behavior, or try and implement your new behavior as a before filter (preferred, if possible).

If you want to extend one of the existing Refinery models, most notably Page or User, you can re-open them to monkey patch in your app, but it took us a few tries to learn the magic require statement:

  require Refinery::Pages::Engine.config.root + 'app' + 'models' + 'page'

Globalize

The Globalize3 gem is used by refinery to manage i18n content. Globalize works by setting up a separate translation table tied to your model. In your model, you specify which columns are translated (plus you need to specify a migration to create a translation table — Globalize has a shortcut for that):

  translate :description, :text

Behind the scenes, when you access the ActiveRecord object, Globalize joins the object with the row in the translation table corresponding to the current locale, and allows you to transparently access the translated versions of the fields corresponding to that locale. Very cool. (Note that once you have added the description and text fields to the translation table, you no longer need them in the main model table.)

A couple of things to be clear on:

Setting locale

I’m not completely sure whether this comes from Refinery or Globalize, but there seem to be two sources of truth as to the what locale is used. Rails uses ::I18n.locale, while Refinery uses Thread.current[:globalize_locale]. We had some difficulty with what appeared to be confusion over these being in synch, and at least temporarily have fixed the problem with a before filter, along the lines as the Rails guide on i18n suggests:

  before_filter :set_locale
  def set_locale
    ::I18n.locale = params[:locale]
    Thread.current[:globalize_locale] = params[:locale]
  end

That seems to solve our problems with a single source of truth, but it does feel a little string-and-sealing-wax, so there’s probably a better way.

Adding functionality to Translation models

One nice side effect of the way Globalize manages locale-specific content is that you aren’t limited to things that are technically translations, anything that is different in each locale can be added to the translate list. For example, if you need to track the author of each particular translation, you can add a :user_id column to the translates call, and place the corresponding column in the MODEL_translations database table and you are good to go.

Except for two things. First, if you want to actually treat that user_id as an ActiveRecord association, you need to add a belongs_to method to the Translation model. Unfortunately, that model is created by Globalize using some metaprogramming magic and doesn’t have a physical location that you can use to update the class.

Happily, this is Ruby, and you can always re-open a class. It took me a few tries to figure out exactly the best place to open the class so that I could actually be opening the right class, but I eventually got to this:

  class MyModel
    translates :text, :user_id
     
    class Translation
      belongs_to :user
    end
  end

Yep. Nested classes. In Ruby. In essence, the outer class is doubling as a module, which implies the translation class could be defined elsewhere, but I’m not sure that’s worth more times to track down.

The other issue is that the Globalize command to automatically create a translation table based on the translates command for a class does not like it if you have non-string columns, such as user_id, in the list of columns to translate. You need to create the translate table using a normal migration. This is even true if you add the user_id column later on after the initial creation, a user running the migrations from scratch after the user_id is added will still have problems.

Pow

I started using Pow to manage my development server. I like it quite a bit, it gives me what I used to have with the Passenger preference pane, but with a support for RVM and less overhead. I recommend the powder gem for a little more command line support.

Anyway, I needed to debug a Facebook issue, which requires me to have my development environment temporarily use the .com address that Facebook knows about in order to use Facebook connect from my system. But how?

Here’s how I did it using Pow:

  • Use the Mac application Gas Mask to change my /etc/hosts file to a file where http://www.myapp.com points to localhost. Gas Mask just makes managing these files easier, you could just edit the file directly

  • Create a symlink in the .pow directory used by Pow named “www.myapp”, and pointing to my application directory. With Powder you can do this from the command line in the root of the application with the command powder link http://www.myapp. This is fine to do even if you have another symlink from the .pow directory to the app

  • Create a .powconfig file in your home directory. Add the line export POW_DOMAINS=dev,com, save the file. This tells POW to try and apply itself to .com requests from your machine. Pow seems to be smart enough to pass through .com requests that don’t match it’s files, so you shouldn’t be cutting yourself off from the entire internet.

  • Restart Pow. Unfortunately this is not like restarting Pow for your one dev server, you need to restart the whole Pow system so that the config file is re-read. As of right now, the only way to do this is to go to the application monitor, find the Pow app, and quit it from there, or the command-line equivalent using ps -ax | grep pow to find the PID and then killing it from the command line. (If I get around to it, this is my pull request for Powder)

And that should be it — http://www.myapp.com should be picked up by the Pow server and run in your dev environment, making Facebook connect happy.

When you are done, comment out the line in the .pow config and restart Pow again. Also change the /etc/hosts file back. You don’t need to remove the symlink in the .pow directory, but you can.

That’s all I’ve got today. Hope that helps somebody.

Nebulous, or More iPad Text Editors. Really.

Hey, guess what, I’ve got another iPad text editor or two to review.

The thing is… I really like writing on the iPad, with or without the bluetooth keyboard. It’s a very lightweight, fun writing machine. But all the editors I’ve used have flaws that have been making them less than workable for me. I still like them, but I’m getting resigned to their limitations.

For example, iaWriter doesn’t see subfolders, meaning that it doesn’t work with Scrivener sync directories. Plus, its sync feature is annoying, and likes to recreate files that I have deleted. It also has a charming habit of not remembering the last open file, and choosing which file to start with seemingly at random. Textastic fixed some of its bugs, but typing is still laggy from the bluetooth keyboard, and the actual display of the text is awkward if you are doing text and not code. I’ve been using PlainText, which has a nice direct sync with Dropbox, but is deliberately not as fully featured as some of the other tools.

I’ve got a couple of new contenders. One is named Nebulous, which is a criminally low $2 on the app store right now, the other is Notesy, which is $3. Without much more ado, lets see how they stack up against the functionality that I find useful in my iPad text editor.

Dropbox support:

Nebulous let’s you read anything on your Dropbox folder, but it doesn’t auto-sync. It does let you open files regardless of type or file extension, which is a big win. When you select a file, it goes into a “auto-saves” list, which is basically local storage — the “auto” refers to automatically saved locally. You can upload a file as you work on it, or from the list of open auto-saved files. The setup is a little non-intuitive (I think calling the lost “local” files would go a long way.) Nebulous does, however, seem to automatically notice and update if the Dropbox version has changed. Overall, once you get used to the naming scheme, the sync seems to work pretty well. I’d rather have full auto-sync, but the implementation here seems clear and safe.

Notesy syncs with one folder on Dropbox, your choice, and automatically syncs when you change the active document if you are connected. I think it only sees .txt files. The auto sync is nice, but the folder constraint is a minus. However, Notesy does allow you to search the body of all the files in the folder, where Nebulous is limited to only a list sorted by name.

Keyboard:

Both programs support TextExpander. Yay. As far as I can tell Notesy has no other fancy keyboard features.

Nebulous has a upper row of extra characters, similar to Textastic, even down to the fact that the row can scroll, which I’m still not sure about. I am sure, though, that Nebulous adds the fantastic ability to customize the keys in the row, making them effectively one-key shortcuts to common snippets. This includes the ability to create macros that wrap selected text. Wow. Very useful. I can already see how I’d use that to make some killer HTML macros. Extra nice: the macro bar stays on-screen even if you are using the bluetooth keyboard.

Text Settings:

Nebulous has about 10 proportional and 5 monospaced fonts to choose from, lets you select size, and uses the pinch gesture to change font size while typing. There are also some themes, which are kind of pointless.

Notesy has a slightly larger set of fonts and let’s you quickly change a single file to the default Monospaced font from the variable font and vice versa.

Other:

Basic word count style information is more accessible in Notesy. On the other hand, Nebulous let’s you preview in HTML or Markdown for any file, regardless of the file extension, which is handy.

Finale:

Nebulous has pretty much taken over as my workhorse editor. It’s more featured than iaWriter, and smoother then Textastic, although Textastic would probably still be my choice if I am actually editing code. I think, though, that it beats out iaWriter and PlainText, at least for the moment, though there are still features of each of those apps that I like. Notesy looks like it will replace Simplenote, since that let’s me sync with NotationalVelocity via Dropbox, and Notesy seems faster for just creating a new, short file.

Numbers, Crunched, or Publishing Economics

So, I’ve been writing technical books for about ten years. What can I say about that time overall?

Here are two pie charts representing my published books to date. I’ve thrown in the Lulu version of Rails Test Prescriptions just for the heck of it. Care to guess what the pie charts represent?

All sales
   
All money

Before I give the answer, please note that there is basically no correlation between the values in each chart. You’d expect that to mean that the two charts are about completely unrelated data, say time spent on each book versus best Amazon rank, or something.

The first chart (with all the green) represents absolute sales, through March 31. The second chart (with all the purple) represents the approximate dollar amount that I’ve been paid for each book, again, through March 31.

Now, you’d expect the sales and money heading to the author to be roughly consistent with each other. At least, I would. Let me explain why this isn’t so, I hope this will be a kind of interesting glance at the twilight economics of publishing, or why Pragmatic is different from other publishers.

By way of context, I should mention that the absolute total count of all these sales is a number of people that could comfortably fit in Wrigley Field.

You’d think that I’d be able to put my finger on the exact number of sales for each book. That’s actually not the case. Most of the sales numbers are approximate in several different and interesting ways:

  • I get quarterly statements for Jython Essentials but they don’t include a running total of how many books have sold — the pie slice here is a stone cold guess.
  • I haven’t seen a statement on wxPython in Action since the end of 2009. The statement is the thing the publisher sends that tells you how many books you have sold. I could be wrong, and I have no desire to look it up, but I believe the publisher is contractually obligated to send me this information.
  • I also haven’t seen a statement on Pro Rails since the one and only I got right after the book’s release in 2008. Not that I’m whining about it. Okay, I’m whining about it.
  • Lulu reported exact up to the minute sales. Yay. This version was on sale for five months.
  • Sales on Rails Test Prescriptions are obviously incomplete. Pragmatic gives up to the minute details for direct sales via the web site, so right now “incomplete” includes those sales, and an educated guess as to bookstore and Amazon sales in the first month of release. Over the next few months, I’d expect that red slice to get a little bigger.

I’m not 100% sure, but I have reason to believe that the Jython book was somewhat below the average sales for an O’Reilly Animal book at that time, although it’s also pretty specialized, so I don’t know what their expectations were. There were preliminary discussions about doing a second one that never went anywhere, so that might be a clue.

The wx book sold more or less what Manning expected (they told me their expectations right before launch), maybe a hair more by now. Pro Rails, frankly, was a disappointment (at least to me), although I think my expectations may have been unrealistic.

Similar context on the dollar numbers: the absolute value here, again, isn’t all that high given that this is about a decade’s worth of writing. You could kind of buy a car with it, but not a “chicks dig the car” kind of car. (I’m not complaining, mind you, I love writing technical books. Just pointing out that I’m not likely to abscond to the Bahamas on my writing income anytime soon.)

The discrepancy between sales and dollars is partially explained by co-authors. For Jython, the author royalties were split 50/50 with a co-author. For wx, I am on the large side of a 66/33 split. For both wx and Pro Rails, this total does not count 15% that was given to an agent. (Which was well earned, by the way, not least because neither book would have happened without the agency.) For the Pragmatic version Rails Test Prescriptions, this is direct sales from the Pragmatic website only, it’s too early to have gotten money from other sales.

The rest of what you are seeing here is that the author’s per-book revenue is much greater with the Pragmatic model. Also, you are seeing that the Pro Rails book never earned back its advance, which makes it’s per-book rate seem unusually high.

I should back up. Most publishers pay authors an advance, which is typically paid in installments, with the last installment tied to the final approval of the book for publication. After publication, the author gets a royalty, which is a percentage of the publisher’s net sales, and for tech books is typically around 10%. However, the author does not get any royalty money until after the royalty total exceeds the amount of the advance, which is literally an “advance” against future sales. When a book has reached the point where the author is getting royalties, the book is said to have earned out.

The wx book earned out almost immediately, in part because the advance was relatively low compared to the price of the book. The Jython book, somewhat to my surprise, earned out after about seven years, and I now get about $10 a quarter from O’Reilly. Pro Rails will never earn out, unless the book becomes retro and hip.

Pragmatic works a little differently. They don’t pay an advance. Instead, they take their net sales on the book subtract per-book shipping costs plus a couple of other one-time costs, and split the remainder 50/50 with the author. That means a significantly higher per-book payment for the author, and explains why Rails Test Prescriptions is the most money I’ve been paid for a book.

Here’s why self-publishing is viable for technical books: In the Lulu self-publish model, I get 70% of the price of the book. Compare to, say, the Jython book, where I got half of 10% of the net cost, or about 2-3% of the gross sales price. The Lulu book earned me about as much as the Jython book. It’s also a fairly quick turnaround, although the major ebook channels are not very good at managing the process if you continually update a book.

Here’s why publisher-publishing is still viable for technical books: Even with making more money per-book, I still made more total money, and reached a lot more people through traditional publishers. Many things that I have no talent or desire to do — editing, cover design, marketing, indexing — were managed by my traditional publishers. (Well, Manning did make us do our own index.)

Testing Advice in Eleven Steps

As it happens, my generic advice on Rails testing hasn’t changed substantially, even though the tools I use on a daily basis have.

  • Any testing tool is better than no testing. Okay, that’s glib. You can make an unholy mess in any tool. You can also write valuable tests in any tool. Focus on the valuable part.

  • If you’ve never tested a Rails application before, I still recommend you start with out of the box stuff: Test::Unit, even fixtures. Because it’s simpler and there’s a very good chance you will be able to get help if you need it.

  • That said, if you are coming into a team that already has a house style to use a different tool, use that one. Again, because you’ll be able to get support from those around you.

  • Whatever tool you choose, the important thing is to write a small test, make it pass with a small piece of code, and refactor. Let the code emerge from the tests. If you do that, you are ahead of the game, no matter what tool you are using.

  • At any given moment, the next test has some chance of costing you time in the short term. The problem is it’s nearly impossible to tell which tests will cost the time. Play the odds, write the test. Over the long haul, the chance that the tests are really the bottleneck are, in my experience, quite small.

  • If you start with the out of the box test experience, you will likely experience some pain points as you test more and more. That’s the time to add new tools, like a mock object package, a factory data package, or a context package. Do it when you have a clear sense that the new complexity will bring value.

  • Some people like the RSpec syntax and, for lack of a better word, culture. Others do not. If you are one of the people who doesn’t like it, don’t use it. Well, try it once. You never know.

  • I go back and forth on whether Test::Unit and RSpec are actually functionally equivalent, and eventually have decided it doesn’t matter. You can write a good test suite in either, and if there is a particular bell or whistle on one of them that attracts you or repels you, go that way.

  • You really should do some kind of full-stack testing, especially once you’ve gotten good at unit testing. But whether it’s the Test::Unit integration testing, the new Capybara syntax, or Steak, or Cucumber, is, again, less important than the idea that you are specifying behavior and automatically verifying that the code matches the specification. Most of what I said about RSpec above also applies to Cucumber.

  • This old joke that was repeated with relish on the XP mailing list circa 2000: “Doctor, it hurts when I do this”. “Then don’t do it”.

  • And last, but not least, buy my book. Or buy Dave’s book. Or Kent Beck’s book. Or hang out on mailing lists. Ask questions on Twitter. If you want to get better at testing, there are all kinds of resources available.

Cucumber Rails 0.4: The De-Web-Step-ining

Consider this part of an occasional series where I attempt to revisit tools discussed in Rails Test Prescriptions that have undergone some revision. (NOTE: Most of this was written before the DHH Twitter-storm about testing this week. For the purposes of this post, I’m choosing to pretend the whole thing didn’t happen.)

The cucumber-rails gem released version 0.4 last week, which had some significant changes, and intensified what we might call the opinionated nature of Cucumber over what a Cucumber scenario should look like.

If you update cucumber-rails, you need to re-run the rails generate cucumber:install to see the new stuff.

There are a couple of minor changes — the default env.rb file is much simpler, the capybara date selector steps now work with Rails 3, that kind of thing. The biggest change, though is conceptual, and comes in two parts.

Part one is best laid out by the new first line of the web_steps.rb file:

# TL;DR: YOU SHOULD DELETE THIS FILE

The header goes on to say that if you make use of these steps you will end up with verbose and brittle cucumber features. Also, your hair will fall out, and you will have seven years bad luck. The last may be more implied than stated.

Why would they do such a thing? And what’s the “official” preferred way to use Cucumber now?

Well, it’s not like the Cucumber dev team has me on speed-dial or anything like that, but since they subtly included in the web_steps.rb file links to, count ’em, three separate blog posts explaining how to best use Cucumber, I will follow that subtle, yet blazing, trail and try to put it together in some coherent way so that I can understand it.

(Note to Cucumber dev team: if you feel the need to link to this post in future versions of Cucumber, you should consider yourself as having permission to do so….)

Anyway, the Cucumber team is making a very opinionated statement about how to use Cucumber “with the grain”, and I actually don’t think that statement is “don’t use the web_steps” file — I think that some parts of the web_steps file have a place in the Cucumber world.

Here’s the statement as I see it:

  • A Cucumber scenario is an acceptance test.
  • As such, the scenario should completely be in the domain of the user.
  • A Cucumber scenario should not have any reference to implementation details.
  • Implementation details include, but are not limited to: CSS selectors, class names, attribute names, and HTML display text.

As a good rule of thumb, if you are putting something in your Cucumber steps in quotation marks, you should at least think about whether your Cucumber scenario is at a high enough level. In the Cucumber world, the place for implementation-specific details is in the step definition files. If the acceptance criteria changes, the scenario should change, but if the implementation changes, only the step definitions should change.

This sharp separation between the acceptance test and the implementation is a feature, not a bug, in Cucumber (By the way, you do not want bugs in your cucumbers. Yuck.) The separation is what makes Cucumber a true black-box test of your application, and not a black box riddled with holes.

That said, full-stack testing that is based on knowing implementation details — which is “integration testing” rather than “acceptance testing” — is a perfectly valid thing to do, especially in a case where there isn’t an external customer that needs or wants to see the acceptance testing. But, if you are actually doing integration testing, then you don’t need the extra level of indirection that Cucumber offers — you should drop down to Steak, or Rails integration tests, or the new Capybara acceptance test DSL or something.

Okay, so. Acceptance testing is not integration testing, and if you are trying to do integration testing via Cucumber, you will be frustrated, because that’s not what Cucumber is good at. To me, there’s a value in acceptance testing, or in this case, acceptance test driven development, because it’s helpful to try and describe the desired system behavior without any implementation details confusing the issue.

Which brings us back to the question of how you actually replace the web steps in your Cucumber scenarios. Essentially the idea is to replace implementation-based steps with steps that describe behavior more generically. You might have something like this:

Scenario: Updating a user profile
  Given a user named "Noel" with a preference for "Cool Stuff"
  When I go to the edit profile page
  And I fill in "bananas" for "Favorite Food"
  And I select "Comic Books" from "Preferences"
  And I press "Submit"
  Then I should see "Bananas" 
  And I should see "Comic Books"

That’s not horrible, because it doesn’t have any explicit CSS or code in it, but it’s still very much about implementation details, such as the exact starting state of the user, the labels in the form, and the details of the output. On the plus side, the only step definition you’d need to write for this is for the first step, every other step is covered by an existing web step. But… I’ve written my share of Cucumber scenarios that look like this, and it’s not the best way to go. It’s hard to tell from this step what the most important parts are and what system behavior is actually being described.

The implicit version of the scenario looks more like this:

Scenario: Updating a user profile
  Given I am an existing user with a partially completed profile
  When I go to edit my profile
  And I fill in new preferences
  Then I see my new preferences on my profile page

Two questions to answer: why is this better, and how does it work?

The second question first. We need to write step definitions for all these steps. Normally, I write these in terms of the underlying Capybara or Webrat API rather than calling web steps. The second step doesn’t need a full definition, it just needs an entry for /edit my profile/ in the paths.rb file (right now, it seems like that’s about the only step in the web steps file that the Cucumber team is willing to use), but the other three steps need definitions — here’s what they might look like, this might have a typo or syntax jumble, it’s just the basic idea.

  
Given /^I am an existing user with a partially completed profile$/ do
  @user = Factory(:user)
  @user.profile = Factory(:profile, :preference => "Cool Stuff",
     :favorite_food => nil)
end 

When /^I fill in new preferences$/ do
  fill_in("Favorite Food", :with => "Bananas")
  select("Comic Books", :from => "Preferences")
  click_button("Submit")
end

Then /^I see my new preferences on my profile page$/
  with_scope("preference listing") do
    page.should have_selector(selector_for("bananas are my favorite food"))
    page.should have_selector(selector_for("comic books are my preference"))
  end
end
  

If you are used to Cucumber but haven’t used the 0.4 Rails version yet, the last step will look unfamiliar. Bear with me for a second.

Why is the second version better? It’s not because it’s shorter — it’s a bit longer, although only a bit (the first version would need a step definition for the user step as well). However, the length is split into more manageable chunks. The Cucumber scenario is shorter, and more to the point, each step is more descriptive in terms of what it does and how it fits into the overall scenario. The new step definitions you need to write add a little complexity, but not very much, and my Cucumber experience is that the at this size, the complexity of the step definitions is rarely the bottleneck. (For the record, the bottleneck is usually getting the object environment set up, followed by the inevitable point of intersection with implementation details, which is why I’m so keen to try and minimize intersection with the implementation.)

Yes, the scenario is something you could show a non-developer member of the team, but I also think it’s easier for coders to comprehend, at least in terms of getting across the goals of the system. And this is supposed to be an acceptance test — making the goals of the system explicit is the whole point.

Okay, either you believe me at this point or you don’t. I suspect that some of you look at the step definitions and say “hey, I could string those seven lines of code together and call it a test all by itself”. Again, if that’s what works for you, fine. Any full-stack testing is probably better than no full-task setting. Try it once, though. For me.

Back to the step definitions, the last one uses the selector_for method — and I hope I’m using it right here because I haven’t gotten a chance to work with it yet, and the docs aren’t totally clear to me. The idea behind selector_for is to be analogous to the path_to method, but instead of being a big long case statement that turns a natural language phrase into a path, it’s a big long case statement that turns a natural language phrase into a CSS selector. The big lng case statement is in the support folder in a selectors.rb file. The with_scope method uses the same big case statement to narrow the statements inside the block to DOM elements within the snippet.

As with the paths, the idea is to take information that is implementation specific and likely to be duplicated and quarantine it into one particular location. As I said, I haven’t really incorporated this into my Cucumber routine yet, my first thought is that it’ll be nice to hide some of the complex CSS selectors I use in view testing, but I worry that the selectors.rb file will become a mess and that there’s less probability of duplicating a snippet.

I sure wish I had a rousing conclusion to reward you as this post nears the 1750 word mark. I like the direction that these changes are taking Cucumber, they are in line with what I’ve found to be the best use of the tool. Take a chance and try writing tests as implicitly as you can, as an exercise and see if it works for you.

Um, Hi? My book is out.

When I say that I’m really bad at self-marketing, one of the things that I mean is that I’ve left this blog basically dark for almost a month. This was an especially good idea because a) the TextMate post on Feb 10 became the most read post on this site ever by a factor of 5 over the previous three most popular posts (the PeepOpen review, the iaWriter review, and the thing about writing bad code, in case you care), and b) my book actually came out in print during this time.

So, obviously that’s a good time for complete radio silence. Sigh.

Book Thing

I should mention that there’s going to be a signing/event at Obtiva HQ on Tuesday, March 8th. We’re going to be giving away about 25 copies, and if there are more people than that, we’ll be selling copies at what I assume will be a discount of the cover price. There will also be food. If you are in the neighborhood stop by, because otherwise this will be depressing, and I’d really prefer it be fun.

PragPub

I have an article in this month’s PragPub about testing against web services. It’s 100% all-new material, none of it is in the book, and I kind of like it, even though I didn’t know about the vcr gem that works with webmock to automate creating good test data.

The Book is out

I have a half-written, somewhat indulgent post on Rails Test Prescriptions being out that might go up someday soon. In the meantime, the book is out, a physical object that you can hold, write in the margins, buy from Amazon, and so on.

People ask me how it’s selling, and I honestly don’t know how to answer, because I don’t really have any expectations — only a few technical books sell what you might think of as objectively a lot of copies. It’s sold far better than the Lulu version did, and it either has already or will soon outsell my Wrox book. (I literally have no idea how many copies the Wrox book sold because the only statement I saw was immediately after the book came out.) The people who have bought have said nice things, and that’s really the best part.

Coming Soon To A Hotel Conference Room Near You

I have a couple of upcoming conference and training appearances that I don’t think that I’ve mentioned on the blog before.

March 16, I’ll be in Salt Lake City for Training Day, the day before the official start of MountainWestRubyConf. I’ll be doing a full day of training, the morning will be on Improving Your Ruby Skills, and the afternoon will be Getting Started with TDD in a Legacy Environment. You can get more details, including location and pricing at the MWRC site. I’m super-excited about this, so if you are planning on being in the neighborhood, please sign up.

The full schedule isn’t online, but I’ll be speaking at Red Dirt RubyConf in Oklahoma City, April 21 and 22. This is a talk about Jasmine, and doing TDD in Javascript from Ruby. I’m hoping to show off a new tool for linking Rails and Jasmine. This looks like it’s going to be a great conference.

Also, Obtiva has updated their web site describing training courses that we’re offering. Sign up for classes or contact Obtiva for more information on scheduling or coaching opportunities.

Text And Mate

After a long time bouncing back and forth, I’ve come back to TextMate as my main editor. I realize that’s starting to sound almost old-school these days, but it still works the best for me.

What I’ve come to realize about TextMate versus, say, Vim, or RubyMine is that a) this is a genuinely personal decision and different people are just more comfortable with some tools than other and b) it comes down to what each tool makes easy and how useful that is.

For instance, RubyMine. RubyMine makes navigating a project super easy, which is great, since I do that all the time. It also makes refactoring easy, which is less useful because in practice I use the automated refactoring less. Vim makes manipulating text, if not easy, at least powerful, but again, I find myself doing that less. And the thing that Vim makes hard, having to keep track of modes, absolutely drives me crazy.

Anyway, TextMate. TextMate makes creating new snippets and triggers very easy, and doesn’t make anything particularly hard. That said, I have seen in some of my pairing around that a lot of Ruby developers don’t know about all the tools that give TextMate some of the features of RubyMine and Vim. So here are a dozen or so things that you can to to make TextMate work for you.

AckMate

Install the AckMate plugin. AckMate is a very fast project-wide text search with a nice interface. It’s about a gazillion times nicer than TextMate’s internal project search.

Ruby Amp

Install the ruby-amp bundle. Ruby-amp gives you a number of features. The one I use most often is a command-; shortcut for auto-completion against symbols in all open files. Very useful. You also get navigation to method, module, or class definitions with a keyboard shortcut.

Search Bundle Commands

Which reminds me, control-command-t is maybe the most important keyboard shortcut to learn, it gives you a pulldown menu of all bundle commands that you can fuzzy-text search. Changed how I work, and opened up a lot more of the power of the various bundles.

Zen Coding

Install the Zen Coding bundle. Zen Coding has a lot of features, but at core, it’s sort-of a meta-shortcut for outputting HTML or XML. So you type in something like div#highlight>ul>(li*3>p), press command-e and out comes fully formed HTML:

  <div id="highlight">
    <ul>
      <li>
        <p></p>
      </li>
      <li>
        <p></p>
      </li>
      <li>
        <p></p>
      </li>
    </ul>
  </div>
	

It’s wildly awesome anytime you have to write highly structured text, not just HTML, but also XML or DocBook or anything like it.

Column Selection

Holding down the option key when you select text, allows you to select text in a rectangle, what TextMate calls “column selection”. What can you do with this? Insert a prefix on a bunch of lines. Remove an entire column of a Cucumber table in one action. Remove the colon at the beginning of a list of symbols. And that’s just the stuff I did with it today…

Peep Open

PeepOpen costs a few bucks (technically $12), but it’s a somewhat cleaner version of TextMate’s file dialog, with slightly faster file search. The main downside is that it’s still kind of beta-y in that it occasionally hangs.

Make Snippets

Learn to create your own snippets. For example, I use the RSpec let command all the time. The RSpec bundle doesn’t have a snippet for let. Sob. Go to the bundle editor, select the RSpec bundle, choose create snippet from the bottom left, and put let(:$1) { $0 } in the text box. Set the tab completion to let, optionally set the scope to source.ruby.rspec and boom, good to go. (The dollar signs indicate places where the cursor goes when you press tab, in numerical order, but $0 is last. You can also set defaults if you want.) I’m skimming the surface here, but it’s super easy, and it would have been a real challenge to write RTP without defining custom snippets.

Commands

You can also create commands which run scripts, which can be written in the scripting language of your choice. Like, say, Ruby. You have access to the current file. Also very easy and very helpful. Here’s a dumb one I wrote that takes an HTML link in text and turns it into a Markdown self link. Again, you do this in the bundle editor:

#!/usr/bin/env ruby -w
input = STDIN.read
print "[#{input}](#{input})"

Assign that a key and a scope of text.html.markdown, and set the input to “Selected Text” and the output to “Replace Selected Text”

Here’s a slightly less dumb one that converts soft-wrapped text to hard wrapped text, indented to whatever level the first selected line is. I use this all the time when I write structured text. In

#!/usr/bin/env ruby -wKU

text = STDIN.read
initial_spaces = " " * ((text.size) - (text.lstrip.size))
text = text.strip.gsub(/\s+/, ' ') 

result = "#{initial_spaces}"

count = initial_spaces.size
text.split.each do |word|
  count += (word.size + 1)
  if count > 79
    result += "\n#{initial_spaces}" 
    count = word.size + initial_spaces.size + 1
  else
    result += " " unless result.size == initial_spaces.size
  end
  result += word
end

printf result

Scopes

Learn About Scopes. TextMate is based on the concept of scopes, which are defined by the language files in each bundle and determine what key commands and bundle items are active at any time. This is what lets TextMate syntax color multiple languages in the same file, it knows, for example, that the ERB &lt= marker makes the code enter Ruby scope so that Ruby syntax coloring and commands apply. control-shift-p at any place to show the scopes in play at that point in the text.

I learned about scopes from the TextMate book. It’s a few years old now, and I haven’t read it in a while, but it had a lot of good info on TextMate basics.

Random other Bundles

The default Cucumber bundle has a lot of useful stuff like goto step definition from feature, and so on. The git bundle has a useful visualization of git blame. The subtle gradient bundle has some useful grab bag stuff, including aligning ruby code.

Random other commands

Command-shift-v: paste previous contents of the clipboard

Control-t: transpose the two characters on either side of the cursor.

Command-shift-B: select enclosing brackets

Themes

Here’s a git repo with a jillion TextMate themes. Find one you like. Also, it’s easy to customize themes, especially once you get the hang of scopes and language definitions, since you can define text types in the bundle language definitions. See this article for more.

I hope that helps somebody. If you have a tip I don’t, leave it as a comment.

Book Review: Among Others by Jo Walton

Among Others is an evocative, subtle, and mostly brilliant fantasy novel on the themes of dealing with loss, growing up, learning to live, and how amazing the new Heinlein novel is. People who grew up inhaling SF and fantasy books are, by and large, going to recognize themselves pretty strongly. Not surprisingly then, many SF writers who have reviewed the book on line have raved. I’ll rave too, with some quibbles that we’ll get to in a bit.

It’s 1979, and Mori is a fifteen-year-old Welsh girl being sent to boarding school in England. We quickly learn that her twin sister died in a car accident about a year earlier, and that Mori has been given to the care of a father she hasn’t seen since she was a small child.

We also learn about the fairies. Turns out that Mori and her sister can see fairies across the Welsh countryside. And they can do magic. Mori’s sister was killed when the two of them effectively saved the world from their evil witch of a mother.

In the novel’s preface (five years earlier), we see Mori and her sister magically destroying a factory by dropping flowers in a pond (we never find out exactly why). They expect something flashy, and in fact believe they have failed, until the next day when they find out the factory has been closed.

Later, Mori explains how magic works, and it’s not like it does in books.

It’s like if you snapped your fingers and produced a rose but it was because someone on an areoplane had dropped a rose at just the right time for it to land in your hand. There was a real person and a real aeroplane and a real rose, but that doesn’t mean the reason you have the rose in your hand isn’t because you did the magic

[…] If it’s like books at all, it’s more like The Lathe of Heaven than anything. We thought the Phurnacite would crumble to ruins before our eyes when in fact the decisions to close it were taken in London weeks before, except they wouldn’t have been if we hadn’t dropped those flowers…It always works through things in the real world and it’s always deniable.

It’s hard for me to overstate how brilliant I think that paragraph is. It’s evocative, describes magic that is genuinely uncanny and weird, and also has a lot of depth in the way it affects the story. Plus it has an SF reference, like nearly everything else Mori does.

There are many things I loved about his novel. Mori reacts to her situation and its loneliness by reading a lot of SF and fantasy, which she namechecks, reviews, and comments on continually. This part is a lot of fun, especially if you’ve read most of the books, and it’s not a bad guide to future reading.

She’s smart, sensitive, and clearly trying to figure out how to go about living after you’ve saved the world among a group of people who don’t know and wouldn’t believe you anyway. Eventually Mori works some magic, then spends a lot of time wondering exactly how disruptive she’s been and the ethics thereof — there’s a lot of free-floating dread and eeriness because of the way magic works.

Walton deliberately subverts your expectation of plot in this book, not least by starting the book a year after the world-saving part, which is conventionally, you know, sort of the climax of these kinds of books. There are other cases, too, where we’re lead to believe that there might be some kind of conventional fantasy menace happening, only to have reality more or less take the air out of it. (That said, the ending, at least in terms of where Mori winds up, is quite satisfying.)

Ironically given that I’m writing this, I wish I had read fewer reviews of the book — I think it messed with my expectations a little (in particular, I expected things to be tied up more cleanly at the end). What you have is a very smart, somewhat nostalgic look at 1979 without a whole lot of conventional plot, and I think that your reaction to the book may depend on how willing you are to identify with the way in which Mori uses books. (In a weird way, the book reminded me of Almost Famous, in that they are about immersing yourself in a particular time and place to be a fan of something — the kid in the movie gets to live with his heroes, while Mori gets to actually live in a fantasy world. I’m way more interested in late 70s SF fandom, though, than mid 70s Rock Fandom.)

Much like Walton’s Lifelode (also highly recommended), at about the 1/3 way through this book, I realized that I wasn’t sure where the author was going, but I was enjoying the characters so much that I didn’t care. I still felt that way at the end, but wished there was just a little more meat to the narrative. Still, I loved this book, and if you looked to SF and fantasy as a teenager as a way to go to places that were amazing, you’ll probably love it too.

Rails Test Prescriptions is at the printer

I suppose I should get this on the blog…

Rails Test Prescriptions was sent to the printer yesterday, actually a couple of days ahead of the schedule that we’ve been on through the last stages of production.

Here are the dates, as I understand them…

  • The book is scheduled to leave the printer on Thursday, Feb 17, headed for bookstores and warehouses. I’d expect that you would probably see it in bookstores early the following week. If you’ve ordered via Amazon,
  • I believe the production version of the ebook will become available a couple of days earlier, on the 14th or 15th
  • I think that’s the same time that Pragmatic will take the book out of beta on the order page, meaning that you can buy the physical book by itself.

This has been a great experience. I know there are a few of you who have been waiting to order the book until it’s official debut — I hope you like it.

How I became a Haml-tonian

I mentioned on Twitter the other day that I was starting to like using Haml and it was surprising me because I used to dislike it so much. Colin Harris asked me to elaborate, but Twitter was too short, so here goes.

I assume that most people reading this have some idea of what Haml is, if you don’t, it’s an ERb replacement for view depleting which uses Python-style indentation for blocks, and a couple of other tricks for simplifying the amount of markup you need to write in your view — here’s a sample from the Haml tutorial, which gives you the flavor.

#profile
  .left.column
    #date= print_date
    #address= current_user.address
  .right.column
    #email= current_user.email
    #bio= current_user.bio

I don’t really intend to turn this into its own-mini tutorial, but suffice to say that “=” indicates Ruby execution, and the “.” and “#” allow you to specify CSS selectors, with a div tag being implied, and indentation indicating the extent of the outer tag.

So, how did I go from really hating Haml to mostly liking it? Well, here’s how I came to dislike it.

My first exposure to Haml in use came on a legacy project that I was asked to take over. The project seemed to have been worked on by two people who rarely spoke, as evidenced by, among other things, the fact that the view code was half ERb, half Haml. And the Haml seemed to be tied to some of the ugliest code in the system.

As a longtime Python programmer, I have no problem with using whitespace to mark blocks. In fact, I kind of like it. However, you have to acknowledge that the side-effect of whitespace blocks is to keep your blocks short, and try not to let them get too deep. That’s part of the point — the structure of the code is supposed to guide you to keeping the code concise and well factored. If you don’t pay attention, then the whitespace code — Python or Haml — becomes very hard to follow and maintain.

I’m sure you see where this is going. This first Haml project had long files, with deep nesting. It also, I realize now, wasn’t particularly good at using Haml’s strengths in specifying DOM elements. Every time I needed to touch that code it was a bad experience, and I got very averse to seeing Haml.

I also had a couple of other issues. Among my coding quirks, I tend to be aggressive about keeping line lengths under 80-90, and Haml 2.x didn’t allow you to insert line breaks in executing Ruby code, which led to unavoidably long lines in some cases. (I realize that the point was to keep you from having long Ruby calls, but sometimes, especially in that code base, it was unavoidable.) To a much lesser extent, I was also not attracted to the “If you don’t like Haml you have no poetry in your soul” tone of the Haml website. I’ve come to terms with that, too.

So what happened?

A couple of things. Haml 3.0 made it possible to break lines in Ruby code, and that was enough to get me to look at Haml again. The addition of SCSS over SASS for writing CSS helped a lot — I love SCSS and never really got into the SASS syntax. I started working on projects that used Haml and were smarter about using CSS, making the Haml’s easy creation of complex CSS selectors more attractive. I saw better examples of Haml code that showed it in a better light.

And one day, working on a totally different project that also happened to be half Haml, half ERb, I noticed that the ERb started to fell clunky and heavyweight. The Haml started to feel disturbingly natural.

I started to prefer Haml, using it as the default on new projects.

What do I like about it?

  • It’s concise, but after you get used to it, completely readable (again, when written well). It did take me a little while to get used to it.
  • Haml makes it much more difficult to write invalid markup, effectively eliminating a source of error
  • Haml encourages treating markup like code and writing it in small pieces
  • Haml implies the use of SCSS, which is pretty unambiguously awesome.
  • As Brian Hogan pointed out on Twitter, Haml makes it easier to restructure the hierarchy of your view output because it’s much easier to change the relative placement of tags.

It’s not perfect. Like all HTML tools that assume an HTML structure, unstructured text is challenging. Ruby blocks still look strange without endings. Other than that, I’m happy making Haml my default view layer. And I’m glad I got over it enough to give it another look

Quick Rails Test Prescriptions Update

It’s been quiet on the Rails Test Prescription front. Those of you on the beta program should have gotten Beta 11 earlier this week. There are no major changes in this beta, but it does contain the final copyedit, a pass through the errata, and a couple of late-breaking reviewer comments.

At the moment, the book is being typeset, which means that non-typesetter changes to the source files are definitely contraindicated.

My understanding, which is guaranteed to be somewhat incorrect, is that the typesetter will be done early next week. At that point, we’ll have a couple of days to make sure everything looks okay, and then it’ll actually go to the printer. Once it goes to the printer, I think it will go out of beta for the purposes of buying the book. I expect to have more concrete dates once it’s actually at the printer.

I’m not saying I’m excited about this finally being a physical book, but my first commit to the original, self-published repo was November 7th, 2008.