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