MakeTaggable

Gem Version Downloads CI Standard Rb

Tagging for Active Record models, across any number of named contexts.

One model can carry several independent sets of tags — genres and moods, skills and interests — each with its own list, counts and queries. Tags can belong to the user who applied them, keep the order they were added in, and be cached on the record for display.

Requirements

Component Supported
Ruby 3.2 or newer
Active Record 7.2 or newer
Databases PostgreSQL, MySQL, SQLite

Tested against Rails 7.2, 8.0 and 8.1 on Ruby 3.2 through 4.0.

Install

bundle add make_taggable
rails make_taggable_engine:install:migrations
rails db:migrate

Quick start

class Book < ApplicationRecord
  make_taggable            # the :tags context, for free-form tags
  make_taggable :genres    # a context of your own, for a curated set
end

Each context is a separate set of tags, with its own list:

book = Book.create!(title: "Dune", genre_list: "sci-fi, classic")

book.genre_list                  # => ["sci-fi", "classic"]

Add and remove individual tags. Nothing is written until you save:

book.genre_list.add("space opera")
book.genre_list.remove("classic")
book.save

book.genre_list                  # => ["sci-fi", "space opera"]
book.genres                      # => [#<MakeTaggable::Tag name: "sci-fi">, #<MakeTaggable::Tag name: "space opera">]

Assigning replaces the whole list, and the two contexts never touch each other:

book.tag_list = "desert, chosen-one, re-read"
book.save

book.tag_list                    # => ["desert", "chosen-one", "re-read"]
book.genre_list                  # => ["sci-fi", "space opera"]

Find them again:

Book.tagged_with("sci-fi")                             # carries this tag
Book.tagged_with(["sci-fi", "space opera"])            # carries both
Book.tagged_with(["sci-fi", "fantasy"], any: true)     # carries either
Book.tagged_with(["fantasy"], exclude: true)           # carries neither

Scope a query to one context, and tags in the others stop counting:

Book.tagged_with("sci-fi", on: :genres)                # => [#<Book title: "Dune">]
Book.tagged_with("sci-fi", on: :tags)                  # => []

Counts, for tag clouds and "most used" lists:

Book.tag_counts_on(:genres)                            # tags carrying a `count`
Book.top_genres(10)

Tags are ordinary attributes as far as your controller is concerned:

params.expect(book: [:title, :tag_list])            # Rails 8
params.require(:book).permit(:title, :tag_list)     # Rails 7.2

Documentation

Guide Covers
Getting started Install, first tagged model, reading and writing
Tag contexts Multiple contexts, ordered tags, contexts created at runtime
Querying Every tagged_with option, counting, related records
Ownership Taggers, owned tags, and why tag_list can look empty
Parsers and delimiters Custom parsers, delimiters, escaping
Caching cached_*_list columns, and what they cost
Tag clouds Counts and the tag_cloud helper
Configuration Every setting
Database Schema, indexes, per-adapter notes
Migrating from acts-as-taggable-on Method and constant mapping

API documentation is generated with YARD:

bundle exec yard doc

Upgrading

See UPGRADING.md. Version 1.0 removes the acts_as_* method names and changes how delimiters are escaped.

Install new migrations when upgrading:

rails make_taggable_engine:install:migrations
rails db:migrate

Development

The test suite runs against bare Active Record — there is no dummy application to generate.

bundle install
bundle exec rake

That uses in-memory SQLite. To run against another adapter, point it at a database:

DATABASE_ADAPTER=postgresql DATABASE_URL=postgres://localhost/make_taggable_test bundle exec rake
DATABASE_ADAPTER=mysql2 DATABASE_URL=mysql2://root@127.0.0.1/make_taggable_test bundle exec rake

Across every supported Rails version:

bundle exec appraisal install
bundle exec appraisal rake

Format with Standard before opening a pull request:

bundle exec standardrb --fix

Public API needs YARD documentation. bundle exec yard stats --list-undoc should report 100%.

See CONTRIBUTING.md for more.

Credits

MakeTaggable is a fork of acts-as-taggable-on by Michael Bleigh and Joost Baaij, with thanks to its contributors.

License

Available as open source under the terms of the MIT License.