Autocomplete fields in Rails 3.1 with JQuery-UI pt. 2

As i have written in my previous post, i’m playing with autocompletion in my web app. I have found some new tricks, that will speed up the process. Never liked the find_by_name implementation, but as this example is derived from jquery.autocomplete plugin behavior, i had no other way. Did some more exploring today and here is what i found out.
Because you are using json response on the ajax controller, and JQuery-UI autocomplete handles it perfectly, you can create a hidden field, and put the user_id there, so you have one less request to the database whena you are saving your record.
The improved model:


class Post < ActiveRecord::Base belongs_to :user attr_accessor :user_name def user_name user.name if user_id end end [/ruby] And the part in your view that i left out the last time, but this one is just better in my opinion: [html] < %= f.label :user_name %>
< %= f.text_field :user_name %>
< %= f.hidden_field :user_id %>
[/html]
Also, you have to edit the CoffeScript that does the magic for you, so it will return the id into the hidden field:

$(document).ready ->
  $('#post_user_name').autocomplete
    source: "/ajax/users"
    select: (event,ui) ->
      $("#post_user_id").val(ui.item.id)

An easier way of doing it, and leaner on the database queries, at least one less.

Autocomplete fields in Rails 3.1 with JQuery-UI

Almost every time you create a web application you will have to add at least one autocomplete field in your application. Here is one of the possible ways of doing it. I will be using Rails 3.1.beta1, JQuery-UI and CoffeScript to make it happen.

I have two models in my app, post(title, body) and user(name, email) and i want to select user with autocomplete when creating the post. As a prerequisite, i have created 100 users with Faker gem.

First, you have to add JQuery-UI to your app/assets/javascripts/application.js file so it will look like this:


//= require jquery
//= require jquery-ui
//= require jquery_ujs
//= require_tree .

Next, we set up an ajax controller with rails g controller ajax users to have a controller with users action and automatic route. I like to call the controller ajax, or autocomplete, to keep things organized for this. Here is the ajax controller with everything just rendered into json that suits JQuery-UI autocomplete format


class AjaxController < ApplicationController
  def users
    if params[:term]
      like= "%".concat(params[:term].concat("%"))
      users = User.where("name like ?", like)
    else
      users = User.all
    end
    list = users.map {|u| Hash[ id: u.id, label: u.name, name: u.name]}
    render json: list
  end
end

Next we set up the post model with user_name attribute getter and setter


def user_name=(name)
  user = User.find_by_name(name)
  if user
    self.user_id = user.id
  else
    errors[:user_name] << "Invalid name entered"
  end
end
def user_name
  User.find(user_id).name if user_id
end

After this, it’s all CoffeScript which i add to app/assets/javascripts/application.js.coffee


$(document).ready ->
  $('#post_user_name').autocomplete({source: "/ajax/users"})

And that is everything needed for a nice autocomplete, be sure to include a suitable JQuery-UI theme in your vendor/assets/stylesheets folder.

Rails 3.1 beta on Ubuntu

As i have written before, i use Ubuntu for my rails development, and have been using it as my main OS last 10 months. I have been trying all the rails 3.1 beta hype and encountered a problem running 3.1 apps on my machine.

The main problem is with CoffeScript and its compiling into “real” JavaScript. So here is an easy way to enable your machine for rails 3.1. You have to install Node.js on your machine( i have tried all other Javascript runtimes with no luck). All the instructions for other platforms are listed on the project’s GitHub page, i will include only the ubuntu procedure here.


sudo apt-get install python-software-properties

sudo add-apt-repository ppa:jerome-etienne/neoip

sudo apt-get update

sudo apt-get install nodejs

And that is all, hope i have made your life easier at least a bit.