Simple way to add tags to a Rails model without plugins

Question

How do I implement tags in Rails without plugins?

I have a Rails application, similar to a blog, and I would like add some tags to the posts.

I see that there are some plugins / gems for tagging:

https://www.ruby-toolbox.com/categories/rails_tagging

However they all seem cumbersome for my use case (e.g. they include many Rails migrations).

How can I implement tagging in Rails from scratch?

Answer

You can add tags to a Rails model (e.g. Post) using PostgreSQL arrays.

First you need to add a new column for tags to your model:

class AddTagsToPosts < ActiveRecord::Migration[7.0]
  def change
    add_column :posts, :tags, :string, array: true, null: false, default: []
    add_index :posts, :tags, using: :gin
  end
end

This adds an array column for tags to the posts table in the database. It also adds an index in order to filter by tag.

Then in your Post model:

class Post < ApplicationRecord
  before_validation :normalize_tags
  def tag_list= list
    self.tags = list.split(',').map(&:strip)
  end
  def tag_list
    self.tags.join(', ')
  end
  private
  def normalize_tags
    self.tags.map!(&:parameterize)
  end
end

We do two different things here:

  • Tag normalization (e.g. convert “My awesome tag!” to “my-awesome-tag“)
  • Define an additional attribute setter and getter in order to deal with tags like comma-separated strings (this can be useful later in the view in order to use a simple text field)

Then in the controller you have:

def post_params
  params.require(:post).permit(:title, :body, :tag_list)
end

And in the form view:

<%= f.text_field :tag_list %>

Finally you can access tags normally as an array:

@post.tags.each { |t| puts t }