##// END OF EJS Templates
Replaces find(:all) calls....
Jean-Philippe Lang -
r10693:5cb56fd1e423
parent child
Show More
@@ -1,133 +1,130
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2012 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 module Redmine
19 19 module Acts
20 20 module Searchable
21 21 def self.included(base)
22 22 base.extend ClassMethods
23 23 end
24 24
25 25 module ClassMethods
26 26 # Options:
27 27 # * :columns - a column or an array of columns to search
28 28 # * :project_key - project foreign key (default to project_id)
29 29 # * :date_column - name of the datetime column (default to created_on)
30 30 # * :sort_order - name of the column used to sort results (default to :date_column or created_on)
31 31 # * :permission - permission required to search the model (default to :view_"objects")
32 32 def acts_as_searchable(options = {})
33 33 return if self.included_modules.include?(Redmine::Acts::Searchable::InstanceMethods)
34 34
35 35 cattr_accessor :searchable_options
36 36 self.searchable_options = options
37 37
38 38 if searchable_options[:columns].nil?
39 39 raise 'No searchable column defined.'
40 40 elsif !searchable_options[:columns].is_a?(Array)
41 41 searchable_options[:columns] = [] << searchable_options[:columns]
42 42 end
43 43
44 44 searchable_options[:project_key] ||= "#{table_name}.project_id"
45 45 searchable_options[:date_column] ||= "#{table_name}.created_on"
46 46 searchable_options[:order_column] ||= searchable_options[:date_column]
47 47
48 48 # Should we search custom fields on this model ?
49 49 searchable_options[:search_custom_fields] = !reflect_on_association(:custom_values).nil?
50 50
51 51 send :include, Redmine::Acts::Searchable::InstanceMethods
52 52 end
53 53 end
54 54
55 55 module InstanceMethods
56 56 def self.included(base)
57 57 base.extend ClassMethods
58 58 end
59 59
60 60 module ClassMethods
61 61 # Searches the model for the given tokens
62 62 # projects argument can be either nil (will search all projects), a project or an array of projects
63 63 # Returns the results and the results count
64 64 def search(tokens, projects=nil, options={})
65 65 if projects.is_a?(Array) && projects.empty?
66 66 # no results
67 67 return [[], 0]
68 68 end
69 69
70 70 # TODO: make user an argument
71 71 user = User.current
72 72 tokens = [] << tokens unless tokens.is_a?(Array)
73 73 projects = [] << projects unless projects.nil? || projects.is_a?(Array)
74 74
75 75 find_options = {:include => searchable_options[:include]}
76 76 find_options[:order] = "#{searchable_options[:order_column]} " + (options[:before] ? 'DESC' : 'ASC')
77 77
78 78 limit_options = {}
79 79 limit_options[:limit] = options[:limit] if options[:limit]
80 80 if options[:offset]
81 81 limit_options[:conditions] = "(#{searchable_options[:date_column]} " + (options[:before] ? '<' : '>') + "'#{connection.quoted_date(options[:offset])}')"
82 82 end
83 83
84 84 columns = searchable_options[:columns]
85 85 columns = columns[0..0] if options[:titles_only]
86 86
87 87 token_clauses = columns.collect {|column| "(LOWER(#{column}) LIKE ?)"}
88 88
89 89 if !options[:titles_only] && searchable_options[:search_custom_fields]
90 searchable_custom_field_ids = CustomField.find(:all,
91 :select => 'id',
92 :conditions => { :type => "#{self.name}CustomField",
93 :searchable => true }).collect(&:id)
90 searchable_custom_field_ids = CustomField.where(:type => "#{self.name}CustomField", :searchable => true).pluck(:id)
94 91 if searchable_custom_field_ids.any?
95 92 custom_field_sql = "#{table_name}.id IN (SELECT customized_id FROM #{CustomValue.table_name}" +
96 93 " WHERE customized_type='#{self.name}' AND customized_id=#{table_name}.id AND LOWER(value) LIKE ?" +
97 94 " AND #{CustomValue.table_name}.custom_field_id IN (#{searchable_custom_field_ids.join(',')}))"
98 95 token_clauses << custom_field_sql
99 96 end
100 97 end
101 98
102 99 sql = (['(' + token_clauses.join(' OR ') + ')'] * tokens.size).join(options[:all_words] ? ' AND ' : ' OR ')
103 100
104 101 find_options[:conditions] = [sql, * (tokens.collect {|w| "%#{w.downcase}%"} * token_clauses.size).sort]
105 102
106 103 scope = self
107 104 project_conditions = []
108 105 if searchable_options.has_key?(:permission)
109 106 project_conditions << Project.allowed_to_condition(user, searchable_options[:permission] || :view_project)
110 107 elsif respond_to?(:visible)
111 108 scope = scope.visible(user)
112 109 else
113 110 ActiveSupport::Deprecation.warn "acts_as_searchable with implicit :permission option is deprecated. Add a visible scope to the #{self.name} model or use explicit :permission option."
114 111 project_conditions << Project.allowed_to_condition(user, "view_#{self.name.underscore.pluralize}".to_sym)
115 112 end
116 113 # TODO: use visible scope options instead
117 114 project_conditions << "#{searchable_options[:project_key]} IN (#{projects.collect(&:id).join(',')})" unless projects.nil?
118 115 project_conditions = project_conditions.empty? ? nil : project_conditions.join(' AND ')
119 116
120 117 results = []
121 118 results_count = 0
122 119
123 120 scope = scope.scoped({:conditions => project_conditions}).scoped(find_options)
124 121 results_count = scope.count(:all)
125 122 results = scope.find(:all, limit_options)
126 123
127 124 [results, results_count]
128 125 end
129 126 end
130 127 end
131 128 end
132 129 end
133 130 end
General Comments 0
You need to be logged in to leave comments. Login now