Module: SearchMagic::FullTextSearch::ClassMethods

Defined in:
lib/search_magic/full_text_search.rb

Instance Method Summary collapse

Instance Method Details

#arrange(arrangeable, direction = :asc) ⇒ Object



46
47
48
# File 'lib/search_magic/full_text_search.rb', line 46

def arrange(arrangeable, direction = :asc)
  arrangeable.blank? || !searchables.keys.include?(arrangeable.to_sym) ? criteria : order_by([["arrangeable_values.#{arrangeable}", direction]])
end

#inverse_searchablesObject



24
25
26
27
28
29
# File 'lib/search_magic/full_text_search.rb', line 24

def inverse_searchables
  @inverse_searchables ||= relations.values.
    map {|| [, .class_name.constantize] }.
    select {|, klass| klass < SearchMagic::FullTextSearch && klass.searchable_fields.keys.include?(.inverse_setter.chomp("=").to_sym)}.
    map(&:first).map(&:name)
end

#search_for(pattern) ⇒ Object Also known as: and_for

To support range searches, this will need to become more complicated. Specifically, it will need to be able to remove any term which contains a [:below, :before, :above, :after] selector, retreive the base selector and the target valuee, and match the latter against the former within the :arrangeable_values array as part of the returned criteria. How this then translates to :values_matching is currently unknown.



35
36
37
38
39
40
41
42
43
# File 'lib/search_magic/full_text_search.rb', line 35

def search_for(pattern)
  options, pattern = strip_option_terms_from(pattern)
  terms = terms_for(pattern)
  unless terms.blank?
    send( :"#{options[:mode] || default_search_mode}_in", :searchable_values => terms)
  else
    criteria
  end
end

#search_on(field_name, options = {}) ⇒ Object



16
17
18
# File 'lib/search_magic/full_text_search.rb', line 16

def search_on(field_name, options = {})
  searchable_fields[field_name] = options
end

#searchablesObject



20
21
22
# File 'lib/search_magic/full_text_search.rb', line 20

def searchables
  @searchables ||= create_searchables
end

#strip_option_terms_from(pattern) ⇒ Object



50
51
52
53
54
55
56
# File 'lib/search_magic/full_text_search.rb', line 50

def strip_option_terms_from(pattern)
  unless pattern.blank?
    [Hash[*(pattern.scan(option_terms).flatten)].symbolize_keys, pattern.gsub(option_terms, '').strip]
  else
    [{}, pattern]
  end
end

#terms_for(pattern) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/search_magic/full_text_search.rb', line 58

def terms_for(pattern)
  rval = /("[^"]+"|'[^']+'|\S+)/
  rnot_separator = "[^#{separator}]+"
  rsearch = /(?:(#{searchable_names})(?:#{separator}#{rval}|(#{presence_detector_escaped})))|#{rval}/i
  unless pattern.blank?
    terms = pattern.scan(rsearch).map(&:compact).map do |term|
      selector = term.length > 1 ? Regexp.escape(term.first) : rnot_separator
       = searchables[term.first.match(/^[^:]+/)[0].to_sym] if term.length > 1
      parsed_date = Chronic.parse(term.last) if  && .datable?
      prefix = "#{selector}#{separator}"
      prefix = "(#{prefix})?" if term.length == 1
      fragment = /^#{selector}#{separator}#{parsed_date}/i if parsed_date
      fragment = /^#{prefix}[^#{separator}\s]+/i if term.last == presence_detector
      fragment || term.last.scan(/\b(\S+)\b/).flatten.map do |word|
        /^#{prefix}.*#{Regexp.escape(word)}/i
      end
    end.flatten
  else
    []
  end
end