Class: Udongo::Search::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/udongo/search/base.rb

Overview

The goal of the Base class is to filter our indices on the given search term. Further manipulation of individual index data into a meaningful result set (think autocomplete results) is done by extending this class.

Examples of class extensions could be: Udongo::Search::Backend - included in Udongo Udongo::Search::Frontend Udongo::Search::Api

The primary benefit in having these namespaced search interfaces is to provide a way for the developer to have different result objects for each resource.

Example #1: A search request for a specific Page instance in the frontend will typically return a link to said page. However, in search requests made in the backend for the same Page instance, you’d expect a link to a form in the backend Page module where you can edit the page’s contents.

Example #2: Some autocompletes in a frontend namespace might require an image or a price to be included in its body.

However these result objects are structured are also up to the developer.

Direct Known Subclasses

Backend, Frontend

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(term, controller: nil, namespace: nil) ⇒ Base

Returns a new instance of Base.



27
28
29
30
31
# File 'lib/udongo/search/base.rb', line 27

def initialize(term, controller: nil, namespace: nil)
  @term = Udongo::Search::Term.new(term, controller: controller)
  @controller = controller
  @namespace = namespace
end

Instance Attribute Details

#controllerObject (readonly)

Returns the value of attribute controller.



25
26
27
# File 'lib/udongo/search/base.rb', line 25

def controller
  @controller
end

#termObject (readonly)

Returns the value of attribute term.



25
26
27
# File 'lib/udongo/search/base.rb', line 25

def term
  @term
end

Instance Method Details

#class_exists?(class_name) ⇒ Boolean

Returns:

  • (Boolean)


33
34
35
36
37
38
# File 'lib/udongo/search/base.rb', line 33

def class_exists?(class_name)
  klass = Module.const_get(class_name)
  return klass.is_a?(Class)
rescue NameError
  return false
end

#indicesObject



40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/udongo/search/base.rb', line 40

def indices
  # Having the searchmodules sorted by weight returns indices in the
  # correct order.
  @indices ||= SearchModule.weighted.inject([]) do |stack, m|
    # The group happens to make sure we end up with just 1 copy of
    # a searchable result. Otherwise matches from both an indexed
    # Page#title and Page#description would be in the result set.
    stack << m.indices
              .where('search_indices.value LIKE ?', "%#{term.value}%")
              .group([:searchable_type, :searchable_id])
  end.flatten
end

#namespaceObject



53
54
55
56
57
58
59
# File 'lib/udongo/search/base.rb', line 53

def namespace
  # This looks daft, but it gives us a foot in the door for when a frontend
  # search is triggered in the backend.
  return @namespace unless @namespace.nil?
  return 'Frontend' if controller.nil?
  controller.class.parent.to_s
end

#result_object(index) ⇒ Object

In order to provide a good result set in a search autocomplete, we have to translate the raw index to a class that makes an index adhere to a certain interface (that can include links).



64
65
66
67
68
# File 'lib/udongo/search/base.rb', line 64

def result_object(index)
  klass = "Udongo::Search::ResultObjects::#{namespace}::#{index.searchable_type}"
  klass = 'Udongo::Search::ResultObjects::Base' unless result_object_exists?(klass)
  klass.constantize.new(index, search_context: self)
end

#result_object_exists?(name) ⇒ Boolean

Returns:

  • (Boolean)


70
71
72
# File 'lib/udongo/search/base.rb', line 70

def result_object_exists?(name)
  class_exists?(name) && name.constantize.method_defined?(:build_html)
end