Archive for August, 2006

Tiny Drawing

Inspired by the flurry of 13×13 icon creation, Luis and I have been at work the past day on a new, super low resolution icon creation system called Tiny. I’ve written a javascript version with a Rails backend that uses RMagick to produce the PNGs. Meanwhile Luis has thrown together a nice little applet, which I have to admit is a tad more sophisticated than my version. We’ll integrate them in the next few days. It’ll be pretty easy, since creating a new icon is as easy as sending an HTTP POST with a data parameter of 169 0’s or 1’s. Title and parent parameters are taken optionally.

Forever alpha at http://tiny.media.mit.edu/

Tiny

The excitement will really never end. There are 2^169 possible images! Thanks to Amber for the original inspiration with her Mini app for OS.

A Market, but for What?

This morning Luis and I are having a nice talk about whether an OS-like market should trade in media (drawings, audio, video, animation) at all, or whether we should be thinking about markets for social information: gossip, secrets, tips, howtos, critiques, even opinions. What would you rather buy: a drawing, or an answer?

Fabulous 13×13 Icons

Roller Skate Rollerskate
Key Factory Key Factory
Splatter Splatter
Little Dancing Guy Little Dancing Guy
Small to big to small Small to Big and Back to Small
Knife Knife
Evil Tripod Evil Tripod

Friendly Ruby (Quiz Solution)

My solution to the recent Ruby Quiz #91 is friendly.rb, a module that allows a user to interactively add method definitions at runtime.

module Friendly

  def method_missing name
    @_new_methods ||= Hash.new
    unless @_new_methods.has_key? name
      prompt_for_definition name
    end
    eval @_new_methods[name]
  end

  def prompt_for_definition name
    puts "It appears that #{name} is undefined."
    puts "Please define what I should do (end with a blankline):"
    @_new_methods[name] = ""
    while $stdin.gets !~ /^\s*$/
      @_new_methods[name] << $_
    end
  end

  def added_methods
    @_new_methods.keys
  end

  def added_method_definitions
    @_new_methods.map {|k,v|
      s = "def #{k}\n  "
      v.rstrip!
      s << v.gsub("\n", "\n  ")
      s << "\nend"
    }
  end

end

Example usage, in this case just using Friendly to extend the top level object:

irb(main):001:0> include Friendly
=> Object
irb(main):002:0> foo = bar * z
It appears that bar is undefined.
Please define what I should do (end with a blankline):
12

It appears that z is undefined.
Please define what I should do (end with a blankline):
4

=> 48
irb(main):003:0> foo
=> 48
irb(main):004:0> bar
=> 12
irb(main):005:0> z
=> 4
irb(main):006:0> added_methods
=> [:z, :bar]
irb(main):007:0> puts added_method_definitions.join("\n\n")
def z
  4
end

def bar
  12
end
=> nil
irb(main):008:0>

Tinkering and Linux (postscript)

I’m finding that this tinkering admin work is a craft that, while perhaps not my primary direction, is not without its pleasures. The depth to which we can pursue and immerse ourselves in studying this sort of technology is essentially limitless. With linux this is as deep as I’ve ever been. When I am learning a new piece of the puzzle like LVM or fsck or mysql, I like to think about all the people who have independently contributed to designing and creating these various tools that cumulatively form such a powerful, flexible system. So much work, so many hours, and so many intelligent ideas have formed linux. It is so big now that I doubt any single individual can understand the whole. I find this complexity surprisingly comforting. We’re moving away from the computer science and engineering paradigm of the abstracted, closed, controlled system, and towards something new, more along the lines of the messy, chaotic, interconnected realm of the natural and social sciences. Or, more accurately, the real world.

Red Hats and Logical Volumes & Mongrels

After a few days of setup our new Dell PowerEdge 1950 1U server is starting to come alive. It is a very capable machine with two dual core 3GHz Xeons, 16 GB memory and an effective 300GB of RAID 1 space. Probably more than we need at the moment, but between PLWire, Opencode and Luis’s new painting tools (prototype only), it makes sense to start serving this all from a new machine.

I still haven’t figured out how to manage the RAID. Dell’s documentation on the PERC 5/i controller is pretty much worthless. It all came set up and working, but it’s unclear how we can monitor the drives to know if one actually dies. Some sort of Windows disks came with the machine, but (a) we don’t have Windows here, and (b) I’m not sure if they are even the right thing. Before starting this thing in production I’m tempted to just pop out one of the drives while the machine is running, as was suggested in some of the forums I’ve been reading. Now I understand what Apple is doing so right with its easy, clear graphical admin software for the Xserve RAID.

One positive note here is that I’m learning all about LVM (Logical Volume Management), which allows fairly flexible configuration of virtual partitions. With extra free space on the physical volume group (ie disks), and of the logical volumes can be expanded simply by running umount, lvresize or lvextend, and the mount. Unfortunately it isn’t so easy if you are trying to extend the volume for /usr, since the mount is usually being used by a bunch of processes and can’t be umounted. So I just created a new 120GB logical volume with mount point /plw for our databases and web apps.

I’m also getting to know mysql more than I ever expected. I have to admit that it really isn’t so horrible a mess as I thought. The magical moment came when I started working directly with the /etc/my.conf file, which acts as the default mysql configuration file. There are still a ton of flags and options that I need to go through to optimize it. I had also never setup linux startup processes, so it was a relief when it turned out that it really wasn’t all that hard using chkconfig.

We’re going to make this mainly a rails production-level machine, the goal being a Rails/Mongrel/Pound/Apache setup, possible with Capistrano for deployment if I can figure that one out. I already have a test version of PLWire running on there, and even in vanilla development mode it seems pretty speedy, much better than the OSX Server machine. Kelly and I had a similar experience moving OPENSTUDIO to an Ubuntu machine earlier this year, so I’m not all that surprised.

Acts As Permalinkable

I’ve released the polymorphic acts_as_permalinkable plugin that I developed for use with PLWire. To install:

./script/plugin discover \
   http://plw.media.mit.edu:9090/repository/public/rails/plugins
./script/plugin install -x acts_as_permalinkable
./script/generate permalinkable_migration
rake migrate

Then just add the acts_as_permalinkable snippet to your models:

class Article < ActiveRecord::Base
  acts_as_permalinkable
  ...
end

class Photo < ActiveRecord::Base
  acts_as_permalinkable
  ...
end

When you save your model the permalink will automatically update as well. By default it uses a title attribute to create the slug and the created_on attribute for the date, but this is easily customized. For example to use it with the name attribute and the updated_at attribute:

  acts_as_permalinkable \:on => :name,
                         :use_date => :updated_at

You can also provide a Proc that filters the permalinkable title field before it is turned into a slug. For example maybe you want to strip the tags and only take the first 20 characters:

  acts_as_permalinkable \:on => :content,
      :slug_modifier => lambda { |x|
             x.gsub(/\<.+?\>/, "").strip[0..20]
          }

Within your views you can link to the permalinks with a few url helper methods, url_for_permalink and link_to_permalink:

<%= url_for_permalink @article,
    {:action => "permalink"},
    {:class => "permalink",
     :title => "Permalink for '#{@article.title}'"}
%>

<%= link_to_permalink "permalink", @article,
    {:action => "permalink"},
    {:class => "permalink",
     :title => "Permalink for '#{@article.title}'"}
%>

And within your controller just use the find_permalinked method:

find_permalinked :slug => "this-is-a-slug",
    :year => 2006,
    :month => 8,
    :day => 7

Underspecifying these parameters will return a collection for all matching records. Or if your parameters already have these values it is pretty easy:

find_permalinked params

You can add permalinks to existing records with the create_all_slugs singleton method. I use the console. For example, with an Article model:

Article.create_all_slugs

Hope it works out to be helpful for at least a few people out there.