diff --git a/lib/assets/javascripts/autocomplete-rails-uncompressed.js b/lib/assets/javascripts/autocomplete-rails-uncompressed.js
index e844c159..a1456008 100644
--- a/lib/assets/javascripts/autocomplete-rails-uncompressed.js
+++ b/lib/assets/javascripts/autocomplete-rails-uncompressed.js
@@ -48,12 +48,22 @@ $(document).ready(function(){
       function extractLast( term ) {
         return split( term ).pop().replace(/^\s+/,"");
       }
+      function bindClearId() {
+        var remember_string = this.value;
+        $(this).bind('keyup.clearId', function(){
+          if($(this).val().trim() != remember_string.trim()){
+            $($(this).attr('data-id-element')).val("").change();
+            $(this).unbind('keyup.clearId');
+          }
+        });
+      }
 
       $(e).autocomplete({
         source: function( request, response ) {
-          $.getJSON( $(e).attr('data-autocomplete'), {
-            term: extractLast( request.term )
-          }, function() {
+          var data = { term: extractLast( request.term ) };
+          var extraData = $(e).triggerHandler('railsAutocomplete.source', data);
+          data = extraData ? extraData : data;
+          $.getJSON( $(e).attr('data-autocomplete'), data, function() {
             $(arguments[0]).each(function(i, el) {
               var obj = {};
               obj[el.id] = el;
@@ -73,6 +83,9 @@ $(document).ready(function(){
           // prevent value inserted on focus
           return false;
         },
+        create: function() {
+          bindClearId.call(this);
+        },
         select: function( event, ui ) {
           var terms = split( this.value );
           // remove the current input
@@ -86,7 +99,7 @@ $(document).ready(function(){
           } else {
             this.value = terms.join("");
             if ($(this).attr('data-id-element')) {
-              $($(this).attr('data-id-element')).val(ui.item.id);
+              $($(this).attr('data-id-element')).val(ui.item.id).change();
             }
             if ($(this).attr('data-update-elements')) {
               var data = $(this).data(ui.item.id.toString());
@@ -96,13 +109,7 @@ $(document).ready(function(){
               }
             }
           }
-          var remember_string = this.value;
-          $(this).bind('keyup.clearId', function(){
-            if($(this).val().trim() != remember_string.trim()){
-              $($(this).attr('data-id-element')).val("");
-              $(this).unbind('keyup.clearId');
-            }
-          });
+          bindClearId.call(this);
           $(this).trigger('railsAutocomplete.select', ui);
 
           return false;
diff --git a/lib/assets/javascripts/autocomplete-rails.js b/lib/assets/javascripts/autocomplete-rails.js
index 2e0bfdbd..9785f250 100644
--- a/lib/assets/javascripts/autocomplete-rails.js
+++ b/lib/assets/javascripts/autocomplete-rails.js
@@ -13,4 +13,4 @@
 *   Example:
 *       <input type="text" data-autocomplete="/url/to/autocomplete" data-id-element="#id_field">
 */
-$(document).ready(function(){$("input[data-autocomplete]").railsAutocomplete()}),function(a){var b=null;a.fn.railsAutocomplete=function(){return this.live("focus",function(){this.railsAutoCompleter||(this.railsAutoCompleter=new a.railsAutocomplete(this))})},a.railsAutocomplete=function(a){_e=a,this.init(_e)},a.railsAutocomplete.fn=a.railsAutocomplete.prototype={railsAutocomplete:"0.0.1"},a.railsAutocomplete.fn.extend=a.railsAutocomplete.extend=a.extend,a.railsAutocomplete.fn.extend({init:function(a){function b(b){return b.split(a.delimiter)}function c(a){return b(a).pop().replace(/^\s+/,"")}a.delimiter=$(a).attr("data-delimiter")||null,$(a).autocomplete({source:function(b,d){$.getJSON($(a).attr("data-autocomplete"),{term:c(b.term)},function(){$(arguments[0]).each(function(b,c){var d={};d[c.id]=c,$(a).data(d)}),d.apply(null,arguments)})},search:function(){var a=c(this.value);if(a.length<2)return!1},focus:function(){return!1},select:function(c,d){var f=b(this.value);f.pop(),f.push(d.item.value);if(a.delimiter!=null)f.push(""),this.value=f.join(a.delimiter);else{this.value=f.join(""),$(this).attr("data-id-element")&&$($(this).attr("data-id-element")).val(d.item.id);if($(this).attr("data-update-elements")){var g=$(this).data(d.item.id.toString()),h=$.parseJSON($(this).attr("data-update-elements"));for(var i in h)$(h[i]).val(g[i])}}var j=this.value;return $(this).bind("keyup.clearId",function(){$(this).val().trim()!=j.trim()&&($($(this).attr("data-id-element")).val(""),$(this).unbind("keyup.clearId"))}),$(this).trigger("railsAutocomplete.select",d),!1}})}})}(jQuery)
\ No newline at end of file
+$(document).ready(function(){$("input[data-autocomplete]").railsAutocomplete()}),function(a){var b=null;a.fn.railsAutocomplete=function(){return this.live("focus",function(){this.railsAutoCompleter||(this.railsAutoCompleter=new a.railsAutocomplete(this))})},a.railsAutocomplete=function(a){_e=a,this.init(_e)},a.railsAutocomplete.fn=a.railsAutocomplete.prototype={railsAutocomplete:"0.0.1"},a.railsAutocomplete.fn.extend=a.railsAutocomplete.extend=a.extend,a.railsAutocomplete.fn.extend({init:function(a){function b(b){return b.split(a.delimiter)}function c(a){return b(a).pop().replace(/^\s+/,"")}function d(){var a=this.value;$(this).bind("keyup.clearId",function(){$(this).val().trim()!=a.trim()&&($($(this).attr("data-id-element")).val("").change(),$(this).unbind("keyup.clearId"))})}a.delimiter=$(a).attr("data-delimiter")||null,$(a).autocomplete({source:function(b,d){var f={term:c(b.term)},g=$(a).triggerHandler("railsAutocomplete.source",f);f=g?g:f,$.getJSON($(a).attr("data-autocomplete"),f,function(){$(arguments[0]).each(function(b,c){var d={};d[c.id]=c,$(a).data(d)}),d.apply(null,arguments)})},search:function(){var a=c(this.value);if(a.length<2)return!1},focus:function(){return!1},create:function(){d.call(this)},select:function(c,f){var g=b(this.value);g.pop(),g.push(f.item.value);if(a.delimiter!=null)g.push(""),this.value=g.join(a.delimiter);else{this.value=g.join(""),$(this).attr("data-id-element")&&$($(this).attr("data-id-element")).val(f.item.id).change();if($(this).attr("data-update-elements")){var h=$(this).data(f.item.id.toString()),i=$.parseJSON($(this).attr("data-update-elements"));for(var j in i)$(i[j]).val(h[j])}}return d.call(this),$(this).trigger("railsAutocomplete.select",f),!1}})}})}(jQuery)
\ No newline at end of file
diff --git a/lib/rails3-jquery-autocomplete/autocomplete.rb b/lib/rails3-jquery-autocomplete/autocomplete.rb
index fefc9146..ca5a5305 100644
--- a/lib/rails3-jquery-autocomplete/autocomplete.rb
+++ b/lib/rails3-jquery-autocomplete/autocomplete.rb
@@ -42,22 +42,30 @@ def self.included(target)
     #
     module ClassMethods
       def autocomplete(object, method, options = {})
-        define_method("autocomplete_#{object}_#{method}") do
+        define_method(options[:action_name] ||
+                      "autocomplete_#{object}_#{method}") do
 
           method = options[:column_name] if options.has_key?(:column_name)
 
           term = params[:term]
 
+          # allow specifying fully qualified class name for model object
+          class_name = options[:class_name] || object
+          parameters = {
+            :model      => get_object(class_name),
+            :controller => self,
+            :term       => term,
+            :method     => method,
+            :options    => options
+          }
+
           if term && !term.blank?
-            #allow specifying fully qualified class name for model object
-            class_name = options[:class_name] || object
-            items = get_autocomplete_items(:model => get_object(class_name), \
-              :options => options, :term => term, :method => method)
+            items = get_autocomplete_items(parameters)
           else
             items = {}
           end
 
-          render :json => json_for_autocomplete(items, options[:display_value] ||= method, options[:extra_data])
+          render :json => json_for_autocomplete(items, parameters)
         end
       end
     end
@@ -81,11 +89,24 @@ def get_object(model_sym)
     # Can be overriden to show whatever you like
     # Hash also includes a key/value pair for each method in extra_data
     #
-    def json_for_autocomplete(items, method, extra_data=[])
+    def json_for_autocomplete(items, parameters)
+      display_value = parameters[:options][:display_value] ||= parameters[:method]
+      label         = parameters[:options][:label]         ||= parameters[:method]
+      extra_data    = parameters[:options][:extra_data]
+
       items.collect do |item|
-        hash = {"id" => item.id.to_s, "label" => item.send(method), "value" => item.send(method)}
-        extra_data.each do |datum|
-          hash[datum] = item.send(datum)
+        hash = {
+          "id" => item.id.to_s,
+          "label" => item.send(label),
+          "value" => item.send(display_value)
+        }
+
+        extra_data.each do |k, v|
+          if v
+            hash[k] = v.is_a?(Proc) ? v.call(item, parameters) : item.send(v)
+          else
+            hash[k] = item.send(k)
+          end
         end if extra_data
         # TODO: Come back to remove this if clause when test suite is better
         hash
diff --git a/lib/rails3-jquery-autocomplete/formtastic.rb b/lib/rails3-jquery-autocomplete/formtastic.rb
index 4fea6945..3c913c53 100644
--- a/lib/rails3-jquery-autocomplete/formtastic.rb
+++ b/lib/rails3-jquery-autocomplete/formtastic.rb
@@ -19,10 +19,28 @@ class AutocompleteInput
           include Base
           include Base::Stringish
 
+          def id_field_dom_id(method)
+            [ builder.custom_namespace,
+              sanitized_object_name,
+              dom_index,
+              method.to_s.gsub(/[\?\/\-]$/, '')
+            ].reject { |x| x.blank? }.join('_')
+          end
+
+          def input_html_options
+            if options[:id_field]
+              { :id_element => '#' + id_field_dom_id(options[:id_field])
+              }.merge(super)
+            else
+              super
+            end
+          end
+
           def to_html
             input_wrapping do
-              label_html <<
-              builder.autocomplete_field(method, options.delete(:url), input_html_options)
+              result = label_html <<
+                builder.autocomplete_field(method, options.delete(:url), input_html_options) <<
+                (options[:id_field] ? builder.hidden_field(options.delete :id_field) : '')
             end
           end
         end
diff --git a/lib/rails3-jquery-autocomplete/orm/active_record.rb b/lib/rails3-jquery-autocomplete/orm/active_record.rb
index e9260dd0..540ca48f 100644
--- a/lib/rails3-jquery-autocomplete/orm/active_record.rb
+++ b/lib/rails3-jquery-autocomplete/orm/active_record.rb
@@ -20,7 +20,13 @@ def get_autocomplete_items(parameters)
 
         items = model.scoped
 
-        scopes.each { |scope| items = items.send(scope) } unless scopes.empty?
+        scopes.each do |scope|
+          if scope.is_a? Proc
+            items = scope.call(items, parameters)
+          else
+            items = items.send(*Array(scope))
+          end
+        end unless scopes.empty?
 
         items = items.select(get_autocomplete_select_clause(model, method, options)) unless options[:full_model]
         items = items.where(get_autocomplete_where_clause(model, term, method, options)).
@@ -29,7 +35,15 @@ def get_autocomplete_items(parameters)
 
       def get_autocomplete_select_clause(model, method, options)
         table_name = model.table_name
-        (["#{table_name}.#{model.primary_key}", "#{table_name}.#{method}"] + (options[:extra_data].blank? ? [] : options[:extra_data]))
+        extra_columns =
+          if options[:extra_data].nil?
+            []
+          elsif options[:extra_data].is_a? Hash
+            options[:extra_data].keys
+          else
+            options[:extra_data]
+          end
+        (["#{table_name}.#{model.primary_key}", "#{table_name}.#{method}"] + extra_columns)
       end
 
       def get_autocomplete_where_clause(model, term, method, options)
diff --git a/test/lib/rails3-jquery-autocomplete/autocomplete_test.rb b/test/lib/rails3-jquery-autocomplete/autocomplete_test.rb
index 4630ce4f..050f1211 100644
--- a/test/lib/rails3-jquery-autocomplete/autocomplete_test.rb
+++ b/test/lib/rails3-jquery-autocomplete/autocomplete_test.rb
@@ -29,29 +29,76 @@ class AutocompleteTest < Test::Unit::TestCase
 
     context '#json_for_autocomplete' do
       should 'parse items to JSON' do
-        item = mock(Object)
-        mock(item).send(:name).times(2) { 'Object Name' }
-        mock(item).id { 1 }
-        items    = [item]
-        response = self.json_for_autocomplete(items, :name).first
+        item = generate_mocked_model_instance
+
+        parameters = { :method => :name, :options => {} }
+        items      = [item]
+        response   = self.json_for_autocomplete(items, parameters).first
+
         assert_equal response["id"], "1"
         assert_equal response["value"], "Object Name"
         assert_equal response["label"], "Object Name"
       end
 
-      context 'with extra data' do
+      context 'with extra data as an Array' do
         should 'add that extra data to result' do
-          item = mock(Object)
-          mock(item).send(:name).times(2) { 'Object Name' }
-          mock(item).id { 1 }
-          mock(item).send("extra") { 'Object Extra ' }
+          item = generate_mocked_model_instance
+          mock(item).send("extra") { 'Object Extra' }
+
+          parameters = { :method => :name, :options => { :extra_data => ["extra"] } }
+          items      = [item]
+          response   = self.json_for_autocomplete(items, parameters).first
+
+          assert_equal "1"            , response["id"]
+          assert_equal "Object Name"  , response["value"]
+          assert_equal "Object Name"  , response["label"]
+          assert_equal "Object Extra" , response["extra"]
+        end
+      end
+
+      context 'with extra data as a Hash' do
+        context 'having lambdas as values' do
+          should 'add that extra data to result' do
+            item = generate_mocked_model_instance
+
+            parameters = {
+              :method => :name,
+              :options => {
+                :extra_data => {
+                  "extra" => lambda { |item, parameters| 'Lambda Extra' }
+                }
+              }
+            }
+            items    = [item]
+            response = self.json_for_autocomplete(items, parameters).first
+
+            assert_equal "1"            , response["id"]
+            assert_equal "Object Name"  , response["value"]
+            assert_equal "Object Name"  , response["label"]
+            assert_equal "Lambda Extra" , response["extra"]
+          end
+        end
+
+        context 'having non-lambdas as values' do
+          should 'add that extra data to result' do
+            item = generate_mocked_model_instance
+            mock(item).send("exxtra") { 'Object Exxtra' }
 
-          items    = [item]
-          response = self.json_for_autocomplete(items, :name, ["extra"]).first
+            parameters = {
+              :method => :name,
+              :options => { :extra_data => {
+                  "extra" => "exxtra"
+                }
+              }
+            }
+            items    = [item]
+            response = self.json_for_autocomplete(items, parameters).first
 
-          assert_equal "1"           , response["id"]
-          assert_equal "Object Name" , response["value"]
-          assert_equal "Object Name" , response["label"]
+            assert_equal "1"             , response["id"]
+            assert_equal "Object Name"   , response["value"]
+            assert_equal "Object Name"   , response["label"]
+            assert_equal 'Object Exxtra' , response["extra"]
+          end
         end
       end
     end
diff --git a/test/lib/rails3-jquery-autocomplete_test.rb b/test/lib/rails3-jquery-autocomplete_test.rb
index 4ca11a8d..ad1034cf 100644
--- a/test/lib/rails3-jquery-autocomplete_test.rb
+++ b/test/lib/rails3-jquery-autocomplete_test.rb
@@ -12,6 +12,13 @@ class ::Movie ; end
         @controller = ActorsController.new
         @items = {}
         @options = { :display_value => :name }
+        @parameters = {
+          :term       => nil,
+          :model      => Movie,
+          :method     => :name,
+          :controller => @controller,
+          :options    => {}
+        }
       end
 
       should 'respond to the action' do
@@ -19,17 +26,15 @@ class ::Movie ; end
       end
 
       should 'render the JSON items' do
-        mock(@controller).get_autocomplete_items({
-          :model => Movie, :method => :name, :options => @options, :term => "query"
-        }) { @items }
-
-        mock(@controller).json_for_autocomplete(@items, :name, nil)
+        parameters = @parameters.merge(:term => "query")
+        mock(@controller).get_autocomplete_items(parameters) { @items }
+        mock(@controller).json_for_autocomplete(@items, parameters)
         get :autocomplete_movie_name, :term => 'query'
       end
 
       context 'no term is specified' do
         should "render an empty hash" do
-          mock(@controller).json_for_autocomplete({}, :name, nil)
+          mock(@controller).json_for_autocomplete({}, @parameters)
           get :autocomplete_movie_name
         end
       end
diff --git a/test/test_helper.rb b/test/test_helper.rb
index 47c50d4f..6b0ba7c6 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -27,5 +27,12 @@ class Application < ::Rails::Application
 
 class Test::Unit::TestCase
   include RR::Adapters::TestUnit
+
+  def generate_mocked_model_instance
+    item = mock(Object)
+    mock(item).send(:name).times(2) { 'Object Name' }
+    mock(item).id { 1 }
+    item
+  end
 end