Tagging in ajax_scaffold
13 Oct, 2006

I’ve been using the Ajax Scaffold for quite some time now. It’s a great piece of software by Mr. Richard White for Ruby on Rails. It seems that the plugin version of AS is getting quite a bit more attention than the generator. I started out with the generator but quickly reverted to the plugin since it’s way more flexible and easier to use.

Since I wanted to create a quick app to inventory my CD/DVD collection (which is now in a very sexy alu DJ case) I used Ajax Scaffold to get me started. In the spirit of Web 2.0 I wanted to add tags to every CD so it would be easier to find certain kinds of disks later on. So, I added acts_as_taggable.

Acts_as_taggable basically allows you to tag any model in your app. So, I made my Disk model taggable. Great. Now I could do this:

d = Disk.new(:number => 1, :name => "Mac OS X 10.4.6 Install DVD 1")
d.tag_with("macoxs apple macbook install")
d.save

The real problem was, how to get this functionality easily integerated in Ajax Scaffold?

First of all I had to show a column in AS that included the tags attached to a given disk. I specify all rows manually in the Manager controller. Manager is scaffolded using AS. Here’s what my Manager controller looks like:

class ManagerController < ApplicationController
ajax_scaffold :disk

@@scaffold_columns = [
AjaxScaffold::ScaffoldColumn.new(Disk, { :name => "number" }),
AjaxScaffold::ScaffoldColumn.new(Disk, { :name => "name" }),
AjaxScaffold::ScaffoldColumn.new(Disk, { :name => "tags",
:eval => "row.tag_list", :sort => "tag_list"}),
]
end

This will show three columns, including a column named ‘tags’. Every model that acts_as_taggable has some extra methods. tag_list is a single string containing all tags seperated by spaces. So, the tags column shows the tag_list for that row. With :sort I specify that AS can just sort keywords alphabetically.

Great! I now can see tags on disks! But, we also need to add those tags and that’s where it got tricky.

Adding tags is not done by assignment but by calling a method with your tags, as shown before: tag_with (string). I could create a custom create and update method for the Disks, but there’s a prettier solution available.

tag_list returns a string with the current tags. How about using that same name to assign tags? It’s rather easy. Here’s my Disk model:

class Disk < ActiveRecord::Base
acts_as_taggable

validates_presence_of :name, :number

def tag_list=(new_tags)
tag_with new_tags
end
end

Now we can assign tags to tag_list as well as read the tags out. Now the only step is to add a special textfield to the form partial for AS.

<label class="required">Tags</label>
<%= text_field 'disk', 'tag_list' %>

Now when a new disk is created or when one is updated, the tag_list will automagically be updated in a correct fashion.

Enjoy!