Module: Pose

Extended by:
ActiveSupport::Concern
Defined in:
lib/pose.rb,
lib/pose/version.rb

Overview

Polymorphic search for ActiveRecord objects.

Defined Under Namespace

Modules: InstanceMethods

Constant Summary

CONFIGURATION =
By default, doesn't run in tests. Set this to true to test the search functionality.
{ :search_in_tests => false }
VERSION =
"0.0.1"

Class Method Summary (collapse)

Class Method Details

+ (Array<String>) get_words_to_add(existing_words, new_words)

Returns all strings that are in new_words, but not in existing_words. Helper method.

Parameters:

  • existing_words (Array<String>)
    The words that are already associated with the object.
  • new_words (Array<String>)
    The words thet the object should have from now on.

Returns:

  • (Array<String>)
    The words that need to be added to the existing_words array.


66
67
68
# File 'lib/pose.rb', line 66

def Pose.get_words_to_add existing_words, new_words
  new_words - existing_words.map(&:text)
end

+ (Array<String>) get_words_to_remove(existing_words, new_words)

Returns the id of all word objects that are in existing_words, but not in new_words. Helper method.

Parameters:

  • existing_words (Array<String>)
    The words that are already associated with the object.
  • new_words (Array<String>)
    The words thet the object should have from now on.

Returns:

  • (Array<String>)
    The words that need to be removed from the existing_words array.


75
76
77
78
79
# File 'lib/pose.rb', line 75

def Pose.get_words_to_remove existing_words, new_words
  existing_words.map do |existing_word|
    new_words.include?(existing_word.text) ? nil : existing_word
  end.compact
end

+ (Boolean) is_url(word)

Returns whether the given string is a URL.

Parameters:

  • word (String)
    The string to check.

Returns:

  • (Boolean)


84
85
86
87
88
89
# File 'lib/pose.rb', line 84

def Pose.is_url word
  uri = URI::parse word
  return uri.scheme == 'http'
rescue URI::InvalidURIError
  false
end

+ (String) root_word(raw_word)

Simplifies the given word to a generic search form.

Parameters:

  • raw_word (String)
    The word to make searchable.

Returns:

  • (String)
    The stemmed version of the word.


94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/pose.rb', line 94

def Pose.root_word raw_word
  result = []
  raw_word_copy = raw_word[0..-1]
  raw_word_copy.gsub! /[()*<>'",;]/, ' '
  raw_word_copy.gsub! /\s+/, ' '
  raw_word_copy.split(' ').each do |word|
    if Pose.is_url(word)
      result.concat word.split(/[\.\/\:]/).delete_if{|word| word.blank?}
    else
      word.gsub! /[\-\/\._:]/, ' '
      word.gsub! /\s+/, ' '
      word.split(' ').each do |w|
        stemmed_word =  w.parameterize.singularize
        result.concat stemmed_word.split ' '
      end
    end
  end
  result.uniq
end

+ (Object) search(query, classes)

Returns all objects matching the given query.

Parameters:

  • query (String)
    The search query as entered by the user.
  • classes (Array<String>)
    The classes that should be returned.


117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/pose.rb', line 117

def Pose.search query, classes
  
  # Turn 'classes' into an array.
  classes = [classes].flatten
  classes_names = classes.map &:name

  # Get the ids of the results.
  result_classes_and_ids = {}
  query.split(' ').each do |query_word|
    current_word_classes_and_ids = {}
    classes.each { |clazz| current_word_classes_and_ids[clazz.name] = [] }
    PoseAssignment.joins(:pose_word) \
                  .where(:pose_words => {:text.matches => "#{query_word}%"},
                         :posable_type => classes_names) \
                  .each do |pose_assignment|
      current_word_classes_and_ids[pose_assignment.posable_type] << pose_assignment.posable_id
    end
    
    current_word_classes_and_ids.each do |class_name, ids|
      if result_classes_and_ids.has_key? class_name
        result_classes_and_ids[class_name] = result_classes_and_ids[class_name] & ids
      else
        result_classes_and_ids[class_name] = ids
      end
    end
  end

  # Load the results by id.
  result = {}
  classes.each { |clazz| result[clazz] = [] }
  result_classes_and_ids.each do |class_name, ids|
    result_class = Kernel.const_get class_name
    next unless classes.include? result_class
    next if ids.empty?
    result[result_class] = result_class.where :id => ids
  end

  result
end