Migrate tags in Rails to PostgreSQL array from ActsAsTaggableOn

ActsAsTaggableOn is a swiss army knife solution if you need to add tags to your ActiveRecord model.

Just by adding one gem to your Gemfile and acts_as_taggable to the model you get everything you need: adding tags, searching for a model by tag, getting top tags, etc. However, sometimes you don't need all these.

In our project, we used acts_as_taggable to store tags for Note model. Then we displayed a list of notes on several pages with assigned tags and had autocompleted input for tags on Note form. Everything worked well, but since we use PostgreSQL, I decided to store tags as an array in Note model.

First of all, I added tags Array<String> column to Note, after this migrated actsastaggable tags to notes table with migration.

 class MigrateNoteTags < ActiveRecord::Migration[5.2] def change execute <<-SQL UPDATE notes SET tags = grouped_taggings.tags_array FROM ( SELECT taggings.taggable_id, ARRAY_AGG ( tags.NAME ) tags_array FROM taggings LEFT JOIN tags ON taggings.tag_id = tags.ID WHERE taggable_type = 'Note' GROUP BY taggings.taggable_id ) AS grouped_taggings WHERE notes.ID = grouped_taggings.taggable_id SQL end end 

To have backward compatibility, I added Note#tag_list method:

 def tag_list tags.join(', ') end 

The last thing is to add the ability to search for tags. Since there about 500k records in the Notes table, I decided to create an SQL view:

 CREATE OR REPLACE VIEW note_tags AS SELECT UNNEST ( tags ) AS name, COUNT ( * ) AS taggings_count FROM notes GROUP BY name 

That's it! It takes from 100ms to 150ms to search for tags in this view, which is fine for me.

If you have more significant data sets, then the best would be to create tags table and add triggers to notes table that will update tags on INSERT/UPDATE/DELETE.

Do you have a project for us?Get a free quote