Bruce Williams

10 September 2010

Rails IE Conditional Tag Plugin

There are a number of ways to support defining different CSS styles for specific versions of Internet Explorer:

  1. Known CSS Hacks (ie, tricking the parser’s tiny brain with strange incantations)
  2. Using IE-specific conditional comments around link tags to additional stylesheets
  3. Applying version-specific CSS classes to help differentiate them, using conditional comments

I agree with Thomas Fuchs about the right choice between the first two — the addition of a new stylesheet that needs to be retrieved is silly… but I think CSS hacks are at least as ugly as IE conditional comments (regardless of how “known” they are, they are still arcane hacks that need to be applied in a specific order and require careful documentation/commenting wherever they’re used — a bad sign). HTML is no more sacrosanct than CSS when it comes to ugliness.

The third option that I mentioned is explained in detail by Paul Irish (make sure to read the more recent updates), but in short it involves the addition of CSS classes to the html tag, which are then easily used in your stylesheet. This is accomplished using IE-specific conditional comments — which, while admittedly ugly, are at least self-documenting. The technique involves repeating the html tag multiple times, all but one within HTML comments (which IE parses) — IE selects the right one to use for its version, and other browsers use the exposed, normal, tag.

Here’s an example:

<!--[if lt IE 7]><html class="ie6"><![endif]-->
<!--[if IE 7]>   <html class="ie7"><![endif]-->
<!--[if IE 8]>   <html class="ie8"><![endif]-->
<!--[if IE 9]>   <html class="ie9"><![endif]-->
<!--[if (gt IE 9)|!(IE)]><!--><html><!--<![endif]-->
 (... the rest of the HTML document...)

Ugly as sin, right? I agree — but that’s a few contained ugly lines in one place vs a sprinkling of CSS hacks in your stylesheet (that, again, need to be commented in detail).

Now, I don’t want to have to type that (or remember it, frankly), and neither am I a huge fan of carting around boilerplate with me from project-to-project — so along with Anthony Burns, I put together ie_conditional_tag, a Rails plugin that adds a simple helper, ie_conditional_tag.

The above code example could simply be:

<%= ie_conditional_tag :html %>

You can add other, dynamic classes if you’re so inclined (though you’d normally do that on the body), and they will be included in all the generated tags.

One nice additional feature is that the plugin supports customizable mappings of conditions to applied attributes, so you can tag versions matching more complex terms — or IE 6 as that-piece-of-crap-that-wont-die, as it should be.

Just add ie_conditional_tag to your Gemfile, and:

$ bundle install
$ rake ie_conditional_tag:install

Check out the documentation for more details.

It may be worth noting, by the way, that I’m far more interested in progressive enhancement and graceful degradation (and I give clients salient feedback along those lines to help them make better decisions about where to spend their money/time) — but when the [unassailable] need arises, this is an approach I support.

12 July 2010

Riak: A friendly key/value store for the web

A few days ago I had the opportunity to speak at DevNation Portland on Riak — a fun NoSQL system I’ve become interested in lately. Here are my slides from the talk.

Note: For some reason both Scribd and Slideshare tend to mangle vector graphics imported into Keynote. You can a download “prettier” PDF version here. (I’m told it looks pretty nice in iBooks.)

Thanks again to Viget Labs and Relevance for putting together the event; I had a great time, learned a lot, and met some great local developers.

27 June 2010

Speaking at DevNation Portland

Just a quick note — a rare spike of activity in my [sadly] dwindling ability to write anything on my blog…

I’ll be speaking at DevNation Portland on July 10th, covering a technology I’ve become interested in lately: Riak. Riak is a robust and friendly key/value store for the web, built on top of Erlang (with a bit of C and Javascript thrown in). I’ll focus primarily on the concepts at play in Riak, where/how it can fit into an application, and where it might be headed in The Future. It will be a talk light on benchmarks, heavy on code.

I hope you’ll join me there; there are still seats available at the event, and I’d love to meet more Portland developers (me being a fairly new transplant). Not from Portland? Now’s a great time to visit; the weather is absolutely gorgeous this time of year.

5 May 2010

A bandaid for Rcov on Ruby 1.9

If you’re running into issues with this encoding-related error using RCov 0.9.8 & Ruby 1.9.X:

in `block in is_code?':
invalid byte sequence in US-ASCII (ArgumentError)

Here’s a quick monkey patch to drop into your test helper or Rakefile until a fix is released:

if defined?(Rcov)
  class Rcov::CodeCoverageAnalyzer
    def update_script_lines__
      if '1.9'.respond_to?(:force_encoding)
        SCRIPT_LINES__.each do |k,v|
          v.each { |src| src.force_encoding('utf-8') }
        end
      end
      @script_lines__ = @script_lines__.merge(SCRIPT_LINES__)
    end
  end
end

Credit: Commenters on the related bug.

22 April 2010

Checking Executables with Spex

If you’ve ever built (or configured) tools for system administration, you know the frustration of not being able to easily verify the effects of running those tools in real-world situations. Executables are little black boxes that can have far-ranging effects on systems that are hard to track down, validate, and even harder to check across multiple executions.

Spex is a simple, extensible Ruby domain specific language that can be used to describe scenarios where executables are run and checks are performed before and after.

Some possible uses:

A simple example

For instance, if I wanted to test that a configuration management system successfully added an entry to /etc/passwd the first time, but in subsequent runs did not modify the file, here’s how I could do it (using Puppet in this example):

scenario "Running Puppet on manifest.pp" do
  executing 'puppet manifest.pp' do
    check '/etc/passwd', :modified => {:added => 'bruce'}
  end
  # Running it again
  executing 'puppet manifest.pp' do
    check '/etc/password', :modified => false
  end
end

Running the scenario is as easy as running:

$ spex path/to/scenario.rb

And the output may look like (with prettier colors):

Running scenario "Creates a file"
Preparing to execute "puppet manifest.pp"
Pre-checks for file modification of /etc/passwd: PASSED
Executing "puppet manifest.pp": DONE (2.08s)
Post-checks for file modification of /etc/passwd: PASSED
Preparing to execute "puppet manifest.pp"
Pre-checks for file modification of /etc/passwd: PASSED
Executing "puppet manifest.pp": DONE (1.25s)
Post-checks for file modification of /etc/passwd: PASSED
SCENARIO PASSED

Checks

The list of available checks is growing, and currently includes:

Checks I’d like to add include querying package management system changes and filesystems/mounts. A list is being built.

Want to build your own custom checks in the meantime? Spex is extensible; merely drop custom checks in ~/.spex/checks/ and they’re available from scenarios.

Checks are easy to build; they’re simple classes that implement before and after methods that utilize normal test/unit assertions.

To see the list of available checks, use the --checks option:

$ spex --checks

You’ll get the full listing of checks, with examples.

Once you know some, it’s easy to dive in. Here we’re checking that the postfix command on OSX behaves as advertised:

scenario "Postfix process management" do
  executing "sudo postfix start" do
    check 'postfix/master', :started => true
  end
  executing "sudo postfix stop" do
    check 'postfix/master', :stopped => true
  end
  executing "sudo postfix start" do
    check 'postfix/master', :started => true
  end
  executing "sudo postfix stop && sudo postfix start" do
    check 'postfix/master', :restarted => true
  end
end

Installing it

Spex is available from github and as a gem:

$ gem install spex

You’ll get the colored, diff-lcs, and facter gems along for the ride.

Caveat utilitor

Remember; Spex calls real executables that do real things to your system. There’s no sandbox, no chroot (unless you do that yourself), no child-proof electric plug covers. Be careful not to zap yourself.

Spex is definitely in its infancy. I’d love to hear feedback (with bugs and features as issues).

It’s been a useful tool for my purposes, and I hope others find it helpful as well. If you give it a spin, let me know!

11 April 2010

RSpecfully, I disagree

RSpec has a very, very strong following in the Ruby community, and for a lot of good reasons. It’s fairly easy to use once you grok it, it’s a DSL (thereby marking off that most important of checkboxes — “expressiveness” — we Rubyists do like our blocks), and its popularity has played an important role in building the Ruby testing culture. Bully for RSpec!

All this being said, though… in my own projects (and whenever I can convince others), I use something else.

It’s too big and complex

At over five thousand lines of Ruby (just in lib/), it’s often much larger than the software that’s being tested. Although this is small potatoes in comparison to Rails, keep in mind it only has one job: to check if something does something. This size makes RSpec quite a bit slower than other testing frameworks, and a lot harder to learn in its entirety (especially if you want to extend it).

It’s a bad DSL

RSpec is a bad example of a domain specific language — partially because it is so unspecific (describe, context, and worst of all, it) — and partially because its attempt to mimic a natural language feels so forced. I’ve lost count of the number of times I’ve seen people confuse a space, period, or underscore placement when writing RSpec (“ah, it’s dot should, then space, then be, and then an.. underscore?). At some point writing code in a literate style crosses the line into confusion — ever used Applescript?

It’s hard to scan

It structures each assertion subject first, followed by the desired value/behavior. Since the subject is usually the same, to scan a series of specs to see what’s being checked, you’re forced to scan the jagged right hand side. In my opinion, plain old test/unit assertions provide superior readability by avoiding a sentence structure and putting the desired behavior first.

Yes, I know you can use Shoulda assertions from RSpec — the fact that’s becoming a popular choice is telling. I don’t buy that it’s just for Shoulda’s Rails goodness.

What’s a Rubyist to do?

f you like RSpec, use it. That you test is far more important than the framework with which you test — and this article is just my opinion. I’m sure a large number of people will tell me I’m crazy, that RSpec is the right tool for the job — and for those people that will be completely correct.

Use the tool that works for you — few things are more personal to a developer than his/her testing framework choice.

Try out smaller frameworks. There are a lot of them out there; some of them simpler versions of RSpec, and some of them completely different in form and approach.

As for me, I’ll use Shoulda — right up to the point something else catches my fancy.

What do you like to use for testing?

Before you comment

Yes, I have used RSpec extensively (at least two years cumulatively, and very recently). I’ve extended it quite a bit, used its matchers in conjunction with Cucumber and other tools, and integrated it in Rails and plain Ruby projects.

I have a huge amount of respect for the people that built and contribute to RSpec, all of whom I consider smart — and some of whom I count as friends.<

4 April 2010

Constrain Yourself

I’ve been traveling a lot lately. After wrapping up two very successful weeks in the U.K. — a fun trip to Edinburgh, where I spoke at the Scottish Ruby Conference (previously “Scotland on Rails”), and a week in London, where I taught a course for Puppet Labs — there was little I wanted to do but get home. I enjoy traveling (especially to the U.K., where I spent some of my formative years), but after a while living out of a bag gets a little old.

Midway through the day-long ordeal that was my trip back to my home in Portland, I had a glimmer of enjoyment, reading American Way Magazine — after hours on my laptop (until it died), hours on my phone (until it nearly died), and hours on my Kindle (finishing a book), I fell on the airline magazine with what can only be considered desperate boredom, to read the following gem on Zach Rogue’s injury and how it changed the way he approached music:

Rogue worked through the pain, pouring his emotions into the lightest instrument he could hold, a Sears Silvertone guitar. The experience had a profound impact not only on the material for the album that would become Permalight but also on his guitar playing as a whole. “I was actually playing in a different way,” Rogue says. “That way made me approach things differently in terms of composition, so it actually had its benefits. I remember thinking, ‘Okay, well, you can’t play regular stuff right now so don’t think of it like that; just think of it in terms of movement. Think of what chords sound like in a percussive kind of way.’ So I remember just trying to play really, really rhythmically, almost like dance music — music your body can kind of sway to, more than just emotions in your mind.

This jives with what I’ve heard from a lot of creative people — software developers, musicians, and other artists. Constraints are important, they are empowering, and they can completely reinvigorate the creative process.

In some ways, adding a constraint to a project is about changing the rules of the game — the working parameters of the problem. It can both complicate and simplify the solution, adding new avenues of thought and completely cutting off others.

We all find ourselves using tired, trite approaches — grabbing that same old hammer, even when today’s problem is a screw. Sometimes a constraint forces us to put down the hammer and look for a new, exciting tool we wouldn’t have experienced otherwise. It’s a shame we usually see constraints as external stressors instead of part of a self-enforced creative process.