ActiveScaffold + acts_as_taggable + Auto Complete
I’ve talked before on how to use ActiveScaffold with acts_as_taggable_on_steroids.
The problem with that solution was that, although the checkboxes for every tag are very nice, you couldn’t easily add new tags. For some people, this may be fine, for others, it is not.
Together with a colleague (who wishes not to be named), I found a solution that is quite elegant. Instead of using check boxes, and creating all kinds of subforms in ActiveScaffold, we opted for an auto_completing, comma-separated list of tags.
This article descripes the solution we found. I think you’ll like it very much!
When you try to use acts_as_taggable with ActiveScaffold, you might use something like this in your BooksController.
active_scaffold :books do |config| config.columns = [:title, :body, :tags] config.list.columns = [:title, :tag_list] config.columns[:tags].ui_type = :select # ... end
This is not so useful when you want the flexibility of creating new tags instantly. Therefore, it’s better to use the tag_list:
active_scaffold :books do |config| config.columns = [:title, :body, :tag_list] config.list.columns = [:title, :tag_list] # ... end
You get a text_field for writing down the tags (comma-separated). The problem of this is that the user has to keep all the tags in mind and is not allowed to make any typos in the tag. To help our users out, I use Rails’ auto_complete feature.
In your BooksController:
auto_complete_for :book, :tag_list def autocomplete_tag_list @all_tags = Tag.find(:all, :order => 'name ASC') re = Regexp.new("^#{params[:record][:tag_list]}", "i") @tags = @all_tags.find_all do |t| t.name.match re end render :layout => false end
We can now create the template for the results which are found.
In app/views/books/autocomplete_tag_list.rhtml:
<ul class="autocomplete_list"> <% @tags.each do |t| %> <li class="autocomplete_item"><%= t %></li> <% end %></ul>
Now comes the difficult part, integration of the auto_complete widget within ActiveScaffold.
ActiveScaffold has the possibility to change the way every attribute is displayed on the create and edit page. I want to change the form for the attribute ‘tag_list’. To do this, I create create a file named app/views/books/_tag_list_form_column.rhtml:
<dl>
<dt>
<label for="record_tag_list">AutoCompleted Tag List</label>
</dt>
<dd>
<%= text_field_tag 'record[tag_list]', @record.tag_list %>
<p class="auto_complete" id="record_tag_list_<%=@record[:id]%>_auto_complete">
style="{height: 80px;}">
<script type="text/javascript">
//<![CDATA[
var record_tag_list_<%= @record[:id].to_s %>_auto_completer =
new Ajax.Autocompleter(
\'record[tag_list]\',
\'record_tag_list_<%=@record[:id]%>_auto_complete\',
\'/articles/autocomplete_tag_list\', {tokens: \',\'});
//]]>
</script>
</dd>
</dl>This shows a text field and generates a div that contains the available tags that we can show to the user. To populate the list of tags we use Ajax.Autocompler, which requires three arguments: the id of the text_field; the id of the div where you want to show possible tags to the user; and third, the URL of the action we created before, that returns the proper tags.
The ‘tokens’ part of the last argument indicates that the user can seperate multiple tags with a comma. So, if you’ve entered one tag, added a comma and start typing a new tag, the auto complete feature will only lookup that second tag you’re typing!
That’s it. Just spice things up a bit with some Style, and you’re done. Enjoy!









[...] ActiveScaffold + acts_as_taggable + Auto Complete [...]
It seems to work great, thanks for that work !
Well, please digg the story, then. ;) Thanks.
done :)
This is nifty. One, how do we speed it up? Two, how can we make it behave more like when you tag a page with del.icio.us?
This is a great tutorial. My only suggestion would be to change the autocomplete to do the string matching in sql as follows:
def autocomplete_tag_list
@tags = Tag.find(
:all,
:order => “name ASC”
:conditions => ["name LIKE ?", "#{params[:record][:tag_list]}%”]
)
render :layout => false
end
Nice – This is exactly what I was looking for!
I’ll implement this after lunch…
:)
Hi,
I ve got a very nice “bug” using Acts as taggeable and Active Scaffold.. let me explain very fast..
I ve got 2 models (categ and souscateg), which all use acts_as_taggeable… these to models are linked together :
categ has many souscateg
souscateg belongs_to categ
In ActiveScaffold configuration for both model i include the other model..
for example for souscateg controller, i ve :
config.columns = [:tag_list, ****, :categ]..
With that, when i edit a tag list, it s the mess, because ActiveScaffold doesn t understand to which tag_list it refers…
In log it s possible to find out :
ActionView::TemplateError (undefined method `tag_list’ for #) on line #6 of app/views/souscateg/_tag_list_form_column.rhtml:
(because of the inclusion, tag_list is loaded both for souscateg and categ, and it seems to be a big problem there)
If i exclude :categ from ActiveSaccold souscateg controller configuration, it works well…. but unfortunately i need it…
Do you have any idea of how to resolve that problem ?
thx a lot
Guillaume.
The “tokens” piece is exactly what I was looking for! I am a tad surprised that this hasn’t been incorporated into the auto_complete plugin.
Thanks!
Just upgraded to Rails 2.2.2 and the corresponding version of Active Scaffold. This solution doesn’t appear to be working anymore.
@Anthony: I think ActiveScaffold is borked in 2.2 anyways. ;-) I’ve been staying well clear of it lately.