Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 3 Autocomplete Across Multiple Models

So I found some great info on Autocomplete for Rails 3, it looks really easy to use. But I have a use case that doesnt fit and I need some advice.

I want to give the user the ability to add Products and Services to an Invoice through a simple form. I'd like them to be able to type into the Item field and have it autocomplete from both Product.name and Service.name as a single set.

I'm thinking of trying to write a parent model that overlays all three, but I still don't think that solves my problem since I can't use a function in the autocomplete definition from what I understand.

Any advice on how I might try to accomplish this? Even with the simple search examples that are out there they seem to be restricted to a single model.

like image 750
R. Yanchuleff Avatar asked Mar 05 '11 21:03

R. Yanchuleff


2 Answers

If you're not opposed to introducing Redis into the mix, have a look at https://github.com/seatgeek/soulmate -- From the README:

Soulmate is a tool to help solve the common problem of developing a fast autocomplete feature. It uses Redis's sorted sets to build an index of partially completed words and the corresponding top matching items, and provides a simple sinatra app to query them. Soulmate finishes your sentences.

Soulmate was designed to be simple and fast, and offers the following:

  • Provide suggestions for multiple types of items in a single query (at SeatGeek we're autocompleting for performers, events, and venues)
  • Results are ordered by a user-specified score
  • Arbitrary metadata for each item (at SeatGeek we're storing both a url and a subtitle)

An item is a simple JSON object that looks like:

{
  "id": 3,
  "term": "Citi Field",
  "score": 81,
  "data": {
    "url": "/citi-field-tickets/",
    "subtitle": "Flushing, NY"
  }
}

Where id is a unique identifier (within the specific type), term is the phrase you wish to provide completions for, score is a user-specified ranking metric (redis will order things lexicographically for items with the same score), and data is an optional container for metadata you'd like to return when this item is matched (at SeatGeek we're including a url for the item as well as a subtitle for when we present it in an autocomplete dropdown).

See Soulmate in action at SeatGeek.

If nothing else, maybe it'll give you some ideas on how to structure the data in a way that makes sense.

I did not write or have anything to do with soulmate. It's just a library I discovered when trying to solve a similar problem. Hope it helps!

like image 62
Josh Deeden Avatar answered Oct 10 '22 08:10

Josh Deeden


If client-side autocomplete is an option (e.g. you have few products and services), you could go with JQuery autocomplete:

controller:

@keys = @categories.map { |x| x.name } + @entries.map { |x| x.description }
@autocomplete_categories = @keys.to_json.html_safe

view:

<script type="text/javascript">
$(document).ready(function() {
    var data = <%= @autocomplete_categories %>;
    $("#auto").autocomplete( { source: data } );
});
</script>

<input type="text" name="auto" id="auto" />
like image 1
Markus Proske Avatar answered Oct 10 '22 09:10

Markus Proske