Tagging in ajax_scaffold

13 October 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

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!