#102
Apr 21, 2008

Auto-Complete Association

Usually a select menu is used for setting a belongs_to association, but in this episode I will show you how to use a text field with auto completion.
Tags: ajax forms
Download (20.3 MB, 13:29)
alternative download for iPod & Apple TV (15.6 MB, 13:29)

Update: As Stephen Gerstacker pointed out in the comments, the :param_name option is preferred over the :with option. See the code below for an example.

script/plugin install git://github.com/rails/auto_complete.git
# product.rb
def category_name
  category.name if category
end

def category_name=(name)
  self.category = Category.find_or_create_by_name(name) unless name.blank?
end

# categories_controller.rb
def index
  @categories = Category.find(:all, :conditions => ['name LIKE ?', "%#{params[:search]}%"])
end
<!-- products/_form.html.erb -->
<p>
  <%= f.label :category_name %>
  <%= text_field_with_auto_complete :product, :category_name, { :size => 15 }, { :url => formatted_categories_path(:js), :method => :get, :param_name => 'search' } %>
</p>

<!-- categories/index.js.erb -->
<%= auto_complete_result @categories, :name %>

RSS Feed for Episode Comments 114 comments

1. vesters Apr 21, 2008 at 02:50

Thanks very much - awesome!


2. jpemberthy Apr 21, 2008 at 06:25

Thaks! :P


3. Mourad Hammiche Apr 21, 2008 at 07:21

Hi

Your screencast make programming rails even more easy !

But there is something strange in the convention used for returning the matching categories.
"categories/index.js.erb" assume you returning javascript code ?
How does it works if I need to get real js elsewhere in my project ?

Thanks


4. Carlos JĂșnior Apr 21, 2008 at 07:44

Mourad Hammiche: instead of use formatted_categories_path(:js) you can use categories_path and at the :with clause you specify something like "partial=true" or "autocomplete=true", then you handle it in your controller to render a special HTML template for autocomplete. Imao it's better then use the js formatted being not semantic.


5. Ryan Bates Apr 21, 2008 at 08:14

@Mourad, great questions, I was wondering if someone would bring this up.

It would be really nice if the auto_complete plugin supported returning javascript (with rjs) instead of a simple HTML list, this way I could provide further instructions for modifying the functionality, however, AFAIK the plugin doesn't support this. Since the HTML list is so closely tied to javascript I find it acceptable to use the "js" extension.

As for your 2nd question, this is more difficult. You could pass a query parameter as Carlos mentioned. Alternatively you could create a new mime type, perhaps call it "autocomplete" and make an "index.autocomplete.erb" template. This should work, but I'm not sure if it's a best practice.


6. James Apr 21, 2008 at 08:15

Your best railscast to date! Thanks for digging into the details of auto-completing virtual attributes, it is just what I needed!


7. Lake Denman Apr 21, 2008 at 09:51

Nice, Ryan.
This was a good one.


8. mrb Apr 21, 2008 at 10:16

Hey Ryan! Thanks for the awesome screencast. One request -- when you show tips for associations which are simple has_many, it would be cool if you showed the same tip with how it would be changed with has_many :through -- this is a tripping point for a lot of beginners. Thanks!


9. Marcel Apr 21, 2008 at 12:47

Hi Ryan,

Just wanted to say thanks for this awesome screencast, and for all the others on your site. It's great to see an enthousiast like yourself sharing knowledge with the rest of the community.
You screencasts make my monday-mornings considerably more pleasant ;-).


10. Joe Beda Apr 21, 2008 at 14:30

Hey Ryan,

I love RailsCasts but I have two comments around this particular episode:

1) I think that using "js" for the request really is wacky. The content type of the response is "text/javascript" indicating that the content really *is* javascript. Perhaps this is a place to register a new psuedo mime type?

2) You are probably open to escaping bugs when you are passing the search parameter through. What happens with your sample app if you type "?foo=bar" into your category box. You need to url encode the value.

Change element.value to encodeURIComponent(element.value).

The prototype way would be to replace the entire :with value with:
Object.toQueryString({search: element.value})


11. Ryan Bates Apr 21, 2008 at 14:58

@Joe, good points. The more I think about it, a custom mime type would probably be a preferred solution here over using js. As mentioned above, ideally I would like to return javascript here with RJS, but AFAIK the plugin/scriptaculous doesn't support this. Someone please correct me if I'm wrong.

I hadn't thought about the escaping issue. I'll change the code in the show notes. Thanks!


12. James Apr 21, 2008 at 16:08

Hey Ryan,

This may be beyond the scope of this tutorial, but how do you handle setting virtual attributes that are scoped to another model? Let's say you want to have several categories that belong to a bucket, and want to find_or_create_by_name_AND_BUCKET_ID. You can't pass the bucket info to the virtual attribute in the model. This question is much more about virtual attributes than auto-complete, but I've had it come up a lot in other situations as well. Thanks!


13. Andrew Skegg Apr 21, 2008 at 16:08

This is just what I was looking for - thank you, thank you.


14. Geoffrey Grosenbach Apr 21, 2008 at 16:24

Great screencast, but it really exposed how hackish the autocomplete plugin is.

Why isn't it a regular form builder like the other form fields? Customizing it shouldn't be so awkward (i.e. passing raw Javascript). Why can't the controller method use the virtual attribute on the model?

To be honest, using unobtrusive Javascript seems more straightforward than jumping through Ruby to accomplish this.

There is a real opportunity for someone to refactor this plugin and become a hero!


15. Bryan Buchs Apr 21, 2008 at 19:24

[Long time listener, first time caller...] Ryan, I swear I saw you type "field.{tab}" to trigger a snippet of a formated label+field. Is that a stock TextMate function or something you wrote for yourself?


16. Ryan Bates Apr 21, 2008 at 20:30

@James, I'm not exactly sure if I understand your question. However, you could create a second virtual attribute for the bucket_id, save it to an instance variable, and use that in the category search.

@Geoffrey, I agree. I think they extracted this out into a plugin for a reason. I would love to see an updated version of it which flows better with modern techniques (such as REST).

@Bryan, it's a custom snippet I made. I use a lot of custom snippets and they are pretty easy to make. I recommend looking into it and developing your own library of snippets.


17. James Apr 22, 2008 at 07:51

Ryan,

Sorry I wasn't clear.

When you create a setter method, they can only have one parameter (the value of the virtual attribute). How do you include other values from your controller in these setter methods?

def category_name=(name)
  self.category = Category.find_or_create_by_name_and_parent_id(name, parent_id) unless name.blank?
end

Can't seem to figure out how to include additional variables (parent_id in this case) in these setters to keep them from being found if they 'belong_to' a different parent.

Same thing would occur if you were trying to tie a model object to "current_user".


18. Ryan Bates Apr 22, 2008 at 09:34

@James, the model will need access to the parent_id somehow, so I recommend creating a 2nd virtual attribute which sets an instance variable.

The problem is there's no way to guarantee the parent_id attribute will be set before the category_name. To solve this, you can use a callback to handle the category setting. Check out this code.

http://pastie.caboo.se/184873

You may want to email me if this doesn't solve your problem: ryan[at]railscasts[dot]com


19. Dan L Apr 22, 2008 at 11:58

Ryan, great railscast as always, but I have a question. When I enter "categories.js" into my browser to display the list of autocomplete items, I get "No route matches '/categories.js' with {:method=>:get}". I don't think I have my routes set up properly. Did you add any routes besides the default ones? I'm not well versed in routing yet, so I'm not sure what I need to add.


20. James Apr 22, 2008 at 12:17

@Dan - You'll probably want to add "format.js" to your respond_to block in your categories controller.


21. Dan L Apr 22, 2008 at 13:00

Thanks James; finally got it working! I had assumed I didn't need it since the file was index.js.erb instead of index.html.erb. Thanks for the help.


22. James Apr 22, 2008 at 13:59

Ryan,
Thanks for the help, adding an additional virtual attribute and doing the find_or_create in a callback worked perfectly.


23. Ryan Bates Apr 22, 2008 at 16:29

@Dan, Here's what my routes file looks like:

map.resources :products, :categories

This generates the formatted_catgories named route which should do what you want. I didn't need a respond_to block in my controller, but if you're not using Rails 2 you will need one.


24. Lucas Uyezu Apr 22, 2008 at 21:08

Thanks for the screencast, it's great and very useful.

When I was trying this, I found a problem with my controller: It wasn't generating anything in the "/controller.js" step. So I put the following code in the end of the method:

respond_to {|format| format.js}

When I tested it, I was given a 'Template is missing' screen, asking for an 'layouts/application.js.erb'.

So I realized my controller has a unremoved "layout 'application'" line in it.

After I removed it, it all worked.

I don't know what really happened, but it may generate some headache for people who'd really need the "layout 'application'" line.


25. Tim Apr 23, 2008 at 05:13

@Lucas - thanks for this 'semi' fix. I've been having problems with for the last day - no one else mentioned having problems so I thought my copy paste skills needed tuning...

I also have a layout :switch_layout (which is serves up a different layout depending on who's logged in) in my controller which is sending this Railscast off the tracks.

From what I've read of the above comments (Ryan, Joe and Geoffrey) - it would be cool to see a sudo mime type used and also a refactored auto_complete plugin...

Anyway, thanks for the screencast :D


26. Aerpe Apr 23, 2008 at 05:41

Hey,

I can't find any contact details so I'll try my luck here.

There's hardly any resources or tutorials on developing the navigation for an application with rails.

Any subject you plan on taking on?

Kind regards
Aerpe


27. Clemens Kofler Apr 23, 2008 at 07:16

I think the main problem is that scriptaculous' Ajax.Autocompleter by default sets the target element's innerHTML to the response of the AJAX call.

Maybe an idea would be to override Ajax.Autocompleter's default onSuccess behavior so that it parses a, say, JSON string and turns it into a list before assigning it to the innerHTML of the target element. This way, it would be reasonable to have a mime type of text/javascript or even application/json because JSON is returned.


28. Ryan Bates Apr 23, 2008 at 09:10

@Lucas, you shouldn't need to specify "layout :application" as this will be the default. However, if you do need to specify another layout you can do this:
http://pastie.caboo.se/185520

I would consider this to be a bug in Rails, maybe I'll get around to submitting a ticket or patch.

@Aerpe, thanks for the suggestion. I'll add it to my list. :)


29. Bala Paranj Apr 23, 2008 at 19:48

Great screencast! I had this problem in one of the project I am working one. Thanks.


30. Adam Apr 24, 2008 at 02:21

Thanks Ryan for yet another gem of a tutorial. keep up the great work.


31. Stephen Gerstacker Apr 24, 2008 at 08:40

This almost works, but it breaks support for tokens.

Instead of specifying :with, I use :param_name. This gives you the correct query string, it escapes the query automatically and tokens are supported.

<%= text_field_with_auto_complete :product, :category_name, { :size => 15 }, { :url => formatted_categories_path(:js), :method => :get, :param_name => 'search' } %>


32. Ryan Bates Apr 24, 2008 at 13:57

@Stephen, thanks! I had no idea there was a :param_name option. That is much nicer. I'll update the code in the show notes.


33. FJuan Apr 28, 2008 at 03:34

Thanks Ryan, you're doing a great job!

I've got a little question: is there an easy way to combine "comlex forms" and "autocomplete with association"?

What I'm trying to do is a "purchase order" form with differents "purchases" (like a porject with different tasks) and I'd like to autocomplete the name of the product of each purchase

Thanks again


34. Ryan Bates Apr 28, 2008 at 08:42

@FJuan, I haven't tried it, but you should be able to do this. The main thing you have to watch out for is that text_field_with_auto_complete can't be called through the form builder. This means you'll somehow have to get the name of the field to match what a normal text field would be. You may need to dig into the source code of text_field_with_auto_complete to figure out how to do this.


35. Joe Jammy Apr 30, 2008 at 11:48

Great work Ryan! I'm a rails beginner and this website has been a huge help.

@FJuan, I'm trying to do a similar thing using the autocomplete in conjunction with Ryan's complex forms. I'm going to look into the source code as Ryan suggested, and hope I dont mess things up. Thanks again Ryan!


36. Tim Cooper May 01, 2008 at 03:25

Thanks for this screencast - a really nice solution to drop down lists!

I'm having some troubles though... when I goto the url http://localhost:3000/categories.js nothing shows up... This is my dev.log

<pre>
Processing CategoriesController#index (for 127.0.0.1 at 2008-05-01 20:25:12) [GET]
  Session ID: BAh7BzoMY3NyZl9pZCIlZGU1MWNkNzQ2MTYzYTQ0MmY3ZDZmNDhhMjljYjU2%0ANjYiCmZsYXNoSUM6J0FjdGlvbkNvbnRyb2xsZXI6OkZsYXNoOjpGbGFzaEhh%0Ac2h7AAY6CkB1c2VkewA%3D--9533e6fe70bd20e0155ec58df1e28d241ac42676
  Parameters: {"format"=>"js", "action"=>"index", "controller"=>"categories"}
  Category Load (0.000386) SELECT * FROM `categories` WHERE (name LIKE '%%')
Completed in 0.00667 (149 reqs/sec) | Rendering: 0.00005 (0%) | DB: 0.00039 (5%) | 406 Not Acceptable [http://localhost/categories.js]
</pre>

Can anyone see something going on?


37. Kieran May 01, 2008 at 12:40

From your log: "[http://localhost/categories.js]"

It would seem Rails is trying to load from port 80 (default for apache), not port 3000 (default for rails).

Furthermore, I believe categories are stored in {RAILS_ROOT}/public/javascripts/categories.js, not {RAILS_ROOT}/public/category.js where is appears you are trying to find it.

Can you post some of your code?


38. Stephen Tudor May 02, 2008 at 12:44

This is great. Thanks Ryan for an excellent screencast, and congrats on breaking 100 episodes.

I'm a bit confused with how to get this process to work with a model that relies on virtual attributes.

For example, I have a Person with :first_name and :last_name attributes, and I use a virtual attribute :name as a shortcut to concatenate them and make it easier to search.

Unfortunately, find_by_name and its dynamic cousins don't exist because in this case, :name is a virtual attribute of Person.


39. Tim Cooper May 03, 2008 at 00:37

I was able to figure out what was happening before with the field not auto completing.. but now I'm having another problem.

When I hit the save button the category id isn't being stored in the product database.

the log says that category_name gets passed as a parameter but the relationship isn't saved - a new product is created with a NULL in category_id and a new category is created with a category_name.

Any ideas?


40. flaubert May 07, 2008 at 07:56

it possible to create more than only one attr_accessor ?? In my case, the "Category equivalent model", has 4 fields.


41. Lucas HĂșngaro May 16, 2008 at 13:13

I know it sounds a bit purist, but using virtual attributes this way you're tightening your model with the view, aren't you?

Besides that, how can I pass two or more parameters in the ajax request with the :param_name option? I got it working with the :with option, but that is a bit ugly.


42. Avishai May 23, 2008 at 09:30

Great screencast... I was trying to get this to work for days and this made it really easy.

I want to take it a step further though, and allow people to enter the name, but actually save the ID of the found object back into the database, which would be useful when adding existing items to a list. I've gotten the results back as JSON, but now I'm wondering how to actually take them and create the list from the JSON rather than an HTML ul.

Does anybody know?


43. rawdd May 25, 2008 at 10:57

auto-complete. oh yes, this good!
but if i have 100 users on-line, this very-very slowly


44. frank May 26, 2008 at 01:10

I tried the autocompletion exactly like the screencast and it works perfectly ....except for safari ( 3.1.1) in production mode. I get no requests at all when typing in the autocomplete field.

It does work in development mode and it works in production mode for firefox, IE6 en IE7.

Any ideas ...?


45. Luiz Carvalho Jun 10, 2008 at 05:01

Very Good!
tnks!


46. Jason FS Jun 20, 2008 at 08:01

Dear Rayn (and Tim Cooper).

Thanks for the work you put into this is helps a lot.

I am having the same problems as tim (i.e. the category id is not being saved into the product model).

any ideas what this might be?


47. jc Jun 29, 2008 at 18:30

This is a really good example, but it is now more easily accomplished with model_auto_completer:

http://agilewebdevelopment.com/plugins/model_auto_completer


48. Jeffrey Lee Jul 11, 2008 at 10:36

I'm attempting to use the auto-complete field to match related records that have a first_name and last_name field. In the profile model I've defined a full_name method that pairs the names: "#{self.first_name} #{self.last_name}"

I'm not sure if that is the proper way to accomplish what I need.

I've replaced all instances of name with full_name which is not working.

The virtual attributes in my other model are as follows:

def profile_name
profile.full_name if profile
end

def profile_name=(full_name)
self.profile=Profile.find_by_full_name(full_name) unless full_name.blank?
end

Now I know that the find_by_full_name is not correct,


49. Jeffrey Lee Jul 11, 2008 at 10:38

Sorry, submitted the form before I was finished.

but I cannot seem to figure out how to combine the fields for use with auto-complete. I don't care if I'm searching on "first_name OR last_name OR (first_name AND last_name)" or something similar but it would be nice to use the full name.


50. bijou Jul 24, 2008 at 01:20

hi Ryan! this was beautiful!
anwyay, i tried it on barebones projects and it worked! (only after i realized/overlooked a stupid mistake).

um, anyway, i was hoping i could incorporate it with your complex forms projects (episodes 73-75) and i tried and..... i can't get it to work. no matter how hard i squeezed my brain i can't seem to find the answer anywhere. i can't seem to make it cooperate with the "fields_for" method :(
the problem is that "text_field_with_auto_complete" doesn't seem to recognize for example, "auto_complete_field" of
<% fields_for "student[class_record_attributes][]" do |auto_complete_field| %>
when i use it like this:
<%= text_field_with_auto_complete :auto_complete_field, ...

any ideas? @_@


51. Peter Jul 25, 2008 at 12:19

@bijou
I'm also trying to incorporate auto-complete with a similar setup to the one introduced in Complex Forms 1-3.

Anyone have any tips?


52. bijou Jul 27, 2008 at 21:06

@Peter

i'm trying.... i tried to get it to work with text_field_tag, because in Ryan's example in this episode, it was used with the object-related text_field. i've put off using auto_complete for now. i need to finish other priorities for a project first before i go back to this... should i go back to this.


53. JDJ Jul 29, 2008 at 17:39

@ bijou and Peter

Just throwing in my chips to let you know I'm also trying to get text_field_with_auto_complete to work sensibly with fields_for.

However, unlike the Complex Forms 1-3 Railscasts, I'm not injecting fields_for with virtual attributes.

I'll post here if I can come up with a solution that isn't too embarrassing.


54. Eric Jul 30, 2008 at 12:10

Is there a way to modify what is displayed in the <li> that is produced? For instance, if I was autocompleting a Name field, searching by lastname only, so I'm doing something like this:

<%= auto_complete_result @user, :lastname %>

Is there a way to display both the firstname and lastname in the <li> that is produced?

I've tried having my format.js respond by calling a partial which contains both the firstname and lastname, and it displays properly when I trigger the autocomplelte, but then when I submit the form, both the firstname and lastname get injected into my :lastname field


55. Isaac Holmlund Aug 20, 2008 at 08:52

Is there a way to place many of these auto complete fields on one page? When I dynamically add more of these elements to my page (I need N topics with descriptions) the other auto complete fields don't work, I suspect because the div IDs are the same. Do you know of a way to fix this?


56. quatromil Aug 20, 2008 at 13:45

Hi, i followed the steps about the auto_complete and it works great!
but i need to add N more textfields with auto_complete in the same form (for example Complex Forms),
and i don't know how to do it, can you give me a hand with this? :(


57. Alex Aug 21, 2008 at 20:34

Hi,

i want to get the same effect with that auto_complete text field, but using class instead id, is that possible?


58. Mike Aug 22, 2008 at 03:37

Same Problem for me getting autocomplete to work with fields_for.

If anyone would get that to work I would appreciate a small hint on this thread :P

regards


59. Friseur Aug 30, 2008 at 01:52

Excellent. I've been searching for this for a long time. Thanks, Ryan!


60. Sri Sep 11, 2008 at 03:25

Hi Ryan ,
all goes fine, but the up/down arrow keys were not working in IE when selecting the items in dropdown

thanks


61. Urlaub Bayern Sep 16, 2008 at 21:10

thnak you Ryan for the fantastic resource.
Greets Urlaub Bayern


62. Richard Scott Sep 30, 2008 at 07:03

i am a rewbie,
i am having trouble getting this to work, i get a
"wrong number of arguments (0 for 1)"
is there anyway to download the example files for this video? thanks for the videos, I look foward to getting this to work :)


63. Event Locations Oct 10, 2008 at 14:04

Hi Ryan, your tutorial has just saved me a few hours of searching. Thanks a lot and best wishes from Germany!


64. Anderson Oct 15, 2008 at 09:18

Hi Ryan!
I tried to make your example work, but when i load the form, the text_field_with_auto_complete don't load the virtual attribute! Any ideas?!


65. Brian Oct 17, 2008 at 21:05

for some reason I'm getting the following routes-related error: formatted_piece_url failed to generate from {:controller=>"piece", :action=>"show", :id=>:js}, expected: {:controller=>"piece", :action=>"show"}, diff: {:id=>:js}
Any idea why it keeps wanting to use the show action? I can't seem to figure how to get the route to go to the index action. My code here is just formatted_piece_url(:js). Can't seem to get this working until the routes are working, but everything else from the video is working fine! Any help?


66. Erez Ben Shoham Oct 21, 2008 at 09:29

If you get the "wrong number of arguments (0 for 1)" Error?
Add * to
def category_name(*name)
and the error will disappear

Thank you Ryan! for your efforts

Erez


67. Erez Ben Shoham Oct 21, 2008 at 09:50

Or don't forget the =
def category_name=(name)


68. Mike Nov 19, 2008 at 14:10

how does this work if my model only has a unique ID column? the "name" is not unique.


69. Pat Dec 01, 2008 at 20:20

Sorry if this discussion is very old by now... with regard to @bijou, @peter, @mike, etc.: I wrote a plugin recently that allows you to use text_field_with_auto_complete with fields_for so that it can be repeated multiple times in a single form.

See: http://github.com/pat11639/repeated_auto_complete

Hope this helps someone!


70. Satynos Dec 22, 2008 at 10:31

How can we add additional fields to the category object on the fly?

I mean if if the category doesn't exist based on the info that user typed in the autocompleter field, I would like to show Category form with name and description fields in place of autocompleter field and the category name should be prepopulated with the value that the user entered in the autocompleter field. Once the product is submitted along with the category name and description information, product should be either created/saved with category assigned to it.

Would appreciate it if somebody could point me to any existing resource that achieves this functionality. Thanks in advance.

-Satynos


71. Val Dec 30, 2008 at 15:12

I must say, that Pat's solution for multiple fields is really cool!


72. Noah - Familienrecht Rechtsanwalt Stuttgart Jan 13, 2009 at 00:56

Thank you for this detailed information, it is done well.


73. Sigfrid Jan 20, 2009 at 18:34

Hello Ryan and guys,
I'm trying to integrate auto_complete feature with complex form (ep. #74) using repeated_auto_complete plug-in but looks like only the first field works.
Does anyone have successfully integrated dynamic fields with auto_completion ?

THANKS


74. Pat Jan 29, 2009 at 17:57

Just a quick note: the link I pasted just above no longer works; for a modified auto_complete plugin that works in a complex form see:

http://patshaughnessy.net/repeated_auto_complete

I also posted a sample app showing how to use auto_complete for repeated fields, and fixed Sigfrid's issue as well.


75. Martin Feb 17, 2009 at 22:41

When using Rails 2.3 it seems like the respond_to format.js is rendered with the application layout. Anyone that know why?


76. Miklos Feb 24, 2009 at 13:41

I'm very interested of finding a solution to the problem that Stephen Tudor describes in comment 39


77. PhilCK Mar 03, 2009 at 05:29

@Martin.

I got round this problem with the respond_to block.

I added it at the end and specified that the .js format would have no layout :layout => false


78. LRaiz Mar 13, 2009 at 15:31

@Martin
I run into the same issue using rails 2.2.2

@PhilCK
Your solution worked for me as well


79. srboisvert Mar 18, 2009 at 03:56

How do you solve the 406 Not Acceptable [http://localhost/journals.js?search=Ab] error? I assume is some sort of routing problem.


80. Juergen Apr 17, 2009 at 01:28

Hi!

I work on a web application where I have sucessfully implemented this cool behavior.

Thanks Ryan!!!

BUT: I use this auto completion feature on a text field that queries a table with almost 4000 records ( an extensive list of restriction enzymes). The drop down menu goes way off screen at the bottom if the user only types in a single common letter.
I suppose I could limit the number of returned search results but that would possibly prevent the user from finding the correct value.
Is there a way to introduce a scroll bar to the drop down menu?

Cheers Juergen


81. Nitin Apr 17, 2009 at 04:43

Hi @Ryan,

A breakthrough functionality I got working for myself in a jiffy. Many thanks for your railcasts...

I am using auto_complete on a search field which auto completes a list of tag.names and company.names for Company model. And it is returning for me a collected list of matching Company or Tag names for the search string.

BUT when i select one value from the Autocomplete list, previous string in the autocomplete text-field gets vanished and the selected word takes over.

What if I need multi word values to be submitted in that search field with commas between them ?
like "Comment, Private, Nitin"

And I also got the autocomplete to work after putting a comma..

Help!
Nitin R


82. Gonzo Apr 20, 2009 at 11:40

Hi Ryan,
Thanks so much for the screencast - It was a massive help.

Recently i refactored my db, and changed the relationship between my 'product' and 'category' from has_many to has_many :through, using the second example in your 'two many-to-many' screencast.

I'm now having trouble getting my app top work - wondered if you had any ideas?

I get an "undefined local variable or method `category' for #<product:0x4cdca2c>"

Thanks a million,
Gonzo


83. GreenPlastik Apr 20, 2009 at 22:28

Hi Ryan:
Wonderful episode. I seem to have uncovered a minor glitch. Perhaps it only happens in my app but I wanted to make sure.

Let's say you create a product with a category. Then you try to edit the product and empty the category field and hit 'Submit'. The product will be saved but will still show the previously stored category.

This may be the case for me because I used your nifty_generator scaffold to set things up. Any ideas?


84. Kevin Monk Apr 27, 2009 at 07:07

@Eric in post 55.

If you're wishing to have the list return virtual atributes such as full_name rather than a field such as surname of first_name then I found I had to modify the auto_complete_macros_helper.rb file

I modified it so that it sent the method rather than retrieved the field name. I changed line 98 to

items = entries.map { |entry| content_tag("li", phrase ? highlight(entry.send(field), phrase) : h(entry.send(field))) }

THis allowed me to access virtual attributes.

@Juergen post 82. I manage to get the autocomplete working nicely with Thinking_Sphinx. Here's my auto-complete-search:

www.crystalpalacelocal.co.uk

If you search for your enzymes this way then you can limit the number of results back but have the most relevant higher up the list depending upon your search weighting factors.

Hope this helps.

Thanks Ryan for the screencast. Yet again I owe you more than one beer for all this.


85. Tyler Gannon May 15, 2009 at 14:19

I'm still a bit of a newbie I guess because there are lots of surprises for me in rails development. Anyways wanted to mention that in order to get this to work I had to add a new layout called categories.js.erb, which was empty except for the yield tag. Otherwise when I went to localhost/categories.js the file would get run through the same layout as the html views, which is obviously unwanted. If there's a way around that I would appreciate the update.

thanks for the helpful info Ryan!


86. acroitor May 22, 2009 at 14:58

for those who were asking how to pass id instead of name because there are many situation where you cannot find a unique entity by name, here is the trick i have used make it work for me.

http://pastie.org/486924

Hope that helps.


87. Sazima May 23, 2009 at 15:16

Hey Ryan!

You don't even need to create the :js output for the category index action, you can use the native method (auto_complete_for :category, :name) provided by the plugin by using the :url parameter of the view helper:

:url => url_for(:controller => :categories, :action => :auto_complete_for_category_name, :escape => false)

Cheers, Sazima


88. Jens Mutschke Jun 07, 2009 at 04:38

works fine for me by setting the correct route in routes.rb.

sample:

map.tags '/tags/:js', :controller => 'tags', :action => 'index'

(tags are what categories are in the example above)

Greets, Jens


89. muntasir muneer Jun 23, 2009 at 14:36

As usual, gr8 work!!
Is it possible for you to do an episode on in_place_editor? It looks like they have a plugin for it, but none of them have a good documentation.

Thanks and keep up the good work.

Muntasir


90. bran Jul 29, 2009 at 00:37

Hey all, I'm having a bit of problem with this thing returning the data into the intended <div> no problem. However the actual div never becomes visible.

I'm using Rails 2.3.3 and Ruby 1.9.1. I have prototype and effect.js loaded.


91. bran Jul 29, 2009 at 13:04

I figured it out.

In Ruby 1.9, the to_s member of arrays changed. (So did the default functionality of spitting out an array directly).

You need to add .join to the end of of items.uniq in the autocompletehelper.rb.

As in "items.uniq.join" instead of just "items.uniq", so search and replace that you'll be fine.


92. John McLeod Aug 13, 2009 at 08:25

Ryan,
Great screencast. I'm having problems though. Instead of categories I'm using departments. I'm also using NetBeans 6.7 for my IDE. Everything is going great until I load the edit page, then in the NetBeans Console is an error:

DEPRECATION WARNING: formatted_departments_path() has been deprecated. Please pass format to the standard departments_path method instead..

I'm not sure where to go from here.
John M


93. Steven Oct 21, 2009 at 19:38

Great podcast, Ryan. I was wondering why this wouldn't work if the Product model has a has_one association to the Category model and the Category model has a belongs_to to the Product.

I've tested both ways and It works the way you have it, but was just curious if you knew why this other way would not work.


94. Judd Nov 09, 2009 at 16:39

Thanks Ryan! I'm a big fan of Railscasts.

I'm running into a snag. http://localhost:3000/companies.js is not rendering the html as expected and has <li> and <ul> take in it. When I look at the source with firebug, I see <pre> tags are included in the output. I'm new to this, and think there may be an easy fix or obvious oversight.

Any help is greatly appreciated!


95. Mike Wicks Nov 16, 2009 at 05:46

@92 John McLeod

To get rid of the Deprecation Warning, I think you need do this:

Change THIS

:url => formatted_..._path(:js) ..

to THIS

:url => ... _path(:format => :js) ..

(FYI I'm running Rails 2.3.4)

Ryan - Superb Web resource you've got here! Well Done - My first port of call when I get stuck developing my Apps. Keep up the good work :-)


96. Justin Zollars Nov 23, 2009 at 22:36

This works Great...

Until I try to edit a record with a Category assigned. In my case the system produces a "SystemStackError in Inventories#edit" stack level too deep

I'm using this code: <%= text_field_with_auto_complete :inventory, :tag_name, { :size => 15 }, { :url => formatted_tags_path(:js), :method => :get, :param_name => 'search' } %>

It works with unpopulated data in create and edit, it does not edit existing data and always produces the Stack level too deep message

Anyone else having this problem?


97. Svend Gundestrup Nov 28, 2009 at 03:00

tried http://pastie.org/184873 (unable to get it to work)

Problem:
I am trying to use autocomplate, for the nested/parent resource places, when creating an shift.

If the place exsists, it works
if the create action is called, I get the error:

error:
Mysql::Error: Column 'user_id' cannot be null: INSERT INTO `places` (`name`, `created_at`, `updated_at`, `user_id`) VALUES('Herlevvidovre', '2009-11-28 10:42:48', '2009-11-28 10:42:48', NULL)

My setup:
map.resources :users do |users|
    users.resources :pays
    users.resources :places
    users.resources :shifts do |shifts|
      shifts.resources :payroles
    end
  end

model:
def place_name
    place.name if place
  end
  

  def place_name=(name)
    self.place = Place.find_or_create_by_name(name, @user) unless name.blank?
  end

places controller:
index:
@places = @user.places.find(:all, :conditions => ['name LIKE ?', "%#{params[:search]}%"])

create:
@place = @user.places.build(params[:place])

shift form view:
<%= text_field_with_auto_complete :shift, :place_name, { :size => 15 }, { :url => formatted_user_places_path(@user, :js), :method => :get, :param_name => 'search' } %>


98. cece Dec 08, 2009 at 19:59

can cascading select be implemented using auto_complete.

i mean, i have country and state fields and i want auto_complete options to show from state field based on the value of country field.

is it possible?

thanks in advance


99. Libby Dec 11, 2009 at 20:37

How did you all solve the 406 Not Acceptable error? I see that others have it but haven't figured out how to fix it. Thanks!


100. AleBoi Dec 13, 2009 at 18:59

@106 Libby
Try to add the following line to the respond_to method in your controller:

format.js {render :html=>@your_collection_of_DB_results}

It fixed similar issue for me.

BTW, I started experiencing this problem as soon as I updated the gems on my PC. A bit embarrassing.


101. Libby Dec 14, 2009 at 19:55

@AleBoi Thanks! That plus Pat's fields_for fork fixed all my issues. Thanks for your help all


102. Ben Holland Jan 04, 2010 at 10:41

Hi there, thought I might try to contribute something.

I followed this screencast and then tried to upload my project to my heroku (these guys rock!!) hosting which uses postsql databases. I found that the search was only return case sensitive results instead of case insensitive results, so I dug into it and on PostSQL you can just replace the LIKE with ILIKE in your controllers query for the same results.


103. Ben Holland Jan 04, 2010 at 10:46

Also a note on CSS styling.

You can override the inline css styling if you want more control over the popup form by adding :skip_style => true

<%= text_field_with_auto_complete :product, :category_name, {:size => 30}, {:skip_style => true, :url => formatted_categories_path(:js), :method => :get, :param_name => 'search' } %>

/* Autocomplete Popup Styling, Notice I changed the color of li.selected to red? */
div.auto_complete {
width: 350px;
background: #fff;
}

div.auto_complete ul {
border:1px solid #888;
margin:0;
padding:0;
width:100%;
list-style-type:none;
}

div.auto_complete ul li {
margin:0;
padding:3px;
}

div.auto_complete ul li.selected {
background-color: #990404;
}

div.auto_complete ul strong.highlight {
color: #800;
margin:0;
padding:0;
}


104. Bruno Jan 06, 2010 at 10:56

Hello all, and thanks Ryan for your great work with these episodes. I've managed to make that work, but slightly modified to work with jQuery.

There's a little trap when using virtual attributes in a way like this

  def document_name=(name)
    self.document = Document.find_by_name(name)
  end

In face, Model.find_or_create_by_name() is handy, but when you pass no name, no Model is being created by ActiveRecord. Though, self.document = XX is still being affected, and a Document object is thought to be present in the parent model. But, in this case, XX is empty (no Document found, and no Document saved to the database yet), thus XX.id is not present, and that leads to strange behaviors as the XX Document is not a "classic Document". Calling document_path(parent_model.document) immediately after the parent_model update or save, causes crashes. Immediately after means, in the partial I'm trying to generate for the response to the browser, in my AJAX context.

I hope my explanation was not too messy to be understood.


106. Steven Jan 13, 2010 at 14:41

I had the hardest time figuring out why I couldn't get any of the Javascript to run. I finally got it to work by restarting the server after issuing the

script/plugin install git://github.com/rails/auto_complete.git


106. wholesale nike shoes Jan 13, 2010 at 23:24

A very good article, I will always come in.


107. fashion scarves Jan 13, 2010 at 23:24

Such a good article, caught my sympathy!
-


108. Tyler Gannon Jan 14, 2010 at 21:39

Ryan, thanks a bunch for this. It's been such a great help. One question: I am running into trouble when my associated entity already has an index.html action. Can you please tell me how to inform the controller of how to discriminate between index.html and index.js?

thank you!


109. pduersteler Feb 17, 2010 at 09:48

Nice Thing, but it find_or_create_by won't work when you have validations on your category model for additional fields.

I tried to prefill them also, but accessing attributes from the form won't work.Creating a virtual attribute was no solution because then i would need to enter information twice.


110. Chris Feb 25, 2010 at 21:31

Is it just me... or when I double-click on one of the resulting values, I get the values twice in the text field, sometimes half of the 2nd one ?!?! Weird!

Chris


111. kamagra Feb 26, 2010 at 11:40

good read thanks for the share.


112. m65 field jacket Feb 26, 2010 at 11:40

nice article


113. nike air max Mar 05, 2010 at 16:28

good read thanks for the share


114. Louis Vuitton handbags Mar 09, 2010 at 18:07

railscasts.com/episodes/102-auto-complete-association

Add your comment:

(SKIP THIS ONE)

(required)

(not shown)


(use pastie or gist for code)

sponsored by:
if you want to help:
required:
Get Quicktime Player
Give Back to Open Source