From 37c5807d8a866292026b7820eea499ac52dd1767 Mon Sep 17 00:00:00 2001 From: Michael Johnston Date: Thu, 4 Feb 2016 01:04:52 -0800 Subject: [PATCH 1/4] allow use of pluck instead of select this in conjunction with using a scope that joins an association allows fetching attributes of associated records. class Organization belongs_to :contact scope :with_contact, -> { joins(:contact) } end autocomplete :organization, :name, extra_data: ['contacts.email'], select_method: :pluck, scopes: [:with_contact] f.autocomplete_field :name, autocomplete_organization_name_product_path, update_elements: {id: '#products_organization_attributes_id', 'contacts.email': '#products_contact_attributes_email'} --- lib/rails-jquery-autocomplete/autocomplete.rb | 20 ++++++++++++------- .../orm/active_record.rb | 13 ++++++++++-- .../autocomplete_test.rb | 3 +++ 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/lib/rails-jquery-autocomplete/autocomplete.rb b/lib/rails-jquery-autocomplete/autocomplete.rb index 4905a75..1e649cb 100644 --- a/lib/rails-jquery-autocomplete/autocomplete.rb +++ b/lib/rails-jquery-autocomplete/autocomplete.rb @@ -97,13 +97,19 @@ def get_object(model_sym) # Hash also includes a key/value pair for each method in extra_data # def json_for_autocomplete(items, method, extra_data=[]) - items = items.collect do |item| - hash = HashWithIndifferentAccess.new({"id" => item.id.to_s, "label" => item.send(method), "value" => item.send(method)}) - extra_data.each do |datum| - hash[datum] = item.send(datum) - end if extra_data - # TODO: Come back to remove this if clause when test suite is better - hash + if items.first && items.first.kind_of?(Hash) + items.each do |item| + item['label'] = item['value'] = item[method.to_s] + end + else + items = items.collect do |item| + hash = HashWithIndifferentAccess.new({"id" => item.id.to_s, "label" => item.send(method), "value" => item.send(method)}) + extra_data.each do |datum| + hash[datum] = item.send(datum) + end if extra_data + # TODO: Come back to remove this if clause when test suite is better + hash + end end if block_given? yield(items) diff --git a/lib/rails-jquery-autocomplete/orm/active_record.rb b/lib/rails-jquery-autocomplete/orm/active_record.rb index 3754334..a8bba92 100644 --- a/lib/rails-jquery-autocomplete/orm/active_record.rb +++ b/lib/rails-jquery-autocomplete/orm/active_record.rb @@ -26,11 +26,20 @@ def active_record_get_autocomplete_items(parameters) scopes.each { |scope| items = items.send(scope) } unless scopes.empty? - items = items.select(get_autocomplete_select_clause(model, method, options)) unless options[:full_model] + select_method = options[:select_method] || :select + + if select_method == :select + items = items.select(get_autocomplete_select_clause(model, method, options)) unless options[:full_model] + end items = items.where(get_autocomplete_where_clause(model, term, method, options)). limit(limit).order(order) items = items.where(where) unless where.blank? - + if select_method == :pluck + columns = get_autocomplete_select_clause(model, method, options) + items = items.pluck(*columns) unless options[:full_model] + columns = columns.map{|column| column.sub(/^#{model.table_name}\./, '')} + items = items.map{|item| Hash[columns.zip(item)]} + end items end diff --git a/test/lib/rails-jquery-autocomplete/autocomplete_test.rb b/test/lib/rails-jquery-autocomplete/autocomplete_test.rb index 66c636c..f4205e0 100644 --- a/test/lib/rails-jquery-autocomplete/autocomplete_test.rb +++ b/test/lib/rails-jquery-autocomplete/autocomplete_test.rb @@ -54,6 +54,7 @@ class AutocompleteTest < Test::Unit::TestCase should 'parse items to JSON' do item = mock(Object) mock(item).send(:name).times(2) { 'Object Name' } + stub(item).kind_of?(Hash){ false } mock(item).id { 1 } items = [item] response = self.json_for_autocomplete(items, :name).first @@ -65,6 +66,7 @@ class AutocompleteTest < Test::Unit::TestCase should 'return an instance of HashWithIndifferentAccess' do item = mock(Object) mock(item).send(:name).times(2) { 'Object Name' } + stub(item).kind_of?(Hash){ false } mock(item).id { 1 } items = [item] response = self.json_for_autocomplete(items, :name).first @@ -77,6 +79,7 @@ class AutocompleteTest < Test::Unit::TestCase should 'add that extra data to result' do item = mock(Object) mock(item).send(:name).times(2) { 'Object Name' } + stub(item).kind_of?(Hash){ false } mock(item).id { 1 } mock(item).send("extra") { 'Object Extra ' } From 7d72df302b1bdab611abcd169f36190f19468982 Mon Sep 17 00:00:00 2001 From: Michael Johnston Date: Thu, 4 Feb 2016 01:11:57 -0800 Subject: [PATCH 2/4] remove full_model check from pluck --- lib/rails-jquery-autocomplete/orm/active_record.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rails-jquery-autocomplete/orm/active_record.rb b/lib/rails-jquery-autocomplete/orm/active_record.rb index a8bba92..67bdab1 100644 --- a/lib/rails-jquery-autocomplete/orm/active_record.rb +++ b/lib/rails-jquery-autocomplete/orm/active_record.rb @@ -36,7 +36,7 @@ def active_record_get_autocomplete_items(parameters) items = items.where(where) unless where.blank? if select_method == :pluck columns = get_autocomplete_select_clause(model, method, options) - items = items.pluck(*columns) unless options[:full_model] + items = items.pluck(*columns) columns = columns.map{|column| column.sub(/^#{model.table_name}\./, '')} items = items.map{|item| Hash[columns.zip(item)]} end From 8632ed8b32a4930c4cd0380e7ceb7bc8014f5c60 Mon Sep 17 00:00:00 2001 From: Michael Johnston Date: Thu, 4 Feb 2016 01:24:53 -0800 Subject: [PATCH 3/4] =?UTF-8?q?=C2=AF\=5F(=E3=83=84)=5F/=C2=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/rails-jquery-autocomplete/autocomplete.rb | 4 ++-- lib/rails-jquery-autocomplete/orm/active_record.rb | 6 ++++-- test/lib/rails-jquery-autocomplete/autocomplete_test.rb | 6 +++--- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/rails-jquery-autocomplete/autocomplete.rb b/lib/rails-jquery-autocomplete/autocomplete.rb index 1e649cb..6453b7c 100644 --- a/lib/rails-jquery-autocomplete/autocomplete.rb +++ b/lib/rails-jquery-autocomplete/autocomplete.rb @@ -97,9 +97,9 @@ def get_object(model_sym) # Hash also includes a key/value pair for each method in extra_data # def json_for_autocomplete(items, method, extra_data=[]) - if items.first && items.first.kind_of?(Hash) + if items.first && items.first.is_a?(Hash) items.each do |item| - item['label'] = item['value'] = item[method.to_s] + item["label"] = item["value"] = item[method.to_s] end else items = items.collect do |item| diff --git a/lib/rails-jquery-autocomplete/orm/active_record.rb b/lib/rails-jquery-autocomplete/orm/active_record.rb index 67bdab1..dbc00c6 100644 --- a/lib/rails-jquery-autocomplete/orm/active_record.rb +++ b/lib/rails-jquery-autocomplete/orm/active_record.rb @@ -37,8 +37,10 @@ def active_record_get_autocomplete_items(parameters) if select_method == :pluck columns = get_autocomplete_select_clause(model, method, options) items = items.pluck(*columns) - columns = columns.map{|column| column.sub(/^#{model.table_name}\./, '')} - items = items.map{|item| Hash[columns.zip(item)]} + columns = columns.map do |column| + column.sub(/^#{model.table_name}\./, "") + end + items = items.map { |item| Hash[columns.zip(item)] } end items end diff --git a/test/lib/rails-jquery-autocomplete/autocomplete_test.rb b/test/lib/rails-jquery-autocomplete/autocomplete_test.rb index f4205e0..9219baf 100644 --- a/test/lib/rails-jquery-autocomplete/autocomplete_test.rb +++ b/test/lib/rails-jquery-autocomplete/autocomplete_test.rb @@ -54,7 +54,7 @@ class AutocompleteTest < Test::Unit::TestCase should 'parse items to JSON' do item = mock(Object) mock(item).send(:name).times(2) { 'Object Name' } - stub(item).kind_of?(Hash){ false } + stub(item).is_a?(Hash) { false } mock(item).id { 1 } items = [item] response = self.json_for_autocomplete(items, :name).first @@ -66,7 +66,7 @@ class AutocompleteTest < Test::Unit::TestCase should 'return an instance of HashWithIndifferentAccess' do item = mock(Object) mock(item).send(:name).times(2) { 'Object Name' } - stub(item).kind_of?(Hash){ false } + stub(item).is_a?(Hash) { false } mock(item).id { 1 } items = [item] response = self.json_for_autocomplete(items, :name).first @@ -79,7 +79,7 @@ class AutocompleteTest < Test::Unit::TestCase should 'add that extra data to result' do item = mock(Object) mock(item).send(:name).times(2) { 'Object Name' } - stub(item).kind_of?(Hash){ false } + stub(item).is_a?(Hash) { false } mock(item).id { 1 } mock(item).send("extra") { 'Object Extra ' } From 3f052d06dbc3d51cd7e5c9edd9773e62c6165878 Mon Sep 17 00:00:00 2001 From: Michael Johnston Date: Sun, 7 Feb 2016 18:52:52 -0800 Subject: [PATCH 4/4] when doing a pluck, we need to ensure no duplicate columns because rails internally does a uniq before querying --- lib/rails-jquery-autocomplete/autocomplete.rb | 1 + lib/rails-jquery-autocomplete/orm/active_record.rb | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/rails-jquery-autocomplete/autocomplete.rb b/lib/rails-jquery-autocomplete/autocomplete.rb index 6453b7c..a9c4bbe 100644 --- a/lib/rails-jquery-autocomplete/autocomplete.rb +++ b/lib/rails-jquery-autocomplete/autocomplete.rb @@ -98,6 +98,7 @@ def get_object(model_sym) # def json_for_autocomplete(items, method, extra_data=[]) if items.first && items.first.is_a?(Hash) + # Query was a "pluck" and items are already hashes items.each do |item| item["label"] = item["value"] = item[method.to_s] end diff --git a/lib/rails-jquery-autocomplete/orm/active_record.rb b/lib/rails-jquery-autocomplete/orm/active_record.rb index dbc00c6..69ccee8 100644 --- a/lib/rails-jquery-autocomplete/orm/active_record.rb +++ b/lib/rails-jquery-autocomplete/orm/active_record.rb @@ -35,7 +35,7 @@ def active_record_get_autocomplete_items(parameters) limit(limit).order(order) items = items.where(where) unless where.blank? if select_method == :pluck - columns = get_autocomplete_select_clause(model, method, options) + columns = get_autocomplete_select_clause(model, method, options).uniq items = items.pluck(*columns) columns = columns.map do |column| column.sub(/^#{model.table_name}\./, "")