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 , Rails, Polymorphic, Has Many Through, Taxonomy, Tags