Module: Redmine::Acts::Searchable::InstanceMethods::ClassMethods

Defined in:
lib/plugins/acts_as_searchable/lib/acts_as_searchable.rb

Instance Method Summary collapse

Instance Method Details

#search_result_ranks_and_ids(tokens, user = User.current, projects = nil, options = {}) ⇒ Object

Searches the model for the given tokens and user visibility. The projects argument can be either nil (will search all projects), a project or an array of projects. Returns an array that contains the rank and id of all results. In current implementation, the rank is the record timestamp.

Valid options:

  • :titles_only - searches tokens in the first searchable column only

  • :all_words - searches results that match all token

  • :limit - maximum number of results to return

Example:

Issue.search_result_ranks_and_ids("foo")
# => [[Tue, 26 Jun 2007 22:16:00 UTC +00:00, 69], [Mon, 08 Oct 2007 14:31:00 UTC +00:00, 123]]

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
# File 'lib/plugins/acts_as_searchable/lib/acts_as_searchable.rb', line 77

def search_result_ranks_and_ids(tokens, user=User.current, projects=nil, options={})
  if projects.is_a?(Array) && projects.empty?
    # no results
    return []
  end

  tokens = [] << tokens unless tokens.is_a?(Array)
  projects = [] << projects if projects.is_a?(Project)

  columns = searchable_options[:columns]
  columns = columns[0..0] if options[:titles_only]

  token_clauses = columns.collect {|column| "(#{search_token_match_statement(column)})"}

  if !options[:titles_only] && searchable_options[:search_custom_fields]
    searchable_custom_fields = CustomField.where(:type => "#{self.name}CustomField", :searchable => true)
    fields_by_visibility = searchable_custom_fields.group_by {|field|
      field.visibility_by_project_condition(searchable_options[:project_key], user, "cfs.custom_field_id")
    }
    # only 1 subquery for all custom fields with the same visibility statement
    fields_by_visibility.each do |visibility, fields|
      ids = fields.map(&:id).join(',')
      sql = "#{table_name}.id IN (SELECT cfs.customized_id FROM #{CustomValue.table_name} cfs" +
        " WHERE cfs.customized_type='#{self.name}' AND cfs.customized_id=#{table_name}.id" +
        " AND cfs.custom_field_id IN (#{ids})" +
        " AND #{search_token_match_statement('cfs.value')}" +
        " AND #{visibility})"
      token_clauses << sql
    end
  end

  sql = (['(' + token_clauses.join(' OR ') + ')'] * tokens.size).join(options[:all_words] ? ' AND ' : ' OR ')

  tokens_conditions = [sql, * (tokens.collect {|w| "%#{w}%"} * token_clauses.size).sort]

  search_scope(user, projects).
    reorder(searchable_options[:date_column] => :desc, :id => :desc).
    where(tokens_conditions).
    limit(options[:limit]).
    uniq.
    pluck(searchable_options[:date_column], :id)
end

#search_results(*args) ⇒ Object

Returns search results with same arguments as search_result_ranks_and_ids


157
158
159
160
# File 'lib/plugins/acts_as_searchable/lib/acts_as_searchable.rb', line 157

def search_results(*args)
  ranks_and_ids = search_result_ranks_and_ids(*args)
  search_results_from_ids(ranks_and_ids.map(&:last))
end

#search_results_from_ids(ids) ⇒ Object

Returns search results of given ids


152
153
154
# File 'lib/plugins/acts_as_searchable/lib/acts_as_searchable.rb', line 152

def search_results_from_ids(ids)
  where(:id => ids).preload(searchable_options[:preload]).to_a
end