Module: SmartSearch::ClassMethods

Defined in:
lib/smart_search.rb

Overview

Class Methods for ActiveRecord

Instance Method Summary collapse

Instance Method Details

#find_by_tags(tags = "", options = {}) ⇒ Object

Serach database for given search tags



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/smart_search.rb', line 67

def find_by_tags(tags = "", options = {})
  if self.is_smart_search?

    tags = tags.join(" ") if tags.is_a?(Array)

    # Save Data for similarity analysis
    if tags.size > 3
      self.connection.execute("INSERT INTO `#{::SmartSearchHistory.table_name}` (`query`) VALUES ('#{tags.gsub(/[^a-zA-ZäöüÖÄÜß\ ]/, '')}');")
    end

    tags = tags.gsub(/[\(\)\[\]\'\"\*\%\|]/, '').split(/[\ -]/).select {|t| !t.blank?}

    # Fallback for Empty String
    tags << "#" if tags.empty?

    # Similarity
    if self.enable_similarity == true
      tags.map! do |t|
        similars = SmartSimilarity.similars(t, :increment_counter => true).join("|")
        "search_tags REGEXP '#{similars}'"
      end

    else
      tags.map! {|t| "search_tags LIKE '%#{t}%'"}
    end

    # Load ranking from Search tags
    result_ids = []
    result_scores = {}
      SmartSearchTag.connection.select_all("select entry_id, sum(boost) as score, group_concat(search_tags) as grouped_tags
    from smart_search_tags where `table_name`= '#{self.table_name}' and

    (#{tags.join(' OR ')}) group by entry_id having (#{tags.join(' AND ').gsub('search_tags', 'grouped_tags')}) order by score DESC").each do |r|
      result_ids << r["entry_id"].to_i
      result_scores[r["entry_id"].to_i] = r['score'].to_f
    end

    # Enable unscoped searching
    if options[:unscoped] == true
      results     =  self.unscoped.where(:id => result_ids)
    else
      results     =  self.where(:id => result_ids)
    end

    if options[:conditions]
      results = results.where(options[:conditions])
    end

    if !self.condition_default.blank?
      results = results.where(self.condition_default)
    end

    if options[:group]
      results = results.group(options[:group])
    end

    if options[:order] || self.order_default
      results = results.order(options[:order] || self.order_default)
    else
      ordered_results = []
      results.each do |r|
        r.query_score = result_scores[r.id]
        ordered_results[result_ids.index(r.id)] = r
      end

      results = ordered_results.compact
    end

    return results
  else
    raise "#{self.inspect} is not a SmartSearch"
  end
end

#is_smart_search?Boolean

Verify if SmartSearch already loaded for this model

Returns:

  • (Boolean)


57
58
59
# File 'lib/smart_search.rb', line 57

def is_smart_search?
  self.included_modules.include?(InstanceMethods)
end

#result_template_pathObject

defines where to look for a partial to load when displaying results for this model



62
63
64
# File 'lib/smart_search.rb', line 62

def result_template_path
  "/search/results/#{self.name.split("::").last.underscore}"
end

#set_search_indexObject

reload search_tags for entire table based on the attributes defined in ‘:on’ option passed to the ‘smart_search’ method



142
143
144
145
146
147
148
# File 'lib/smart_search.rb', line 142

def set_search_index
  s = self.all.size.to_f
  self.all.each_with_index do |a, i|
    a.create_search_tags
    done = ((i+1).to_f/s)*100
  end
end

#set_similarity_indexObject

Load all search tags for this table into similarity index



151
152
153
154
155
# File 'lib/smart_search.rb', line 151

def set_similarity_index
  search_tags_list = self.connection.select_all("SELECT search_tags from #{SmartSearchTag.table_name} where `table_name` = #{self.table_name}").map {|r| r["search_tags"]}

  SmartSimilarity.create_from_text(search_tags_list.join(" "))
end

#smart_search(options = {:on => [], :conditions => nil, :group => nil, :order => "created_at", :force => false}) ⇒ Object

Enable SmartSearch for the current ActiveRecord model. accepts options:

  • :on, define which attributes to add to the search index

  • :conditions, define default scope for all queries made

  • :group, group by column

  • :order, order by column

see readme for details



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/smart_search.rb', line 27

def smart_search(options = {:on => [], :conditions => nil, :group => nil, :order => "created_at", :force => false})
  if table_exists?
    # Check if search_tags exists
    if !is_smart_search? || options[:force] == true || Rails.env == "test"

      cattr_accessor :condition_default, :group_default, :tags, :order_default, :enable_similarity, :default_template_path
      send :include, InstanceMethods
        self.send(:after_save, :create_search_tags, :if => :update_search_tags?) unless options[:auto] == false
        self.send(:before_destroy, :clear_search_tags)
        self.enable_similarity ||= true

        attr_accessor :query_score, :dont_update_search_tags

        # options zuweisen
        if options[:conditions].is_a?(String) && !options[:conditions].blank?
          self.condition_default = options[:conditions]
        elsif !options[:conditions].nil?
          raise ArgumentError, ":conditions must be a valid SQL Query"
        else
          self.condition_default = nil
        end

        self.order_default = options[:order]

        self.tags = options[:on] || []
    end
  end
end