acts-as-taggable-on and space delimited tag lists

Written by pete

Topics: Code, Rails

UPDATE:

I made the classic coder mistake, and didn’t dig into the plugin code before working around it. I am leaving this post up instead of being embarrassed and deleting it because it a good example of why you should read your plugin code. After reading the code, I found that TAGLIST IS JUST AN ARRAY: you can simply do this and avoid all of the filter magic that I put in place below.

1
2
  # in config/initializers/tag_list.rb
  TagList.delimiter = " "

Drat. That’s way better.

As it turns out, this answer is in the README for acts_as_taggable_on_steroids, but not in acts_as_taggable_on. I’m sending Michael a note to ask him to include that detail in the documentation.

Original Post

Michael Bleigh’s acts_as_taggable_on plugin is a useful extension of acts_as_taggable_on_steroids.

When using it in forms, however, many users have noticed that the @model.tag_list field deals with comma separated lists of tags, like so:

1
2
# From the README
@user.tag_list = "awesome, slick, hefty"      # this should be familiar

If, in your edit view template, you provide a text field for your users to type in freeform tags, then you will find that your database tables have multiword tags instead of multiple tags. This is less than ideal. Users do not like to type commas.

Build your form like this, and you will see the issue when a user types in “awesome slick hefty” in the input box.

<% form_for([@model]) do |f| %>
    <div id="model_tags">
	Tags: <%= f.text_field :tag_list %> 		
    </div>
...
<% end %>

You will see this in your DB:

+----+-----------------------------------+
| id | name                              |
+----+-----------------------------------+
|  1 | awesome slick hefty               | 
+----+-----------------------------------+

What you wanted was this:

+----+-----------------------------------+
| id | name                              |
+----+-----------------------------------+
|  1 | awesome                           | 
|  2 | slick                             | 
|  3 | hefty                             | 
+----+-----------------------------------+

The Answer

My workaround involves using a before_filter to unroll the content of the input box, and a compactor method in the edit action to change the internal storage format of acts_as_taggable_on to the format that the user expects. Here is an example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# ... In the taggable_controller
  before_filter :join_tag_list, :only => [:create, :update]
 
  # GET /users/:id/quotes/1/edit
  def edit 
    @model ||= Model.find(params[:id])
    unroll_tag_list
  end
 
  private
  def join_tag_list
    # Split the tags on spaces and join into comma separated format
    params[:model][:tag_list] = params[:model][:tag_list].split(" ").join(",")
  end
 
  def unroll_tag_list
    # Split the tags on commas and join into a single space separated string
    @model.tag_list = @model.tag_list.join(" ")    
  end

That’s it! Now my users see and work with space-separated tags, and acts_as_taggable_on continues to store comma separated lists internally.

  • http://www.arctickiwi.com Jonathon

    Thanks for your post Pete, tried it as per your updated instructions and got this error:

    uninitialized constant TagList

    Wonder if it's to do with Rails 3?

    Cheers

    Jonno

  • dpie

    I needed to do this with Rails 2.3.8:

    # in config/initializers/tag_list.rb
    ActsAsTaggableOn::TagList.delimiter = ” “

  • dpie

    I needed to do this with Rails 2.3.8:

    # in config/initializers/tag_list.rb
    ActsAsTaggableOn::TagList.delimiter = ” “

  • http://www.creditcardslogic.com Bparanj

    How do you handle tags that has multiple words?

  • http://twitter.com/greham Vadim

    Pete, thanks.
    Working well!