Class: Tokite::SearchQuery

Inherits:
Object
  • Object
show all
Defined in:
app/models/tokite/search_query.rb

Defined Under Namespace

Classes: Parser, QueryError, QueryParseError, QueryRegexpError

Constant Summary collapse

DEFAULT_FIELDS =
%i(title body)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(query) ⇒ SearchQuery

Returns a new instance of SearchQuery.



56
57
58
59
# File 'app/models/tokite/search_query.rb', line 56

def initialize(query)
  @query = query
  @tree = Array.wrap(self.class.parse(query))
end

Instance Attribute Details

#queryObject (readonly)

Returns the value of attribute query.



5
6
7
# File 'app/models/tokite/search_query.rb', line 5

def query
  @query
end

#treeObject (readonly)

Returns the value of attribute tree.



5
6
7
# File 'app/models/tokite/search_query.rb', line 5

def tree
  @tree
end

Class Method Details

.parse(query) ⇒ Object



41
42
43
44
45
# File 'app/models/tokite/search_query.rb', line 41

def self.parse(query)
  Array.wrap(parser.parse(query))
rescue Parslet::ParseFailed => e
  raise QueryParseError, e
end

.parserObject



37
38
39
# File 'app/models/tokite/search_query.rb', line 37

def self.parser
  @parser ||= Tokite::SearchQuery::Parser.new
end

.validate(query) ⇒ Object



47
48
49
50
51
52
53
54
# File 'app/models/tokite/search_query.rb', line 47

def self.validate(query)
  tree = SearchQuery.parse(query)
  tree.each do |word|
    Regexp.compile(word[:regexp_word].to_s, Regexp::IGNORECASE) if word[:regexp_word]
  end
rescue RegexpError => e
  raise QueryRegexpError, e
end

Instance Method Details

#match?(doc) ⇒ Boolean

Returns:

  • (Boolean)


61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'app/models/tokite/search_query.rb', line 61

def match?(doc)
  tree.all? do |word|
    field = word[:field]
    if field
      targets =
        case doc[field.to_sym]
        when Array
          doc[field.to_sym].map(&:downcase)
        when nil
          []
        else
          [doc[field.to_sym].downcase]
        end
    else
      targets = DEFAULT_FIELDS.map{|field| doc[field]&.downcase }.compact
    end
    if word[:regexp_word]
      begin
        regexp = Regexp.compile(word[:regexp_word].to_s, Regexp::IGNORECASE)
        matched = targets.any?{|text| regexp.match?(text) }
      rescue RegexpError
        matched = false
      end
    else
      value = word[:word].to_s.downcase
      matched = targets.any?{|text| text.index(value) }
    end
    word[:exclude].present? ? !matched : matched
  end
end