Class: FullSearch::Highlighter
- Inherits:
-
Object
- Object
- FullSearch::Highlighter
- Defined in:
- lib/full_search/highlighter.rb
Class Method Summary collapse
- .apply!(records, model, query) ⇒ Object
- .apply_fields!(records, model, query) ⇒ Object
- .build_field_snippets(model, query) ⇒ Object
- .build_snippets(model, query) ⇒ Object
- .connection ⇒ Object
- .highlight_rows(model, query) ⇒ Object
- .manual_field_snippets(records, model, query) ⇒ Object
- .manual_highlight(text, query, config) ⇒ Object
- .manual_snippets(records, model, query) ⇒ Object
- .quote(value) ⇒ Object
Class Method Details
.apply!(records, model, query) ⇒ Object
5 6 7 8 9 10 11 12 |
# File 'lib/full_search/highlighter.rb', line 5 def self.apply!(records, model, query) snippets = build_snippets(model, query) if snippets.values.all?(&:nil?) && records.any? snippets = manual_snippets(records, model, query) end records.each { |record| record.full_search_snippet = snippets[record.id] } records end |
.apply_fields!(records, model, query) ⇒ Object
14 15 16 17 18 19 20 21 |
# File 'lib/full_search/highlighter.rb', line 14 def self.apply_fields!(records, model, query) fields = build_field_snippets(model, query) if fields.empty? && records.any? fields = manual_field_snippets(records, model, query) end records.each { |record| record.full_search_highlight_fields = fields[record.id] || {} } records end |
.build_field_snippets(model, query) ⇒ Object
35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/full_search/highlighter.rb', line 35 def self.build_field_snippets(model, query) rows = highlight_rows(model, query) dsl = model.full_search_dsl cols = dsl.fields.map(&:name) open_tag = (dsl.highlight_config || { open_tag: "<mark>" })[:open_tag] rows.to_h do |row| snippets = cols.each_with_object({}) do |col, hash| snippet = row["#{col}_snippet"].to_s.strip hash[col.to_s] = snippet if snippet.include?(open_tag) end [row["rowid"], snippets] end end |
.build_snippets(model, query) ⇒ Object
25 26 27 28 29 30 31 32 33 |
# File 'lib/full_search/highlighter.rb', line 25 def self.build_snippets(model, query) rows = highlight_rows(model, query) cols = model.full_search_dsl.fields.map(&:name) rows.to_h do |row| text = cols.map { |col| row["#{col}_snippet"] }.compact.join(" ").strip [row["rowid"], text.presence] end end |
.connection ⇒ Object
105 106 107 |
# File 'lib/full_search/highlighter.rb', line 105 def self.connection ActiveRecord::Base.connection end |
.highlight_rows(model, query) ⇒ Object
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/full_search/highlighter.rb', line 82 def self.highlight_rows(model, query) dsl = model.full_search_dsl config = dsl.highlight_config || { open_tag: "<mark>", close_tag: "</mark>" } match_expr = QueryParser.to_match_expression(QueryParser.parse(query)) return [] if match_expr.empty? table = FullSearch::Index.fts_table_name(model) cols = dsl.fields.map(&:name) return [] if cols.empty? highlight_parts = cols.each_with_index.map do |col, idx| "highlight(#{table}, #{idx}, #{quote(config[:open_tag])}, #{quote(config[:close_tag])}) AS #{col}_snippet" end.join(", ") sql = <<~SQL SELECT rowid, #{highlight_parts} FROM #{table} WHERE #{table} MATCH #{quote(match_expr)} SQL connection.execute(sql) end |
.manual_field_snippets(records, model, query) ⇒ Object
62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/full_search/highlighter.rb', line 62 def self.manual_field_snippets(records, model, query) dsl = model.full_search_dsl config = dsl.highlight_config || { open_tag: "<mark>", close_tag: "</mark>" } cols = dsl.fields.map(&:name) records.to_h do |record| snippets = cols.each_with_object({}) do |col, hash| value = record.public_send(col).to_s highlighted = manual_highlight(value, query, config) hash[col.to_s] = highlighted if highlighted.include?(config[:open_tag]) end [record.id, snippets] end end |
.manual_highlight(text, query, config) ⇒ Object
77 78 79 80 |
# File 'lib/full_search/highlighter.rb', line 77 def self.manual_highlight(text, query, config) return text if text.empty? || query.empty? text.gsub(/#{Regexp.escape(query)}/i, "#{config[:open_tag]}\\0#{config[:close_tag]}") end |
.manual_snippets(records, model, query) ⇒ Object
50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/full_search/highlighter.rb', line 50 def self.manual_snippets(records, model, query) dsl = model.full_search_dsl config = dsl.highlight_config || { open_tag: "<mark>", close_tag: "</mark>" } cols = dsl.fields.map(&:name) records.to_h do |record| text = cols.map { |col| record.public_send(col).to_s }.join(" ").strip highlighted = manual_highlight(text, query, config) [record.id, highlighted.presence] end end |
.quote(value) ⇒ Object
109 110 111 |
# File 'lib/full_search/highlighter.rb', line 109 def self.quote(value) connection.quote(value) end |