public
Description: Tog Platform Core
Homepage: http://www.toghq.com
Clone URL: git://github.com/tog/tog_core.git
Aitor García (author)
Wed Jul 01 13:22:06 -0700 2009
tog_core / app / models / tog / search.rb
100644 86 lines (74 sloc) 3.302 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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
55
56
57
58
59
60
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
# Tog::Search provides a simple interface to site-wide searches through a flexible collection of +sources+
# that the developer can extend to plug its own classes on the general search.
#
# ==== Simple example
#
# Tog::Search.sources << "User"
# @results = Tog::Search.search("joe-theplumber") # the @results instance will be paginated
#
# The modules used as +sources+ should implement a class method called site_search(query, options={}) and
# should return an +Array+ instance.
module Search
 
  # The sources availables to search in. These sources must be strings representing classes o modules that can
  # be retrieved through <pre>source.constantize</pre>.
  def self.sources
    @sources ||= []
  end
 
  # This method iterates all the classes/modules (usually activerecord models) added to the +sources+ attribute.
  # For each class, its search method is called and the matches are added to the paginated collection of
  # final results.
  #
  # ==== Attributes
  #
  # * <tt>:options</tt> - search options.
  # * <tt>:paginate_options</tt> - The same options allowed for the +paginate+ method provided by will_paginate
  #
  # == Filter conditions
  #
  # Search may be limited to specific sources by declaring the sources to
  # include or exclude. Both options accept single sources
  # (<tt>:only => "Model1"</tt>) or arrays of sources
  # (<tt>:except => ["Model1", "Model2"]</tt>).
  #
  # Tog::Search.search(term, :only => ["User","Course"])
  # Tog::Search.search(term, :except => "ClubHouse")
  
  def self.search(query, options = {}, paginate_options = {})
    paginate_options.reverse_merge! :per_page => Tog::Config['plugins.tog_core.pagination_size']
    results = []
    sources.uniq.flatten.each{|name|
      begin
        source = name.constantize
        if source.respond_to?(:site_search)
          if included_in_search?(name, options)
            results << source.site_search(query, options)
          end
        else
          RAILS_DEFAULT_LOGGER.warn(<<-WARNING
 
**************************************************************************************************************************************************
SEARCH WARNING: The source #{source} should implement a ´self.site_search(query, options={})´ method to be available on site-wide searches.
**************************************************************************************************************************************************
 
WARNING
          )
        end
 
      rescue NameError => e
        RAILS_DEFAULT_LOGGER.error(<<-ERROR
 
**************************************************************************************************************************************************
SEARCH ERROR: The source #{name} can't be constantized. Double-check it and make sure there is a matching Class or Module.
**************************************************************************************************************************************************
 
ERROR
        )
 
      end
 
    }
    results.flatten.paginate(paginate_options)
  end
  
  protected
  
  def self.included_in_search?(source, options)
    if options[:only]
      options[:only].include?(source)
    elsif options[:except]
      !options[:except].include?(source)
    else
      true
    end
  end
end