@@ -36,9 +36,6 class SearchController < ApplicationController | |||||
36 | @project |
|
36 | @project | |
37 | end |
|
37 | end | |
38 |
|
38 | |||
39 | offset = nil |
|
|||
40 | begin; offset = params[:offset].to_time if params[:offset]; rescue; end |
|
|||
41 |
|
||||
42 | # quick jump to an issue |
|
39 | # quick jump to an issue | |
43 | if (m = @question.match(/^#?(\d+)$/)) && (issue = Issue.visible.find_by_id(m[1].to_i)) |
|
40 | if (m = @question.match(/^#?(\d+)$/)) && (issue = Issue.visible.find_by_id(m[1].to_i)) | |
44 | redirect_to issue_path(issue) |
|
41 | redirect_to issue_path(issue) | |
@@ -66,34 +63,39 class SearchController < ApplicationController | |||||
66 | # no more than 5 tokens to search for |
|
63 | # no more than 5 tokens to search for | |
67 | @tokens.slice! 5..-1 if @tokens.size > 5 |
|
64 | @tokens.slice! 5..-1 if @tokens.size > 5 | |
68 |
|
65 | |||
69 | @results = [] |
|
|||
70 | @results_by_type = Hash.new {|h,k| h[k] = 0} |
|
|||
71 |
|
||||
72 | limit = 10 |
|
66 | limit = 10 | |
73 | @scope.each do |s| |
|
67 | ||
74 | r, c = s.singularize.camelcase.constantize.search(@tokens, projects_to_search, |
|
68 | @result_count = 0 | |
|
69 | @result_count_by_type = Hash.new {|h,k| h[k] = 0} | |||
|
70 | ranks_and_ids = [] | |||
|
71 | ||||
|
72 | # get all the results ranks and ids | |||
|
73 | @scope.each do |scope| | |||
|
74 | klass = scope.singularize.camelcase.constantize | |||
|
75 | ranks_and_ids_in_scope = klass.search_result_ranks_and_ids(@tokens, User.current, projects_to_search, | |||
75 | :all_words => @all_words, |
|
76 | :all_words => @all_words, | |
76 |
:titles_only => @titles_only |
|
77 | :titles_only => @titles_only | |
77 | :limit => (limit+1), |
|
78 | ) | |
78 | :offset => offset, |
|
79 | @result_count_by_type[scope] += ranks_and_ids_in_scope.size | |
79 | :before => params[:previous].nil?) |
|
80 | @result_count += ranks_and_ids_in_scope.size | |
80 | @results += r |
|
81 | ranks_and_ids += ranks_and_ids_in_scope.map {|r| [scope, r]} | |
81 | @results_by_type[s] += c |
|
|||
82 | end |
|
82 | end | |
83 | @results = @results.sort {|a,b| b.event_datetime <=> a.event_datetime} |
|
83 | @result_pages = Paginator.new @result_count, limit, params['page'] | |
84 | if params[:previous].nil? |
|
84 | ||
85 | @pagination_previous_date = @results[0].event_datetime if offset && @results[0] |
|
85 | # sort results, higher rank and id first | |
86 | if @results.size > limit |
|
86 | ranks_and_ids.sort! {|a,b| b.last <=> a.last } | |
87 | @pagination_next_date = @results[limit-1].event_datetime |
|
87 | ranks_and_ids = ranks_and_ids[@result_pages.offset, limit] || [] | |
88 | @results = @results[0, limit] |
|
88 | ||
89 | end |
|
89 | # load the results to display | |
90 | else |
|
90 | results_by_scope = Hash.new {|h,k| h[k] = []} | |
91 | @pagination_next_date = @results[-1].event_datetime if offset && @results[-1] |
|
91 | ranks_and_ids.group_by(&:first).each do |scope, rs| | |
92 | if @results.size > limit |
|
92 | klass = scope.singularize.camelcase.constantize | |
93 | @pagination_previous_date = @results[-(limit)].event_datetime |
|
93 | results_by_scope[scope] += klass.search_results_from_ids(rs.map(&:last).map(&:last)) | |
94 | @results = @results[-(limit), limit] |
|
|||
95 | end |
|
|||
96 | end |
|
94 | end | |
|
95 | ||||
|
96 | @results = ranks_and_ids.map do |scope, r| | |||
|
97 | results_by_scope[scope].detect {|record| record.id == r.last} | |||
|
98 | end.compact | |||
97 | else |
|
99 | else | |
98 | @question = "" |
|
100 | @question = "" | |
99 | end |
|
101 | end |
@@ -35,9 +35,9 class Changeset < ActiveRecord::Base | |||||
35 | :url => Proc.new {|o| {:controller => 'repositories', :action => 'revision', :id => o.repository.project, :repository_id => o.repository.identifier_param, :rev => o.identifier}} |
|
35 | :url => Proc.new {|o| {:controller => 'repositories', :action => 'revision', :id => o.repository.project, :repository_id => o.repository.identifier_param, :rev => o.identifier}} | |
36 |
|
36 | |||
37 | acts_as_searchable :columns => 'comments', |
|
37 | acts_as_searchable :columns => 'comments', | |
38 |
: |
|
38 | :preload => {:repository => :project}, | |
39 | :project_key => "#{Repository.table_name}.project_id", |
|
39 | :project_key => "#{Repository.table_name}.project_id", | |
40 |
:date_column => |
|
40 | :date_column => :committed_on | |
41 |
|
41 | |||
42 | acts_as_activity_provider :timestamp => "#{table_name}.committed_on", |
|
42 | acts_as_activity_provider :timestamp => "#{table_name}.committed_on", | |
43 | :author_key => :user_id, |
|
43 | :author_key => :user_id, |
@@ -22,7 +22,7 class Document < ActiveRecord::Base | |||||
22 | acts_as_attachable :delete_permission => :delete_documents |
|
22 | acts_as_attachable :delete_permission => :delete_documents | |
23 |
|
23 | |||
24 | acts_as_searchable :columns => ['title', "#{table_name}.description"], |
|
24 | acts_as_searchable :columns => ['title', "#{table_name}.description"], | |
25 |
: |
|
25 | :preload => :project | |
26 | acts_as_event :title => Proc.new {|o| "#{l(:label_document)}: #{o.title}"}, |
|
26 | acts_as_event :title => Proc.new {|o| "#{l(:label_document)}: #{o.title}"}, | |
27 | :author => Proc.new {|o| o.attachments.reorder("#{Attachment.table_name}.created_on ASC").first.try(:author) }, |
|
27 | :author => Proc.new {|o| o.attachments.reorder("#{Attachment.table_name}.created_on ASC").first.try(:author) }, | |
28 | :url => Proc.new {|o| {:controller => 'documents', :action => 'show', :id => o.id}} |
|
28 | :url => Proc.new {|o| {:controller => 'documents', :action => 'show', :id => o.id}} |
@@ -46,8 +46,7 class Issue < ActiveRecord::Base | |||||
46 | acts_as_customizable |
|
46 | acts_as_customizable | |
47 | acts_as_watchable |
|
47 | acts_as_watchable | |
48 | acts_as_searchable :columns => ['subject', "#{table_name}.description", "#{Journal.table_name}.notes"], |
|
48 | acts_as_searchable :columns => ['subject', "#{table_name}.description", "#{Journal.table_name}.notes"], | |
49 | # sort by id so that limited eager loading doesn't break with postgresql |
|
49 | :preload => [:project, :status, :tracker], | |
50 | :order_column => "#{table_name}.id", |
|
|||
51 | :scope => lambda { joins(:project). |
|
50 | :scope => lambda { joins(:project). | |
52 | joins("LEFT OUTER JOIN #{Journal.table_name} ON #{Journal.table_name}.journalized_type='Issue'" + |
|
51 | joins("LEFT OUTER JOIN #{Journal.table_name} ON #{Journal.table_name}.journalized_type='Issue'" + | |
53 | " AND #{Journal.table_name}.journalized_id = #{Issue.table_name}.id" + |
|
52 | " AND #{Journal.table_name}.journalized_id = #{Issue.table_name}.id" + |
@@ -25,9 +25,9 class Message < ActiveRecord::Base | |||||
25 | attr_protected :id |
|
25 | attr_protected :id | |
26 |
|
26 | |||
27 | acts_as_searchable :columns => ['subject', 'content'], |
|
27 | acts_as_searchable :columns => ['subject', 'content'], | |
28 |
: |
|
28 | :preload => {:board => :project}, | |
29 |
:project_key => "#{Board.table_name}.project_id" |
|
29 | :project_key => "#{Board.table_name}.project_id" | |
30 | :date_column => "#{table_name}.created_on" |
|
30 | ||
31 | acts_as_event :title => Proc.new {|o| "#{o.board.name}: #{o.subject}"}, |
|
31 | acts_as_event :title => Proc.new {|o| "#{o.board.name}: #{o.subject}"}, | |
32 | :description => :content, |
|
32 | :description => :content, | |
33 | :group => :parent, |
|
33 | :group => :parent, |
@@ -29,7 +29,7 class News < ActiveRecord::Base | |||||
29 | acts_as_attachable :edit_permission => :manage_news, |
|
29 | acts_as_attachable :edit_permission => :manage_news, | |
30 | :delete_permission => :manage_news |
|
30 | :delete_permission => :manage_news | |
31 | acts_as_searchable :columns => ['title', 'summary', "#{table_name}.description"], |
|
31 | acts_as_searchable :columns => ['title', 'summary', "#{table_name}.description"], | |
32 |
: |
|
32 | :preload => :project | |
33 | acts_as_event :url => Proc.new {|o| {:controller => 'news', :action => 'show', :id => o.id}} |
|
33 | acts_as_event :url => Proc.new {|o| {:controller => 'news', :action => 'show', :id => o.id}} | |
34 | acts_as_activity_provider :scope => preload(:project, :author), |
|
34 | acts_as_activity_provider :scope => preload(:project, :author), | |
35 | :author_key => :author_id |
|
35 | :author_key => :author_id |
@@ -33,7 +33,8 class WikiPage < ActiveRecord::Base | |||||
33 | :url => Proc.new {|o| {:controller => 'wiki', :action => 'show', :project_id => o.wiki.project, :id => o.title}} |
|
33 | :url => Proc.new {|o| {:controller => 'wiki', :action => 'show', :project_id => o.wiki.project, :id => o.title}} | |
34 |
|
34 | |||
35 | acts_as_searchable :columns => ['title', "#{WikiContent.table_name}.text"], |
|
35 | acts_as_searchable :columns => ['title', "#{WikiContent.table_name}.text"], | |
36 |
:scope => |
|
36 | :scope => joins(:content, {:wiki => :project}), | |
|
37 | :preload => {:wiki => :project}, | |||
37 | :permission => :view_wiki_pages, |
|
38 | :permission => :view_wiki_pages, | |
38 | :project_key => "#{Wiki.table_name}.project_id" |
|
39 | :project_key => "#{Wiki.table_name}.project_id" | |
39 |
|
40 |
@@ -23,9 +23,9 | |||||
23 |
|
23 | |||
24 | <% if @results %> |
|
24 | <% if @results %> | |
25 | <div id="search-results-counts"> |
|
25 | <div id="search-results-counts"> | |
26 |
<%= render_results_by_type(@result |
|
26 | <%= render_results_by_type(@result_count_by_type) unless @scope.size == 1 %> | |
27 | </div> |
|
27 | </div> | |
28 |
<h3><%= l(:label_result_plural) %> (<%= @result |
|
28 | <h3><%= l(:label_result_plural) %> (<%= @result_count %>)</h3> | |
29 | <dl id="search-results"> |
|
29 | <dl id="search-results"> | |
30 | <% @results.each do |e| %> |
|
30 | <% @results.each do |e| %> | |
31 | <dt class="<%= e.event_type %>"> |
|
31 | <dt class="<%= e.event_type %>"> | |
@@ -38,18 +38,9 | |||||
38 | </dl> |
|
38 | </dl> | |
39 | <% end %> |
|
39 | <% end %> | |
40 |
|
40 | |||
41 | <p class="pagination"> |
|
41 | <% if @result_pages %> | |
42 | <% if @pagination_previous_date %> |
|
42 | <p class="pagination"><%= pagination_links_full @result_pages, @result_count, :per_page_links => false %></p> | |
43 | <%= link_to_content_update("\xc2\xab " + l(:label_previous), |
|
|||
44 | params.merge(:previous => 1, |
|
|||
45 | :offset => @pagination_previous_date.strftime("%Y%m%d%H%M%S"))) %> |
|
|||
46 | <% end %> |
|
43 | <% end %> | |
47 | <% if @pagination_next_date %> |
|
|||
48 | <%= link_to_content_update(l(:label_next) + " \xc2\xbb", |
|
|||
49 | params.merge(:previous => nil, |
|
|||
50 | :offset => @pagination_next_date.strftime("%Y%m%d%H%M%S"))) %> |
|
|||
51 | <% end %> |
|
|||
52 | </p> |
|
|||
53 |
|
44 | |||
54 | <% html_title(l(:label_search)) -%> |
|
45 | <% html_title(l(:label_search)) -%> | |
55 |
|
46 |
@@ -23,15 +23,18 module Redmine | |||||
23 | end |
|
23 | end | |
24 |
|
24 | |||
25 | module ClassMethods |
|
25 | module ClassMethods | |
|
26 | # Adds the search methods to the class. | |||
|
27 | # | |||
26 | # Options: |
|
28 | # Options: | |
27 | # * :columns - a column or an array of columns to search |
|
29 | # * :columns - a column or an array of columns to search | |
28 | # * :project_key - project foreign key (default to project_id) |
|
30 | # * :project_key - project foreign key (default to project_id) | |
29 | # * :date_column - name of the datetime column (default to created_on) |
|
31 | # * :date_column - name of the datetime column used to sort results (default to :created_on) | |
30 | # * :sort_order - name of the column used to sort results (default to :date_column or created_on) |
|
32 | # * :permission - permission required to search the model | |
31 | # * :permission - permission required to search the model (default to :view_"objects") |
|
33 | # * :scope - scope used to search results | |
|
34 | # * :preload - associations to preload when loading results for display | |||
32 | def acts_as_searchable(options = {}) |
|
35 | def acts_as_searchable(options = {}) | |
33 | return if self.included_modules.include?(Redmine::Acts::Searchable::InstanceMethods) |
|
36 | return if self.included_modules.include?(Redmine::Acts::Searchable::InstanceMethods) | |
34 |
options.assert_valid_keys(:columns, :project_key, :date_column, |
|
37 | options.assert_valid_keys(:columns, :project_key, :date_column, :permission, :scope, :preload) | |
35 |
|
38 | |||
36 | cattr_accessor :searchable_options |
|
39 | cattr_accessor :searchable_options | |
37 | self.searchable_options = options |
|
40 | self.searchable_options = options | |
@@ -43,8 +46,7 module Redmine | |||||
43 | end |
|
46 | end | |
44 |
|
47 | |||
45 | searchable_options[:project_key] ||= "#{table_name}.project_id" |
|
48 | searchable_options[:project_key] ||= "#{table_name}.project_id" | |
46 |
searchable_options[:date_column] ||= |
|
49 | searchable_options[:date_column] ||= :created_on | |
47 | searchable_options[:order_column] ||= searchable_options[:date_column] |
|
|||
48 |
|
50 | |||
49 | # Should we search custom fields on this model ? |
|
51 | # Should we search custom fields on this model ? | |
50 | searchable_options[:search_custom_fields] = !reflect_on_association(:custom_values).nil? |
|
52 | searchable_options[:search_custom_fields] = !reflect_on_association(:custom_values).nil? | |
@@ -59,23 +61,28 module Redmine | |||||
59 | end |
|
61 | end | |
60 |
|
62 | |||
61 | module ClassMethods |
|
63 | module ClassMethods | |
62 | # Searches the model for the given tokens |
|
64 | # Searches the model for the given tokens and user visibility. | |
63 | # projects argument can be either nil (will search all projects), a project or an array of projects |
|
65 | # The projects argument can be either nil (will search all projects), a project or an array of projects. | |
64 | # Returns the results and the results count |
|
66 | # Returns an array that contains the rank and id of all results. | |
65 | def search(tokens, projects=nil, options={}) |
|
67 | # In current implementation, the rank is the record timestamp. | |
|
68 | # | |||
|
69 | # Valid options: | |||
|
70 | # * :titles_only - searches tokens in the first searchable column only | |||
|
71 | # * :all_words - searches results that match all token | |||
|
72 | # * :limit - maximum number of results to return | |||
|
73 | # | |||
|
74 | # Example: | |||
|
75 | # Issue.search_result_ranks_and_ids("foo") | |||
|
76 | # # => [[Tue, 26 Jun 2007 22:16:00 UTC +00:00, 69], [Mon, 08 Oct 2007 14:31:00 UTC +00:00, 123]] | |||
|
77 | def search_result_ranks_and_ids(tokens, user=User.current, projects=nil, options={}) | |||
66 | if projects.is_a?(Array) && projects.empty? |
|
78 | if projects.is_a?(Array) && projects.empty? | |
67 | # no results |
|
79 | # no results | |
68 |
return [ |
|
80 | return [] | |
69 | end |
|
81 | end | |
70 |
|
82 | |||
71 | # TODO: make user an argument |
|
|||
72 | user = User.current |
|
|||
73 | tokens = [] << tokens unless tokens.is_a?(Array) |
|
83 | tokens = [] << tokens unless tokens.is_a?(Array) | |
74 | projects = [] << projects if projects.is_a?(Project) |
|
84 | projects = [] << projects if projects.is_a?(Project) | |
75 |
|
85 | |||
76 | limit_options = {} |
|
|||
77 | limit_options[:limit] = options[:limit] if options[:limit] |
|
|||
78 |
|
||||
79 | columns = searchable_options[:columns] |
|
86 | columns = searchable_options[:columns] | |
80 | columns = columns[0..0] if options[:titles_only] |
|
87 | columns = columns[0..0] if options[:titles_only] | |
81 |
|
88 | |||
@@ -105,38 +112,39 module Redmine | |||||
105 | if scope.is_a? Proc |
|
112 | if scope.is_a? Proc | |
106 | scope = scope.call |
|
113 | scope = scope.call | |
107 | end |
|
114 | end | |
108 | project_conditions = [] |
|
115 | ||
109 | if searchable_options.has_key?(:permission) |
|
116 | if respond_to?(:visible) && !searchable_options.has_key?(:permission) | |
110 | project_conditions << Project.allowed_to_condition(user, searchable_options[:permission] || :view_project) |
|
|||
111 | elsif respond_to?(:visible) |
|
|||
112 | scope = scope.visible(user) |
|
117 | scope = scope.visible(user) | |
113 | else |
|
118 | else | |
114 | 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." |
|
119 | permission = searchable_options[:permission] || :view_project | |
115 | project_conditions << Project.allowed_to_condition(user, "view_#{self.name.underscore.pluralize}".to_sym) |
|
120 | scope = scope.where(Project.allowed_to_condition(user, permission)) | |
116 | end |
|
121 | end | |
|
122 | ||||
117 | # TODO: use visible scope options instead |
|
123 | # TODO: use visible scope options instead | |
118 | project_conditions << "#{searchable_options[:project_key]} IN (#{projects.collect(&:id).join(',')})" unless projects.nil? |
|
124 | if projects | |
119 | project_conditions = project_conditions.empty? ? nil : project_conditions.join(' AND ') |
|
125 | scope = scope.where("#{searchable_options[:project_key]} IN (?)", projects.map(&:id)) | |
|
126 | end | |||
120 |
|
127 | |||
121 | results = [] |
|
128 | results = [] | |
122 | results_count = 0 |
|
129 | results_count = 0 | |
123 |
|
130 | |||
124 |
|
|
131 | scope. | |
125 |
|
|
132 | reorder(searchable_options[:date_column] => :desc, :id => :desc). | |
126 | order("#{searchable_options[:order_column]} " + (options[:before] ? 'DESC' : 'ASC')). |
|
|||
127 | where(project_conditions). |
|
|||
128 | where(tokens_conditions). |
|
133 | where(tokens_conditions). | |
129 | uniq |
|
134 | limit(options[:limit]). | |
130 |
|
135 | uniq. | ||
131 | results_count = scope.count |
|
136 | pluck(searchable_options[:date_column], :id) | |
|
137 | end | |||
132 |
|
138 | |||
133 | scope_with_limit = scope.limit(options[:limit]) |
|
139 | # Returns search results of given ids | |
134 | if options[:offset] |
|
140 | def search_results_from_ids(ids) | |
135 | scope_with_limit = scope_with_limit.where("#{searchable_options[:date_column]} #{options[:before] ? '<' : '>'} ?", options[:offset]) |
|
141 | where(:id => ids).preload(searchable_options[:preload]).to_a | |
136 |
|
|
142 | end | |
137 | results = scope_with_limit.to_a |
|
|||
138 |
|
143 | |||
139 | [results, results_count] |
|
144 | # Returns search results with same arguments as search_result_ranks_and_ids | |
|
145 | def search_results(*args) | |||
|
146 | ranks_and_ids = search_result_ranks_and_ids(*args) | |||
|
147 | search_results_from_ids(ranks_and_ids.map(&:last)) | |||
140 | end |
|
148 | end | |
141 | end |
|
149 | end | |
142 | end |
|
150 | end |
@@ -75,8 +75,8 class SearchControllerTest < ActionController::TestCase | |||||
75 | assert_select 'dt.issue a', :text => /Add ingredients categories/ |
|
75 | assert_select 'dt.issue a', :text => /Add ingredients categories/ | |
76 | assert_select 'dd', :text => /should be classified by categories/ |
|
76 | assert_select 'dd', :text => /should be classified by categories/ | |
77 |
|
77 | |||
78 |
assert assigns(:result |
|
78 | assert assigns(:result_count_by_type).is_a?(Hash) | |
79 |
assert_equal 5, assigns(:result |
|
79 | assert_equal 5, assigns(:result_count_by_type)['changesets'] | |
80 | assert_select 'a', :text => 'Changesets (5)' |
|
80 | assert_select 'a', :text => 'Changesets (5)' | |
81 | end |
|
81 | end | |
82 |
|
82 | |||
@@ -222,20 +222,24 class SearchControllerTest < ActionController::TestCase | |||||
222 | assert_equal 1, results.size |
|
222 | assert_equal 1, results.size | |
223 | end |
|
223 | end | |
224 |
|
224 | |||
225 |
def test_search_with_ |
|
225 | def test_search_with_pagination | |
226 | get :index, :q => 'coo', :offset => '20080806073000' |
|
226 | issue = (0..24).map {Issue.generate! :subject => 'search_with_limited_results'}.reverse | |
|
227 | ||||
|
228 | get :index, :q => 'search_with_limited_results' | |||
227 | assert_response :success |
|
229 | assert_response :success | |
228 |
|
|
230 | assert_equal issue[0..9], assigns(:results) | |
229 | assert results.any? |
|
|||
230 | assert results.map(&:event_datetime).max < '20080806T073000'.to_time |
|
|||
231 | end |
|
|||
232 |
|
231 | |||
233 | def test_search_previous_with_offset |
|
232 | get :index, :q => 'search_with_limited_results', :page => 2 | |
234 | get :index, :q => 'coo', :offset => '20080806073000', :previous => '1' |
|
|||
235 | assert_response :success |
|
233 | assert_response :success | |
236 |
|
|
234 | assert_equal issue[10..19], assigns(:results) | |
237 | assert results.any? |
|
235 | ||
238 | assert results.map(&:event_datetime).min >= '20080806T073000'.to_time |
|
236 | get :index, :q => 'search_with_limited_results', :page => 3 | |
|
237 | assert_response :success | |||
|
238 | assert_equal issue[20..24], assigns(:results) | |||
|
239 | ||||
|
240 | get :index, :q => 'search_with_limited_results', :page => 4 | |||
|
241 | assert_response :success | |||
|
242 | assert_equal [], assigns(:results) | |||
239 | end |
|
243 | end | |
240 |
|
244 | |||
241 | def test_search_with_invalid_project_id |
|
245 | def test_search_with_invalid_project_id |
@@ -42,25 +42,25 class SearchTest < ActiveSupport::TestCase | |||||
42 | def test_search_by_anonymous |
|
42 | def test_search_by_anonymous | |
43 | User.current = nil |
|
43 | User.current = nil | |
44 |
|
44 | |||
45 |
r = Issue.search(@issue_keyword) |
|
45 | r = Issue.search_results(@issue_keyword) | |
46 | assert r.include?(@issue) |
|
46 | assert r.include?(@issue) | |
47 |
r = Changeset.search(@changeset_keyword) |
|
47 | r = Changeset.search_results(@changeset_keyword) | |
48 | assert r.include?(@changeset) |
|
48 | assert r.include?(@changeset) | |
49 |
|
49 | |||
50 | # Removes the :view_changesets permission from Anonymous role |
|
50 | # Removes the :view_changesets permission from Anonymous role | |
51 | remove_permission Role.anonymous, :view_changesets |
|
51 | remove_permission Role.anonymous, :view_changesets | |
52 | User.current = nil |
|
52 | User.current = nil | |
53 |
|
53 | |||
54 |
r = Issue.search(@issue_keyword) |
|
54 | r = Issue.search_results(@issue_keyword) | |
55 | assert r.include?(@issue) |
|
55 | assert r.include?(@issue) | |
56 |
r = Changeset.search(@changeset_keyword) |
|
56 | r = Changeset.search_results(@changeset_keyword) | |
57 | assert !r.include?(@changeset) |
|
57 | assert !r.include?(@changeset) | |
58 |
|
58 | |||
59 | # Make the project private |
|
59 | # Make the project private | |
60 | @project.update_attribute :is_public, false |
|
60 | @project.update_attribute :is_public, false | |
61 |
r = Issue.search(@issue_keyword) |
|
61 | r = Issue.search_results(@issue_keyword) | |
62 | assert !r.include?(@issue) |
|
62 | assert !r.include?(@issue) | |
63 |
r = Changeset.search(@changeset_keyword) |
|
63 | r = Changeset.search_results(@changeset_keyword) | |
64 | assert !r.include?(@changeset) |
|
64 | assert !r.include?(@changeset) | |
65 | end |
|
65 | end | |
66 |
|
66 | |||
@@ -68,25 +68,25 class SearchTest < ActiveSupport::TestCase | |||||
68 | User.current = User.find_by_login('rhill') |
|
68 | User.current = User.find_by_login('rhill') | |
69 | assert User.current.memberships.empty? |
|
69 | assert User.current.memberships.empty? | |
70 |
|
70 | |||
71 |
r = Issue.search(@issue_keyword) |
|
71 | r = Issue.search_results(@issue_keyword) | |
72 | assert r.include?(@issue) |
|
72 | assert r.include?(@issue) | |
73 |
r = Changeset.search(@changeset_keyword) |
|
73 | r = Changeset.search_results(@changeset_keyword) | |
74 | assert r.include?(@changeset) |
|
74 | assert r.include?(@changeset) | |
75 |
|
75 | |||
76 | # Removes the :view_changesets permission from Non member role |
|
76 | # Removes the :view_changesets permission from Non member role | |
77 | remove_permission Role.non_member, :view_changesets |
|
77 | remove_permission Role.non_member, :view_changesets | |
78 | User.current = User.find_by_login('rhill') |
|
78 | User.current = User.find_by_login('rhill') | |
79 |
|
79 | |||
80 |
r = Issue.search(@issue_keyword) |
|
80 | r = Issue.search_results(@issue_keyword) | |
81 | assert r.include?(@issue) |
|
81 | assert r.include?(@issue) | |
82 |
r = Changeset.search(@changeset_keyword) |
|
82 | r = Changeset.search_results(@changeset_keyword) | |
83 | assert !r.include?(@changeset) |
|
83 | assert !r.include?(@changeset) | |
84 |
|
84 | |||
85 | # Make the project private |
|
85 | # Make the project private | |
86 | @project.update_attribute :is_public, false |
|
86 | @project.update_attribute :is_public, false | |
87 |
r = Issue.search(@issue_keyword) |
|
87 | r = Issue.search_results(@issue_keyword) | |
88 | assert !r.include?(@issue) |
|
88 | assert !r.include?(@issue) | |
89 |
r = Changeset.search(@changeset_keyword) |
|
89 | r = Changeset.search_results(@changeset_keyword) | |
90 | assert !r.include?(@changeset) |
|
90 | assert !r.include?(@changeset) | |
91 | end |
|
91 | end | |
92 |
|
92 | |||
@@ -94,16 +94,16 class SearchTest < ActiveSupport::TestCase | |||||
94 | User.current = User.find_by_login('jsmith') |
|
94 | User.current = User.find_by_login('jsmith') | |
95 | assert User.current.projects.include?(@project) |
|
95 | assert User.current.projects.include?(@project) | |
96 |
|
96 | |||
97 |
r = Issue.search(@issue_keyword) |
|
97 | r = Issue.search_results(@issue_keyword) | |
98 | assert r.include?(@issue) |
|
98 | assert r.include?(@issue) | |
99 |
r = Changeset.search(@changeset_keyword) |
|
99 | r = Changeset.search_results(@changeset_keyword) | |
100 | assert r.include?(@changeset) |
|
100 | assert r.include?(@changeset) | |
101 |
|
101 | |||
102 | # Make the project private |
|
102 | # Make the project private | |
103 | @project.update_attribute :is_public, false |
|
103 | @project.update_attribute :is_public, false | |
104 |
r = Issue.search(@issue_keyword) |
|
104 | r = Issue.search_results(@issue_keyword) | |
105 | assert r.include?(@issue) |
|
105 | assert r.include?(@issue) | |
106 |
r = Changeset.search(@changeset_keyword) |
|
106 | r = Changeset.search_results(@changeset_keyword) | |
107 | assert r.include?(@changeset) |
|
107 | assert r.include?(@changeset) | |
108 | end |
|
108 | end | |
109 |
|
109 | |||
@@ -115,26 +115,26 class SearchTest < ActiveSupport::TestCase | |||||
115 | User.current = User.find_by_login('jsmith') |
|
115 | User.current = User.find_by_login('jsmith') | |
116 | assert User.current.projects.include?(@project) |
|
116 | assert User.current.projects.include?(@project) | |
117 |
|
117 | |||
118 |
r = Issue.search(@issue_keyword) |
|
118 | r = Issue.search_results(@issue_keyword) | |
119 | assert r.include?(@issue) |
|
119 | assert r.include?(@issue) | |
120 |
r = Changeset.search(@changeset_keyword) |
|
120 | r = Changeset.search_results(@changeset_keyword) | |
121 | assert !r.include?(@changeset) |
|
121 | assert !r.include?(@changeset) | |
122 |
|
122 | |||
123 | # Make the project private |
|
123 | # Make the project private | |
124 | @project.update_attribute :is_public, false |
|
124 | @project.update_attribute :is_public, false | |
125 |
r = Issue.search(@issue_keyword) |
|
125 | r = Issue.search_results(@issue_keyword) | |
126 | assert r.include?(@issue) |
|
126 | assert r.include?(@issue) | |
127 |
r = Changeset.search(@changeset_keyword) |
|
127 | r = Changeset.search_results(@changeset_keyword) | |
128 | assert !r.include?(@changeset) |
|
128 | assert !r.include?(@changeset) | |
129 | end |
|
129 | end | |
130 |
|
130 | |||
131 | def test_search_issue_with_multiple_hits_in_journals |
|
131 | def test_search_issue_with_multiple_hits_in_journals | |
132 | i = Issue.find(1) |
|
132 | issue = Issue.find(1) | |
133 | assert_equal 2, i.journals.where("notes LIKE '%notes%'").count |
|
133 | assert_equal 2, issue.journals.where("notes LIKE '%notes%'").count | |
134 |
|
134 | |||
135 |
r = Issue.search('%notes%') |
|
135 | r = Issue.search_results('%notes%') | |
136 | assert_equal 1, r.size |
|
136 | assert_equal 1, r.size | |
137 | assert_equal i, r.first |
|
137 | assert_equal issue, r.first | |
138 | end |
|
138 | end | |
139 |
|
139 | |||
140 | private |
|
140 | private |
General Comments 0
You need to be logged in to leave comments.
Login now