There's a bunch of articles that helpfully diagnose and solve the GRRRRowl + autotest + Leopard snafu.

In order to save me, and my cohorts, some time I've bundled it all up in a README + script + icons.

Being a new father, currently at my in-laws, I've reached for the nearest toy, and made bob the builder icons. I think they might even challenge hookercookerman's set (sadly, not on the web as afar as I can see - step up hookercookerman and post them).

Grab it

here (tarball, installation instructions inside)

P.S.

I made the screenshots with Photo booth's 'backdrop' feature, and a real toy. Finally, I can do composites (I just knew not learning photoshop would pay off).

So you're using ssh keys for all your servers and github and whatnot, and you've been using SSHKeychain in OS X 10.4, to manage that, and not type your password in all the time (SSHKeychain is a gui for ssh-agent).

Now that you're on Leopard, this all Just Works. No need for SSHKeychain (although SSHKeychain does other things too), and everything is nicely integrated with Mac OS keychain services. There's a nice write up over here at Ormset i Noreg. Buried in the comments, Luke Redpath notes that macports users might not be seeing this coolness, as OpenSSL is a dependency of some common ports (like git), and so the macport's ssh is not compiled with the leopard funkiness.

To fix this (assuming a standard macports install):

  sudo mv /opt/local/bin/ssh /opt/local/bin/ssh-macports
  sudo mv /opt/local/bin/scp /opt/local/bin/scp-macports

Now, when you next push to github, or deploy to a server, you'll get something like this:

Hooray!

git hosting with Leopard

May 19th, 2008

So you wanna host your own git repos? Got Leopard? Got Git? Read On...

Assumptions: You have git installed.


Create a git server on leopard with gitosis

Download and install gitosis

  mkdir src
  git clone git://eagain.net/gitosis.git
  cd gitosis
  sudo python setup.py install

Create a git user and group on the server

Create a unix user and group for git, using dscl: leopard's directory service cli

1. Find an unused uid and gid

  sudo dscl . list /Users uid
  sudo dscl . list groups gid

(check that, say, 401, is unused in both)

2. Create the git group

  sudo dscl . create groups/git
  sudo dscl . create groups/git gid 401

3. Create the git user

  sudo dscl . create users/git
  sudo dscl . create users/git uid 401
  sudo dscl . create users/git NFSHomeDirectory /Users/git
  sudo dscl . create users/git gid 401
  sudo dscl . create users/git UserShell /bin/bash
  sudo dscl . create users/git Password '*'

4. Create the git home directory (make this location match the end of line 3 above)

  sudo mkdir /Users/git
  sudo chown git /Users/git
  sudo chgrp git /Users/git

Create an ssh key, and copy it to the server

1. If you don't already have one, create an ssh key, on your local machine if it is not the server

  ssh-keygen -t rsa

2. Copy the public key to /tmp on the server

(if your local machine is the server)

  cp ~/.ssh/id_rsa.pub /tmp/my_key.pub

(if the server is different from your local machine)

  scp ~/.ssh/id_rsa.pub your.server.com:/tmp/my_key.pub

Setup gitosis in git user's home directory

1. Initialise gitosis [on the git server]

  sudo -H -u git gitosis-init < /tmp/my_key.pub
(you should see something like this:)
  Initialized empty Git repository in ./
  Reinitialized existing Git repository in ./

2. Make sure git's paths are set to your current ones (where you can see gitosis and git)

  sudo su git  (enter your password)
  echo "export PATH=$PATH" > ~/.bashrc
  exit

Clone the gitosis repo to your local machine

  git clone git@your.server.com:gitosis-admin.git

If you see something like this, then you're all set

  remote: Counting objects: 5, done.
  remote: Compressing objects: 100% (4/4), done.
  remote: Total 5 (delta 0), reused 5 (delta 0)
  Receiving objects: 100% (5/5), done.

What next?

Get familiar with gitosis. scie.nti.st has a great writeup for *nix systems, which I used as a reference point. The end of that blog has some general intro to gitosis.

Troubles? Make sure that you can ssh to the server as git (make sure that Leopard's ssh settings allow any user to login, or edit /etc/sshd_config). Otherwise post your troubles here in the comments.

I don’t know how I missed this (well, I do, I've been ridiculously busy), but about a month ago Microsoft issued a statement about planned CSS standards support in the upcoming IE8. The good news is that CSS 2.1 support will be almost complete—good, but not great, considering that this standard is rather old now, as it’s been a “candidate recommendation since 2004”.

The bad news is the level of support for CSS3 elements. Look through that list & try to keep afloat in the sea of red “no”s that signify their CSS3 support—or lack thereof. Of course, CSS3 is still very much a work in progress and is unlikely to be a candidate recommendation for another decade, judging from the pace of “Last Calls” for various components of the CSS3 spec. Nevertheless, the developers behind Safari & Firefox have been implementing a lot of the spec. There’s some fantastic stuff in it (multi-column support! colours with opacity!), that I for one would like to use immediately—and which we do, on our own site & some others we’re currently developing. But for the foreseeable future, if you’re using IE, you won’t see these things.

Given the clusterfuck of discontent that was IE7, and that Safari & Firefox have cleaned their clocks with current & emerging standards support, one might think that Microsoft would take the opportunity to really push IE8 to be a 1st-class browser. But no, they’ve just decided to tread so softly, so slowly, that the net result will be that IE8 will be that much farther in the distance. I mean, IE8b has just passed the Acid2 test. Hooray. Safari & Opera have worked on complete compliance with Acid3—and have succeeded.

This sucks. There are fantastic things taking place in CSS, in particular CSS3—which you can experience right now in Firefox & especially Safari. And I’d like all my site’s viewers to be able to see these effects in action.

Congratulations to Ian!

May 7th, 2008

As of last night, Ian became a father! At around 11pm, his son was born. Let me be the first in a public forum to congratulate him :)

Hopefully, he’ll soon post pictures—and a name!

Many of our plugins are now available on github: github.com/ianwhite

And OSS projects such as these can now be hosted free on lighthouse: ianwhite.lighthouseapp.com

The ones that you see on lighthouse have all had a good dusting off to make sure they're compliant with the very latest edge, and BC to 2.0.2. response_for is now branched to support edge and 2.0.2, but the other plugins haven't yet required this.

If you don't see one you use there, it means that I haven't deemed it being used by many people - so leave a comment to say otherwise

resources_controller: things

April 27th, 2008

RC's got a github home now

The subversion repo will still continue to be maintained for the foreseeable future.

RC's also reported as being one of the things under the hood at naked.

Lastly, I've been cooking my CI with garlic.

Two CSS Debugging Tips

April 25th, 2008

Ian may claim to be doing nothing but git-work (and what an unfortunate name that is), but the fact of the matter is that we’re both eyebrow-deep in client work. This business has been running since April 1999 & we’ve never been so busy.

When you’re so busy, the last thing you want is a series of bugs that won’t seem to go away. Since most of my work is in the HTML/CSS/Rails templates realm, I’m speaking mostly of visual bugs, things that seemingly won’t budge no matter how much time you put into them. I thought I’d share two tips which have helped me squash a considerable number of visual bugs, one created by someone else & the other merely a process that I follow.

CSS Debugging Tip 1: Burn it all to the ground

First, the work supplied by someone else: Eric Meyer’s CSS Reset. If you’re unfamiliar with it, go & read up on it ASAP. For those unfamiliar with why you’d need to reset something your CSS, the answer is simple: different browsers have different default sizes for fonts, lists, buttons & a hell of a lot else. By resetting all these items via CSS, you help ensure that all your browsers—Safari, Firefox, Opera & the thorniest of them all, Internet Explorer—start from a common vantage point.

The idea is not new. For years I’ve employed a very basic, simple reset:

  html * { margin: 0; padding: 0; }

The problem is that this didn’t reset nearly enough things—and it often didn’t even reset everything it was supposed to! Eric’s reset is a total razing to the ground of all browser-specific sizing quirks & as such should be adopted by every designer. In my experience, it’s particularly useful for a project that you’re just starting up: my IE-specific stylesheets are a fraction of their former size. For pre-existing sites, however, it’s not going to be a magic bullet. You still assembled your CSS based on different assumptions & short of starting from scratch, it will be of more limited use (although still recommended in my book).

CSS Debugging Tip 2: Build it back up brick by brick

The second tip is merely a process that I’ve been following. I’m surely not the first person to do this, but since it doesn’t appear to be widely discussed I thought I’d write it up here.

I’m going to take a real-world example from a site we’re building. In this site, we’re using some Scriptaculous effects to aid in the creation of a visually compact secondary navigation for a database of imagery. The markup is simple:

    <h4>Section Heading</h4>
    <a href="subsection/1">Subsection 1</a>
    <a href="subsection/2">Subsection 2</a>
    ...

Clicking on the H4 tag will cause the subnavigation links to reveal themselves, or hide themselves if they’re already revealed.

Unless you’re viewing in Internet Explorer 7, that is—no, the problem for once isn’t IE6! In IE7, the links were invisible—they were clickable, but you couldn’t see them.

I tore out what little hair I had left, for weeks, trying to figure out this bug. I even thought it might have been Scriptaculous’ fault. It wasn’t, however & eventually I realised I was compounding the problem by adding CSS declarations instead of removing them—instead of trying to figure out what was triggering the bug, I was trying to pave over the bug. If you’re adding more declarations in order to fix a bug, you may very well be creating a shifting target, which is definitely not what you want to be doing. Particularly when you have a lot of other work to do.

The answer is just a process & a very simple one at that: take your CSS declarations & strip them out. Add them incrementally, viewing in the target browser every time, until you trigger the bug.

In the example above, removing a declaration of a:link { display: block; } rendered the links visible again in IE7. I don’t know why—I’ve used this declaration countless times with no problems—but nevertheless the declaration wasn’t necessary & it was causing a big problem.

Again, though, it’s the process of stripping away your CSS & then re-implementing your declarations which is the key. It’s all too easy to add more & more to your declarations, but remember: you may only be making the job of fixing your problems worse.

So I've been curled up in a ball, riding the git avalanche, trying to sort out my rails plugins - making sure they're getting tested against the latest and greatest.

Inspired by this ticket for rspec, git's coolness, some menthol snuff, and a lot of coffee, I came up with garlic.

It's an extremely lightweight set of rake tasks that let you test your plugins or app against various version of rails, and other dependencies.

If you want to see it in action (on one of my plugins), do this:

  git clone git://github.com/ianwhite/inherit_views
  cd inherit_views
  rake cruise

Sit back, watch it download all the dependencies, then create rails apps for each set, and run the rcov task for the plugin in each one... (the download only happens the first time you do it).

You configure it using a little dsl, like this:

garlic do
  # default paths are 'garlic/work', and 'garlic/repos'
  work_path "tmp/work"
  repo_path "tmp/repos"
  
  # repo, give a url, specify :local to use a local repo (faster
  # and will still update from the origin url)
  repo 'rails', :url => 'git://github.com/rails/rails' #, :local => "~/dev/vendor/rails"
  repo 'rspec', :url => 'git://github.com/dchelimsky/rspec'
  repo 'rspec-rails', :url => 'git://github.com/ianwhite/rspec-rails'
  repo 'inherit_views', :url => '.'
  
  # for target, default repo is 'rails', default branch is 'master'
  target 'edge'
  target '2.0-stable', :branch => 'origin/2-0-stable'
  target '2.0.2', :tag => 'v2.0.2'
  
  all_targets do
    prepare do
      plugin 'rspec'
      plugin 'rspec-rails', :branch => 'origin/aliased-render-partial' do
        sh "script/generate rspec -f"
      end
      plugin 'inherit_views'
    end
    
    run do
      cd "vendor/plugins/inherit_views" do
        sh "rake spec:rcov:verify"
      end
    end
  end
end

Notice that I'm using my fork of rpsec-rails, and the plugin specifies that it should use a particular branch 'aliased-render-partial'. The reason for this is that I have some outstanding tickets on rspec, which haven't been resolved. In the meantime, I can just use my patched version. If the patch gets accepted, I can just change the url, and garlic will inform me that I need to remove and run rake garlic:install_repos to get the new one. This is just making use of the awesomely cool coolness of git.

Also notice the block passed to the 'rspec-rails' plugin. This will be executed inside the rails target after the plugin has been installed. Finally the run block says what should happen for the actual CI. In this case cding into the plugin and running an rcov task.

It's new stuff

So it probably has bugs and stuff.

Neocon Clone Math!

March 18th, 2008

Special Neoconservative Incompetence Cloning edition!

Dick Cheney

Soulless, chillingly evil US Veep Dick Cheney +

Donald Rumsfeld

Formerly (and mysteriously) popular war criminal US Sec’y of Defense Donald Rumsfeld,

-( (hair/2) + (war criminality) ) * ( (avg. human sympathy)/10 ) =

Hank Paulson

Totally on-the-ball Sec’y of the Treasury Hank Paulson?

Fucking hell, where do they get these people? Aside from a petri dish, that is.

HP Total GoatseCare

February 28th, 2008

So I was reading an article this afternoon & noticed the HP advertisement that appeared right next to it:

OMG it's HP Total GoatseCare!

And I kept thinking, that’s so familiar…

dynamic resolution + prototype

February 27th, 2008

You may have heard of the Dynamic CSS resolution switcher from Particletree, it's a neat bit of js that allows you to specify different css files depending on the browser resolution.

We love this script, but we had problems running it with Safari, and we are using prototype, so we wanted to make use of its goodness for the browser independent stuff.

So, if you're already using prototype, the following script achieves the same effect as the original particletree script. It also uses the dom:ready event, which fires after the dom is loaded, but before the screen is drawn, so you shouldn't see any 'twitch'.

Example

In the following example, we have three stylesheets that correspond to browser widths as follows:

  thin      up to 1020
  wide     1021...1400
  widest    above 1400

For non js users we want to default to 'wide' (the middle one). In order for this to work properly, we disable all of the non-default stylesheet links.

In your html

In your html you need to link to the three stylesheets, give them each a title attribute, and disable the ones you don't want non-js users to see.

  <link title="wide" href="/stylesheets/wide.css" rel="stylesheet" type="text/css" />
  <link title="thin" disabled="true" href="/stylesheets/thin.css" rel="stylesheet"  type="text/css" />
  <link title="widest" disabled="true" href="/stylesheets/widest.css" rel="stylesheet" type="text/css" />

And link to the script, we'll call it dynamic_css.js

  <script src="/javascripts/dynamic_css.js" type="text/javascript"></script>

The script

This is the script, it uses the title attribute of the stylesheets to disable or enable them. It is run when the dom is ready, and when the browser width changes.

// DYNAMIC RESOLUTION SWITCHER
// Originally from ParticleTree
// Simplified with Prototype by Ian White of Argument from Design 2008
// include prototype.js (>=1.6) before this file

// you need to edit this function as per your situation
function applyDynamicLayout() {
  var width = document.viewport.getWidth();
  if (width <= 1020 )                 { applyStylesheet("thin") }
  if (width > 1020 && width <= 1400)  { applyStylesheet("wide") }
  if (width > 1400)                   { applyStylesheet("widest") }
}

// you shouldn't need to edit past here
function applyStylesheet(title) {
  var i, stylesheet;
  for(i=0; (stylesheet = document.getElementsByTagName("link")[i]); i++) {
    // is it a stylesheet with a title attribute?
    if(stylesheet.getAttribute("rel").indexOf("style") != -1 && stylesheet.getAttribute("title")) {
      stylesheet.disabled = true;
      if (stylesheet.getAttribute("title") == title) {
        stylesheet.disabled = false;
      }
    }
  }
}

//Run applyDynamicLayout function when window is ready and when it resizes.
Event.observe(document, 'dom:ready', applyDynamicLayout);
Event.observe(window, 'resize', applyDynamicLayout);

That's it!

That's it, it works for us in Safari, Opera, FF and IE 6 or greater.

Also, you can have as many stylesheet links as you like with the same title. For example, let's say you have some IE6 specific kludges for the 'thin' layout. You would do this:

<!--[if lt IE 7]>
  <link title="thin" disabled="true" href="/stylesheets/thinie6.css" rel="stylesheet" type="text/css" />
<![endif]-->

resources_controller new trunk

February 26th, 2008

There's going to be some new features coming in resources_controller. Stay tuned...

Meanwhile, rc has got a new repository location (the old one will still work for a while, but will remain at the current version):

trunk: http://svn.ardes.com/resources_controller/trunk/resources_controller

tag 0.5: http://svn.ardes.com/resources_controller/tags/0.5/resources_controller

For those interested in providing patches, you should checkout http://svn.ardes.com/resources_controller/trunk and run rake pre_commit in that directory to check your changes. Then send a diff along, or post it on the google group.

Ruby muckin

February 12th, 2008

So I was writing a Rakefile and found myself doing stuff like this:

  cmd = "svn co #{src} #{dest}"
  puts cmd
  system cmd

Everytime I wrote lines like this, a little corner of my heart died.

I dreamt of something like this:

  "svn co #{src} #{dest}".to :puts, :system

But it's hard to do this properly, because you need to get hold of the receiver (in the above case main, or some Rake task) or binding, so that the methods can be sent where they ought. With crippled Kernel#caller, the the demise of Binding.of_caller (Ruby-debug solved the problem but there's significant overhead) it was looking like I should just wait for the next ruby release.

But I frowned like Hiro and came up with this:

  pass("svn co #{src} #{dest}").to :puts, :system

Briefly, Object gets #pass which creates a PassProxy (basic object). It keeps hold of the receiver, but acts like the object (in this case the string). When you send #to(:method) to this PassProxy, it calls the original receiver with the object.

This is just sugar, but its nice sugar in some cases. Compare:

   # plain ruby
   msg = "oooh!"
   MyObj.foo msg
   MyObj.far msg
   MyObj.faz msg
   msg
   # => 'oooh!'
   

   # returning (ActiveSupport)
   returning "oooh!" do |s|
     MyObj.foo s
     MyObj.far s
     MyObj.faz s
   end
   # => 'oooh!'

   # (pass) (this code)
   MyObj.pass("oooh!").to :foo, :far, :faz
   # => 'oooh!'

But eat too much sugar and your teeth will fall out: I realised that this probably has limited usefulness (how often do you need to send the same object to a bunch of different methods?). But at least I learned some things in that last couple of hours of coding.

Go get the code from pastie if you're interested.

Thanks for reading

A great start to 24 Ways 2007

December 1st, 2007

Since 2005, 24 Ways has been a great collection of web design tips & tricks in an “advent” format (i.e., one article per day in December before Christmas). This year already looks like it’s going to be a great one. Drew McLellan has a great opening article on dealing with transparent PNGs in Internet Explorer 6 & 5.5 (yes, many of us do have to factor in those old browsers in our designs).

This comes at a great time: currently we’re working on a site that uses 24-bit PNGs with alpha transparency, and as Drew says, the common solutions to the issue don’t help you when you want to use that type of PNG as a background image. He also mentions that it’s a big problem to use such PNGs behind a form—because of the way IE6 & earlier deals with the PNGs. IE effectively puts another layer on top of the area you’re looking at—meaning that form inputs are completely inaccessible. This is a problem not simply for forms, but indeed potentially for any design where you’re playing with positioning. For example, we’ve got an organisation’s logo dipping slightly below a masthead, spilling onto the crumbs bar below. Any links that happen to be in that PNG’s area were completely inaccessible, too. Our solution was to set z-index for both the #masthead img & #crumbs. Drew’s solution is better, however—it’s far more set & forget.