Syndication IconNew article alerts are available via Atom. Hide this message

Make sure you're @importing files that exist

A few people near me have heard the start of my rumblings about optimising the number of HTTP requests required for each page. There are a variety of reasons that you might want to do this, but that discussion is for another post. For now simply assume that I don't like unnecessary HTTP requests. Extrapolating from that you would reasonably assume that I really don't like wasted HTTP requests such as might happen when the url in a CSS @import directive 404's. If you assumed that, you'd be right.

I got fed up of tracking down the source of these errors in a few applications that I maintain so I fired up a TextMate session and scraped together this nasty little snippet of Ruby to do my dirty work for me.

#! /usr/bin/env ruby

css_root = File.expand_path(`pwd`.strip)
css_files = Dir[File.join(css_root, "**", "*.css")]

missing_imports = Hash.new([])
css_files.each_with_index do |css_file, index|
  imports = File.read(css_file).split(/\n|\r/).grep(/\@import url\((.*)\)/)
  imports.each do |import|
    desired_path = import.scan(/url\((["'\ ])?(.*)\1\)/).to_a.first.to_a.last
    desired_root = desired_path[0,1] == "/" ? css_root : File.dirname(css_file)
    filesystem_path = File.expand_path(File.join(desired_root, desired_path))
    if !File.exists?(filesystem_path)
      missing_imports[css_file] += [{ :path => filesystem_path, :directive => import }]
    end
  end
end

if missing_imports.any?
  puts "Missing files declared as imports in CSS:\n\n"

  missing_imports.keys.each do |origin|
    puts "Origin:               #{origin}"
    missing_imports[origin].each do |import|
      puts "Missing @import file: #{import[:path]}"
      puts "Directive:            #{import[:directive]}"
    end
    puts ""
  end
else
  puts "No imported files are missing. Well done."
end

Run it in the directory which serves your document root - for Rails applications this would be RAILS_ROOT/public/ - and it'll either spit out a list of missing files you've tried to @import or tell you that you've done well.

Missing files declared as imports in CSS:

Origin:               /Users/craig/projects/1.8/public/stylesheets/.../find_by_service.css
Missing @import file: /Users/craig/projects/1.8/public/stylesheets/.../a_to_z.css
Directive:            @import url('.../a_to_z.css');

Now, just to be clear, I don't like @import directives. I'd prefer they were completely removed from the CSS. They are popular with a lot of people though so I'll compromise for the moment: if you must use them, please make sure they're going to work.

Using signals to debug long-running processes

Sometimes a long-running process will start to perform it's tasks much slower than it should, or in a strange order. It'd be lovely to know what the process is doing but strace produces a deluge of information that is several levels below what you want to know. What can you do?

Well, we could ask the process to turn on debugging output while it's still running. How does that sound?

trap("USR1") do
  $DEBUG = !$DEBUG
  @logger.level = $DEBUG ? Logger::DEBUG : Logger::INFO
  @logger.info "USR1 received. Turning #{$DEBUG ? 'on' : 'off'} debugging."
end

Now whenever you need more debugging information simple send a USR1 signal to your process.

kill -USR1 [pid]

About the boy

A picture of Craig in grayscale

Hi, I'm Craig and I'm a Ruby coder. I live, work and play in London. I like scaling applications and eating yoghurt. Sometimes I climb rocks. Most of the time I climb back down.

You can contact me by email, MSN or Jabber. My address on all of these is craig@xeriom.net.

Licence

The entire content of this blog is public domain. Use it however you fancy. You don't even need to attribute it to me, although it would be nice if you did. Just don't sue me and we'll all be happy.

Interesting Blogs

I Work With Rails

Recommend Me

My Travels

I go places. Do you go places too? Let's meet up!.