lib/pg_search/features/tsearch.rb in pg_search-1.0.5 vs lib/pg_search/features/tsearch.rb in pg_search-1.0.6
- old
+ new
@@ -1,23 +1,19 @@
require "pg_search/compatibility"
require "active_support/core_ext/module/delegation"
module PgSearch
module Features
- class TSearch < Feature
+ class TSearch < Feature # rubocop:disable Metrics/ClassLength
def self.valid_options
- super + [:dictionary, :prefix, :negation, :any_word, :normalization, :tsvector_column]
+ super + [:dictionary, :prefix, :negation, :any_word, :normalization, :tsvector_column, :highlight]
end
def initialize(*args)
super
-
- if options[:prefix] && model.connection.send(:postgresql_version) < 80400 # rubocop:disable Style/GuardClause
- raise PgSearch::NotSupportedForPostgresqlVersion.new(<<-MESSAGE.strip_heredoc)
- Sorry, {:using => {:tsearch => {:prefix => true}}} only works in PostgreSQL 8.4 and above.")
- MESSAGE
- end
+ checks_for_highlight
+ checks_for_prefix
end
def conditions
Arel::Nodes::Grouping.new(
Arel::Nodes::InfixOperation.new("@@", arel_wrap(tsdocument), arel_wrap(tsquery))
@@ -26,10 +22,49 @@
def rank
arel_wrap(tsearch_rank)
end
+ def highlight
+ arel_wrap(ts_headline)
+ end
+
private
+
+ def checks_for_prefix
+ if options[:prefix] && model.connection.send(:postgresql_version) < 80400
+ raise PgSearch::NotSupportedForPostgresqlVersion.new(<<-MESSAGE.strip_heredoc)
+ Sorry, {:using => {:tsearch => {:prefix => true}}} only works in PostgreSQL 8.4 and above.")
+ MESSAGE
+ end
+ end
+
+ def checks_for_highlight
+ if options[:highlight] && model.connection.send(:postgresql_version) < 90000
+ raise PgSearch::NotSupportedForPostgresqlVersion.new(<<-MESSAGE.strip_heredoc)
+ Sorry, {:using => {:tsearch => {:highlight => true}}} only works in PostgreSQL 9.0 and above.")
+ MESSAGE
+ end
+ end
+
+ def ts_headline
+ "ts_headline((#{document}), (#{tsquery}), '#{ts_headline_options}')"
+ end
+
+ def ts_headline_options
+ return nil unless options[:highlight].is_a?(Hash)
+
+ headline_options = map_headline_options
+ headline_options.map{|key, value| "#{key} = #{value}" if value }.compact.join(", ")
+ end
+
+ def map_headline_options
+ {
+ "StartSel" => options[:highlight][:start_sel],
+ "StopSel" => options[:highlight][:stop_sel],
+ "MaxFragments" => options[:highlight][:max_fragments]
+ }
+ end
DISALLOWED_TSQUERY_CHARACTERS = /['?\\:]/
def tsquery_for_term(unsanitized_term) # rubocop:disable Metrics/AbcSize
if options[:negation] && unsanitized_term.start_with?("!")