Skip to main content

Acts-as-taggable-on

Using Acts As Taggable On

If you have an ActiveRecord model and you're using acts-as-taggable-on, chances are you might want to search on tagged fields. Follow the instructions to install the gem and then set up your project files.

Configure the model

app/models/tasks.rb

You can call the tagging field anything you like, it just needs to be plural. No migration is needed as this is stored in the internal ActsAsTaggable tables (tags and taggings).

class Task < ApplicationRecord
acts_as_taggable_on :projects
end

Controller

Add a field to strong params in the controller. Use the singular name with _list.

app/controllers/tasks_controller.rb

def strong_params
params
.require(:tasks)
.permit(:task, :example_field, :project_list)

Form

We need to send the tag fieldname to our model, also using the singular naming.

<div class='form-group'>
<%= f.label :project_list %>
<%= f.text_field :project_list, value: @task.send(:project_list).to_s %>
</div>

Now we can collect our data via the form, with tags separated by commas.

Imagine you have the following two instances of Task:

{ id: 1, name: 'Clean up my room',        projects: [ 'Home', 'Personal' ] }
{ id: 2, name: 'Complete math exercises', projects: [ 'Homework', 'Study' ] }

When you're writing a Ransack search form, you can choose any of the following options:

<%= search_form_for @search do |f| %>
<%= f.text_field :projects_name_in %> <!-- option a -->
<%= f.text_field :projects_name_eq %> <!-- option b -->
<%= f.text_field :projects_name_cont %> <!-- option c -->
<% end %>

Option A - Match keys exactly

Option A will match keys exactly. This is the solution to choose if you want to distinguish 'Home' from 'Homework': searching for 'Home' will return just the Task with id 1. It also allows searching for more than one tag at once (comma separated):

  • Home, Personal will return task 1
  • Home, Homework will return task 1 and 2

Option B - match key combinations

Option B will match all keys exactly. This is the solution if you wanna search for specific combinations of tags:

  • Home will return nothing, as there is no Task with just the Home tag
  • Home, Personal will return task 1

Option C - match substrings

Option C is used to match substrings. This is useful when you don't care for the exact tag, but only for part of it:

  • Home will return task 1 and 2 (/Home/ matches both "Home" and "Homework")

Option D - select from a list of tags

In Option D we allow the user to select a list of valid tags and then search against them. We use the plural name here.

<div class='form-group'>
<%= f.label :projects_name, 'Project' %>
<%= f.select :projects_name_in, ActsAsTaggableOn::Tag.distinct.order(:name).pluck(:name) %>
</div>

Multitenancy

ActsAsTaggableOn allows scoping of tags based on another field on the model. Suppose we have a language field on the model, as an effective second level key. We would adjust our model to look like this:

class Task < ApplicationRecord
acts_as_taggable_on :projects
acts_as_taggable_tenant :language
end

The Ransack search is then filtered using the for_tenant method

<div class='form-group'>
<%= f.label :projects_name, 'Project' %>
<%= f.select :projects_name_in, ActsAsTaggableOn::Tag.for_tenant('fr').distinct.order(:name).pluck(:name) %>
</div>