Kristian Nissen

Icon

my contemporary identity

Running your own taggable in Rails isn’t that hard

I’m working on a Rails app where I want to offer the ability to use tags (labels) for categorization, but they have to be polymorphic since I don’t want to have more than one table with tags.You will need something like the following setup if you want to roll your own tagable tables in your Rails app:

class Taxonomy < ActiveRecord::Base
belongs_to :job, :polymorphic => true
belongs_to :applicant, :polymorphic => true
belongs_to :tag
end

This model is polymorphic and you will have to specify all the different associations between this polymorphic model and the models that will use it, in this case both jobs and applicants can make use of tags (labels).

class Tag < ActiveRecord::Base
has_many :taxonomies
end

The Tag model only contains our tags (labels) and nothing else, but since I want to be able to use the same tags for both models, they have their own model – this also gives me the advantage to extend these models later on.

And here we have the applicant model:

class Applicant < ActiveRecord::Base
belongs_to :job
has_many :ratings
has_many :taxonomies, :as => :tagable
has_many :tags, :through => :taxonomies
end

As you can see, this model has many taxonomies using the interface :tagable, and the applicant model has many tags through taxonomies, let’s see how you can use this in your app, I’ll use script/console for demonstration:

>> reload!
Reloading...
=> true
>> Applicant.find(1)
=> #<Applicant id: 1, email: "k", job_id: 1, created_at: "2009-05-16 11:56:45", ...
>> Applicant.find(1).tags
=> []
>> Applicant.find(1).tags << Tag.create(:name => 'Groovy')
=> [#<Tag id: 3, name: "Groovy", created_at: "2009-05-17 07:40:14", updated_at: ...
>> Applicant.find(1).tags
=> [#<Tag id: 3, name: "Groovy", created_at: "2009-05-17 07:40:14", updated_at: ...
>>

First I grab my Applicant from the database and then fetching that Applicants tags by using Applicant.find(1).tags, this provides me with an empty collection []. Now I can create a new Tag and associate this with my Applicant by using the following line of code: Applicant.find(1).tags << Tag.create(:name => 'Groovy').

Now to get a collection of tags for a particular Applicant I just run Applicant.find(1).tags and there you have it, the Applicant model now has a nice tag associated with it. The brilliant idea here is that I can also choose to tag a job using the same tag as I just used for the Applicant.

Filed under: code is poetry , , , , ,

Leave a Reply