If you've ever implemented type-ahead functionality and wondered how to get it to work when users are entering multiple items, like a list of comma delimited tags, here it is.

You can, of course, roll your own Javascript and Ajax calls but why bother when Rails gives us a nice Javascript helper to handle this. The helper is text_field_with_auto_complete but this defaults to the current controller. For my purposes tags can be entered on different areas of the site for different models so I used text_field_with_auto_complete with one modification:

def text_field_with_auto_complete_with_custom_url(object, method, url_options = {}, tag_options = {}, completion_options = {})
  (completion_options[:skip_style] ? "" : auto_complete_stylesheet) +
  text_field(object, method, tag_options) +
  content_tag("div", "", :id => "#{object}_#{method}_auto_complete", :class => "auto_complete") +
  auto_complete_field("#{object}_#{method}", { :url => { :action => "auto_complete_for_#{object}_#{method}" }.update(url_options) }.update(completion_options))
end

Note: text_field_with_auto_complete is deprecated and will be moved to a plugin in Rails 2.0.

The third parameter is now a hash of optional url arguments (action, controller, etc). You can also monkey patch the original method or better use some alias/alias_method_chain trickery in your own app. In your view call the newly created helper with your arguments.

<label for="tag_name">Tags:</label>
<%= text_field_with_auto_complete_with_custom_url :tag, :names, 
    {:controller => "tagging_demo"}, {}, { :tokens => ','} %>

Include the necessary javascript libraries (prototype and scriptaculous):

<%= javascript_include_tag 'prototype' %>
<%= javascript_include_tag 'scriptaculous' %>

You can set the controller and action to whatever you like but it defaults to a method in the form of auto_complete_for_object_method. Going with that your action could look something like this:

def auto_complete_for_tag_names
  @tags = Tag.find(:all, 
    :conditions => ["name like ?", "%#{params[:tag][:names]}%"], 
    :order => 'name DESC', :limit => 20)
  render :layout => false
end

And your view (auto_complete_for_tag_names.html.erb):

<ul class="tags">
<% for tag in @tags do -%>
  <li class="tag"><%= tag.name -%></li>
<% end -%>
</ul>

That's all there is to it. The magic comes from providing a token to Ajax.Autocompleter which we provided in the argument hash to text_field_with_auto_complete_with_custom_url ( { :tokens => ','} ). You can use any delimiter you like. You can also customize the UI in your view and CSS.

Here's a demo http://www.naffis.com/demos/tagging_demo