Blob Blame History Raw
From d86f6e61e75d07f0ed8b9214a1b8f1e60dccf73a Mon Sep 17 00:00:00 2001
From: Willem van Bergen <willem@vanbergen.org>
Date: Thu, 1 May 2014 06:10:17 -0400
Subject: [PATCH] Clean up auto complete builder to fix ActiveRecord
 deprecation warnings.

---
 lib/scoped_search/auto_complete_builder.rb | 73 ++++++++++++++++--------------
 lib/scoped_search/definition.rb            |  2 +-
 spec/integration/ordinal_querying_spec.rb  |  6 +--
 spec/integration/string_querying_spec.rb   |  6 +--
 4 files changed, 45 insertions(+), 42 deletions(-)

diff --git a/lib/scoped_search/auto_complete_builder.rb b/lib/scoped_search/auto_complete_builder.rb
index 6085bf6..8ab9ac0 100644
--- a/lib/scoped_search/auto_complete_builder.rb
+++ b/lib/scoped_search/auto_complete_builder.rb
@@ -1,17 +1,16 @@
 module ScopedSearch
 
-
-  LOGICAL_INFIX_OPERATORS  = ScopedSearch::QueryLanguage::Parser::LOGICAL_INFIX_OPERATORS
-  LOGICAL_PREFIX_OPERATORS = ScopedSearch::QueryLanguage::Parser::LOGICAL_PREFIX_OPERATORS
-  NULL_PREFIX_OPERATORS    = ScopedSearch::QueryLanguage::Parser::NULL_PREFIX_OPERATORS
-  NULL_PREFIX_COMPLETER    = ['has']
-  COMPARISON_OPERATORS     = ScopedSearch::QueryLanguage::Parser::COMPARISON_OPERATORS
-  PREFIX_OPERATORS         = LOGICAL_PREFIX_OPERATORS + NULL_PREFIX_OPERATORS
-
   # The AutoCompleteBuilder class builds suggestions to complete query based on
   # the query language syntax.
   class AutoCompleteBuilder
 
+    LOGICAL_INFIX_OPERATORS  = ScopedSearch::QueryLanguage::Parser::LOGICAL_INFIX_OPERATORS
+    LOGICAL_PREFIX_OPERATORS = ScopedSearch::QueryLanguage::Parser::LOGICAL_PREFIX_OPERATORS
+    NULL_PREFIX_OPERATORS    = ScopedSearch::QueryLanguage::Parser::NULL_PREFIX_OPERATORS
+    NULL_PREFIX_COMPLETER    = ['has']
+    COMPARISON_OPERATORS     = ScopedSearch::QueryLanguage::Parser::COMPARISON_OPERATORS
+    PREFIX_OPERATORS         = LOGICAL_PREFIX_OPERATORS + NULL_PREFIX_OPERATORS
+    
     attr_reader :ast, :definition, :query, :tokens
 
     # This method will parse the query string and build  suggestion list using the
@@ -174,10 +173,14 @@ def complete_key(name, field, val)
       quoted_table  = field.key_klass.connection.quote_table_name(field.key_klass.table_name)
       quoted_field  = field.key_klass.connection.quote_column_name(field.key_field)
       field_name    = "#{quoted_table}.#{quoted_field}"
-      select_clause = "DISTINCT #{field_name}"
-      opts =  value_conditions(field_name, val).merge(:select => select_clause, :limit => 20)
 
-      field.key_klass.all(opts).map(&field.key_field).compact.map{ |f| "#{name}.#{f} "}
+      field.key_klass
+        .where(value_conditions(field_name, val))
+        .distinct(field_name)
+        .limit(20)
+        .map(&field.key_field)
+        .compact
+        .map { |f| "#{name}.#{f} " }
     end
 
     # this method auto-completes values of fields that have a :complete_value marker
@@ -197,10 +200,13 @@ def complete_value
       return complete_date_value if field.temporal?
       return complete_key_value(field, token, val) if field.key_field
 
-      opts = value_conditions(field.quoted_field, val)
-      opts.merge!(:limit => 20, :select => "DISTINCT #{field.quoted_field}")
-
-      return completer_scope(field).all(opts).map(&field.field).compact.map{|v| v.to_s =~ /\s+/ ? "\"#{v}\"" : v}
+      completer_scope(field)
+        .where(value_conditions(field.quoted_field, val))
+        .distinct(field.quoted_field)
+        .limit(20)
+        .map(&field.field)
+        .compact
+        .map { |v| v.to_s =~ /\s/ ? "\"#{v}\"" : v }
     end
 
     def completer_scope(field)
@@ -215,7 +221,7 @@ def complete_set(field)
     end
     # date value completer
     def complete_date_value
-      options =[]
+      options = []
       options << '"30 minutes ago"'
       options << '"1 hour ago"'
       options << '"2 hours ago"'
@@ -233,24 +239,29 @@ def complete_date_value
     # complete values in a key-value schema
     def complete_key_value(field, token, val)
       key_name = token.sub(/^.*\./,"")
-      key_opts = value_conditions(field.quoted_field,val).merge(:conditions => {field.key_field => key_name})
-      key_klass = field.key_klass.first(key_opts)
+      key_klass = field.key_klass.where(field.key_field => key_name).first
       raise ScopedSearch::QueryNotSupported, "Field '#{key_name}' not recognized for searching!" if key_klass.nil?
 
-      opts = {:limit => 20, :select => "DISTINCT #{field.quoted_field}"}
-      if(field.key_klass != field.klass)
-        key  = field.key_klass.to_s.gsub(/.*::/,'').underscore.to_sym
-        fk   = field.klass.reflections[key].association_foreign_key.to_sym
-        opts.merge!(:conditions => {fk => key_klass.id})
-      else
-        opts.merge!(key_opts)
+      query = completer_scope(field)
+
+      if field.key_klass != field.klass
+        key   = field.key_klass.to_s.gsub(/.*::/,'').underscore.to_sym
+        fk    = field.klass.reflections[key].association_foreign_key.to_sym
+        query = query.where(fk => key_klass.id)
       end
-      return completer_scope(field).all(opts).map(&field.field).compact.map{|v| v.to_s =~ /\s+/ ? "\"#{v}\"" : v}
+      
+      query
+        .where(value_conditions(field, val))
+        .distinct(field.quoted_field)
+        .limit(20)
+        .map(&field.field)
+        .compact
+        .map { |v| v.to_s =~ /\s/ ? "\"#{v}\"" : v }
     end
 
-    #this method returns conditions for selecting completion from partial value
-    def value_conditions(field_name, val)
-      return val.blank? ? {} : {:conditions => "#{field_name} LIKE '#{val.gsub("'","''")}%'".tr_s('%*', '%')}
+    # This method returns conditions for selecting completion from partial value
+    def value_conditions(field, val)
+      val.blank? ? nil : "#{field.quoted_field} LIKE '#{val.gsub("'","''")}%'".tr_s('%*', '%')
     end
 
     # This method complete infix operators by field type
@@ -259,8 +270,4 @@ def complete_operator(node)
     end
 
   end
-
 end
-
-# Load lib files
-require 'scoped_search/query_builder'
diff --git a/lib/scoped_search/definition.rb b/lib/scoped_search/definition.rb
index 7483857..f5b2c79 100644
--- a/lib/scoped_search/definition.rb
+++ b/lib/scoped_search/definition.rb
@@ -258,7 +258,7 @@ def register_named_scope! # :nodoc
         when 4
           @klass.scope(:search_for, lambda { |*args|
             find_options = ScopedSearch::QueryBuilder.build_query(definition, args[0], args[1])
-            search_scope = @klass.all
+            search_scope = @klass
             search_scope = search_scope.where(find_options[:conditions]) if find_options[:conditions]
             search_scope = search_scope.includes(find_options[:include]) if find_options[:include]
             search_scope = search_scope.references(find_options[:include]) if find_options[:include]
diff --git a/spec/integration/ordinal_querying_spec.rb b/spec/integration/ordinal_querying_spec.rb
index 5c591d9..9247682 100644
--- a/spec/integration/ordinal_querying_spec.rb
+++ b/spec/integration/ordinal_querying_spec.rb
@@ -85,10 +85,8 @@
       # any implicit type conversions to a string (+ or << operators) a TypeError would be raised.
       # https://github.com/wvanbergen/scoped_search/issues/33 for more details
       it "encoded string should not raise TypeError when querying non-indexed column without a value" do
-        if defined? Encoding
-          query = 'unindexed ='.force_encoding(Encoding::UTF_8).encode
-          lambda { @class.search_for(query) }.should_not raise_error
-        end
+        query = 'unindexed ='.force_encoding(Encoding::UTF_8).encode
+        lambda { @class.search_for(query) }.should_not raise_error
       end
 
       it "should not return records for which the query matches unindex records" do
diff --git a/spec/integration/string_querying_spec.rb b/spec/integration/string_querying_spec.rb
index 3008266..029d201 100644
--- a/spec/integration/string_querying_spec.rb
+++ b/spec/integration/string_querying_spec.rb
@@ -221,10 +221,8 @@
       end
 
       it "resetting order when selecting distinct values" do
-        distinct_search =
-          @class.search_for('', :order => '').all(:select => 'DISTINCT(explicit)')
-
-        Set.new(distinct_search.map(&:explicit)).should == Set['baz', nil]
+        distinct_search = @class.search_for('', :order => '').distinct(:explicit)
+        Set.new(distinct_search.pluck(:explicit)).should == Set['baz', nil]
       end
 
       it 'should order using symbol' do