Auto-Complete Text Fields in Rails 2
[Note: this entry updated to include required routing, as I failed to mention that the first time.]
In Rails 2, the PrototypeHelper and ScriptaculousHelper code was removed to plugins. This means that doing auto-complete for various fields was no longer part of the base Rails. I didn't find any great, straight-forward docs on how to do this for Rails 2.x, so am sharing what I've done to hopefully help others. Further, the README for this tells you how to do it for standard string fields on a given object, but I needed to do it for an associated object field, so I'll cover that here as well. As you can guess, this only pertains to Rails 2.x...First you'll need to install the auto_complete plugin:script/plugin install auto_complete
This plugin will give you the text_field_with_auto_complete view helper method amongst others. It also provides a controller hook ( auto_complete_for) to implement the auto-complete action/method in your controller for you, if that works for the field you need. As per the auto_complete README, it looks like:
class BlogController auto_complete_for :post, :title
end
auto_complete_for, as used above, would implement a auto_complete_for_post_title method in your controller class. The parameters are the object and field/method of that object. The method it implements will dig through all the Post records in your database and do a LIKE comparison on the title column, comparing the title to the contents of the post[title] form field. With the results, it will generate the HTML for an unordered list (ul), and return that to the view.This is pretty slick: you can essentially get auto-complete with a view method name change in your HTML (from calling text_field, to text_filed_with_auto_complete), and a single line added to your controller. Now, what happens if the field you want to auto-complete on doesn't directly correlate to a field on your model object? For example, in my case, I wanted to auto-complete on a field from a belongs_to association, so I couldn't use the pre-built auto-completion method that does a direct SQL query on the field.This is actually easy to solve. You can just implement the auto_complete_for_object_field method yourlself. And, while you're at it, you might as well leverage some of the other helpful methods in the auto_complete plugin. Or, if you need custom view/HTML output, you can just render as you need within that method. When you do this, do not call the controller hook, simply implement the method yourself. Here's mine for example:def auto_complete_for_doctor_organization
re = Regexp.new("^#{params[:doctor][:organization]}", "i")
find_options = { :order => "name ASC" }
@organizations = Organization.find(:all, find_options).collect(&:name).select { |org| org.match re } render :inline => "<%= content_tag(:ul, @organizations.map { |org| content_tag(:li, h(org)) }) %>"
end
Finally, for completeness, here's the field's definition in my view template (Erb):
<label for="organization">Group/Practice/Hospital Affiliation</label>The one counter-intuitive looking thing there is the :autocomplete => "off" bit. Uh, aren't we doing autocomplete? Well, this particular attribute tells the browser to not do it's auto form completion stuff (so that our code can do it instead). Oh, and of course you need to ensure you are including Prototype and Scriptaculous JavaScript libraries in your views, which you can achieve, rather bluntly, with:
<%= text_field_with_auto_complete :doctor, :organization, :autocomplete => "off" %>
<%= javascript_include_tag :all, :cache => true %>Finally, you will need to add route(s) to your routing file. I use a sort of wild-card route to cover all my auto-completes:
map.auto_complete ':controller/:action',
:requirements => { :action => /auto_complete_for_\S+/ },
:conditions => { :method => :get }
This will resolve any routes that match an action starting with "auto_complete_for_".With that, we have auto-completing text fields in Rails 2.x! Cool stuff.
Comments [0]