diff --git a/lib/administrate/field/base.rb b/lib/administrate/field/base.rb index 65121587c..8d281c127 100644 --- a/lib/administrate/field/base.rb +++ b/lib/administrate/field/base.rb @@ -24,6 +24,18 @@ def self.searchable? false end + def self.search_exact? + false + end + + def self.search_lower? + true + end + + def self.search_requires_string_cast? + true + end + def self.field_type to_s.split("::").last.underscore end diff --git a/lib/administrate/field/deferred.rb b/lib/administrate/field/deferred.rb index ae3a79e85..28a74920f 100644 --- a/lib/administrate/field/deferred.rb +++ b/lib/administrate/field/deferred.rb @@ -41,6 +41,26 @@ def searchable? end end + def search_exact? + if options.key?(:getter) + false + else + options.fetch(:search_exact, deferred_class.search_exact?) + end + end + + def search_lower? + if options.key?(:getter) + false + else + options.fetch(:searchable, deferred_class.searchable?) + end + end + + def search_requires_string_cast? + deferred_class.search_requires_string_cast? + end + def searchable_field Administrate.deprecator.warn( "searchable_field is deprecated, use searchable_fields instead" diff --git a/lib/administrate/field/email.rb b/lib/administrate/field/email.rb index a84a0abfa..933634c5b 100644 --- a/lib/administrate/field/email.rb +++ b/lib/administrate/field/email.rb @@ -6,6 +6,10 @@ class Email < Field::Base def self.searchable? true end + + def search_requires_string_cast? + false + end end end end diff --git a/lib/administrate/field/string.rb b/lib/administrate/field/string.rb index 2d28d8e1e..43bfd8e9e 100644 --- a/lib/administrate/field/string.rb +++ b/lib/administrate/field/string.rb @@ -7,6 +7,10 @@ def self.searchable? true end + def search_requires_string_cast? + false + end + def truncate data.to_s[0...truncation_length] end diff --git a/lib/administrate/field/text.rb b/lib/administrate/field/text.rb index 397471eff..017a34915 100644 --- a/lib/administrate/field/text.rb +++ b/lib/administrate/field/text.rb @@ -7,6 +7,10 @@ def self.searchable? false end + def search_requires_string_cast? + false + end + def truncate data.to_s[0...truncation_length] end diff --git a/lib/administrate/field/url.rb b/lib/administrate/field/url.rb index b5f1dad2a..1924a2d45 100644 --- a/lib/administrate/field/url.rb +++ b/lib/administrate/field/url.rb @@ -7,6 +7,10 @@ def self.searchable? true end + def search_requires_string_cast? + false + end + def truncate data.to_s[0...truncation_length] end diff --git a/lib/administrate/search.rb b/lib/administrate/search.rb index ac04587c9..b0d4ff860 100644 --- a/lib/administrate/search.rb +++ b/lib/administrate/search.rb @@ -87,8 +87,18 @@ def query_template search_attributes.map do |attr| table_name = query_table_name(attr) searchable_fields(attr).map do |field| + attribute_type = attribute_types[attr] column_name = column_to_query(field) - "LOWER(CAST(#{table_name}.#{column_name} AS CHAR(256))) LIKE ?" + + search_target = "#{table_name}.#{column_name}" + search_target = "CAST(#{search_target} AS CHAR(256))" if attribute_type.search_requires_string_cast? + search_target = "LOWER(#{search_target})" if attribute_type.search_lower? + + if attribute_types[attr].search_exact? + "#{search_target} = ?" + else + "#{search_target} LIKE ?" + end end.join(" OR ") end.join(" OR ") end @@ -100,10 +110,21 @@ def searchable_fields(attr) end def query_values - fields_count = search_attributes.sum do |attr| - searchable_fields(attr).count + search_attributes.flat_map do |attr| + attribute_type = attribute_types[attr] + + search_term = if attribute_type.search_lower? + term.mb_chars.downcase + else + term.mb_chars + end + + if attribute_type.search_exact? + [search_term] * searchable_fields(attr).count + else + ["%#{search_term}%"] * searchable_fields(attr).count + end end - ["%#{term.mb_chars.downcase}%"] * fields_count end def search_attributes