##// END OF EJS Templates
Merged r10801 from trunk (#12349)....
Jean-Philippe Lang -
r10592:ab69845ea23e
parent child
Show More
@@ -1,95 +1,95
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 class Principal < ActiveRecord::Base
19 19 self.table_name = "#{table_name_prefix}users#{table_name_suffix}"
20 20
21 21 has_many :members, :foreign_key => 'user_id', :dependent => :destroy
22 22 has_many :memberships, :class_name => 'Member', :foreign_key => 'user_id', :include => [ :project, :roles ], :conditions => "#{Project.table_name}.status<>#{Project::STATUS_ARCHIVED}", :order => "#{Project.table_name}.name"
23 23 has_many :projects, :through => :memberships
24 24 has_many :issue_categories, :foreign_key => 'assigned_to_id', :dependent => :nullify
25 25
26 26 # Groups and active users
27 27 scope :active, :conditions => "#{Principal.table_name}.status = 1"
28 28
29 29 scope :like, lambda {|q|
30 30 if q.blank?
31 31 {}
32 32 else
33 q = q.to_s.downcase
33 q = q.to_s
34 34 pattern = "%#{q}%"
35 sql = "LOWER(login) LIKE :p OR LOWER(firstname) LIKE :p OR LOWER(lastname) LIKE :p OR LOWER(mail) LIKE :p"
35 sql = "LOWER(login) LIKE LOWER(:p) OR LOWER(firstname) LIKE LOWER(:p) OR LOWER(lastname) LIKE LOWER(:p) OR LOWER(mail) LIKE LOWER(:p)"
36 36 params = {:p => pattern}
37 37 if q =~ /^(.+)\s+(.+)$/
38 38 a, b = "#{$1}%", "#{$2}%"
39 sql << " OR (LOWER(firstname) LIKE :a AND LOWER(lastname) LIKE :b) OR (LOWER(firstname) LIKE :b AND LOWER(lastname) LIKE :a)"
39 sql << " OR (LOWER(firstname) LIKE LOWER(:a) AND LOWER(lastname) LIKE LOWER(:b)) OR (LOWER(firstname) LIKE LOWER(:b) AND LOWER(lastname) LIKE LOWER(:a))"
40 40 params.merge!(:a => a, :b => b)
41 41 end
42 42 {:conditions => [sql, params]}
43 43 end
44 44 }
45 45
46 46 # Principals that are members of a collection of projects
47 47 scope :member_of, lambda {|projects|
48 48 projects = [projects] unless projects.is_a?(Array)
49 49 if projects.empty?
50 50 {:conditions => "1=0"}
51 51 else
52 52 ids = projects.map(&:id)
53 53 {:conditions => ["#{Principal.table_name}.status = 1 AND #{Principal.table_name}.id IN (SELECT DISTINCT user_id FROM #{Member.table_name} WHERE project_id IN (?))", ids]}
54 54 end
55 55 }
56 56 # Principals that are not members of projects
57 57 scope :not_member_of, lambda {|projects|
58 58 projects = [projects] unless projects.is_a?(Array)
59 59 if projects.empty?
60 60 {:conditions => "1=0"}
61 61 else
62 62 ids = projects.map(&:id)
63 63 {:conditions => ["#{Principal.table_name}.id NOT IN (SELECT DISTINCT user_id FROM #{Member.table_name} WHERE project_id IN (?))", ids]}
64 64 end
65 65 }
66 66
67 67 before_create :set_default_empty_values
68 68
69 69 def name(formatter = nil)
70 70 to_s
71 71 end
72 72
73 73 def <=>(principal)
74 74 if principal.nil?
75 75 -1
76 76 elsif self.class.name == principal.class.name
77 77 self.to_s.downcase <=> principal.to_s.downcase
78 78 else
79 79 # groups after users
80 80 principal.class.name <=> self.class.name
81 81 end
82 82 end
83 83
84 84 protected
85 85
86 86 # Make sure we don't try to insert NULL values (see #4632)
87 87 def set_default_empty_values
88 88 self.login ||= ''
89 89 self.hashed_password ||= ''
90 90 self.firstname ||= ''
91 91 self.lastname ||= ''
92 92 self.mail ||= ''
93 93 true
94 94 end
95 95 end
@@ -1,109 +1,118
1 # encoding: utf-8
2 #
1 3 # Redmine - project management software
2 4 # Copyright (C) 2006-2012 Jean-Philippe Lang
3 5 #
4 6 # This program is free software; you can redistribute it and/or
5 7 # modify it under the terms of the GNU General Public License
6 8 # as published by the Free Software Foundation; either version 2
7 9 # of the License, or (at your option) any later version.
8 10 #
9 11 # This program is distributed in the hope that it will be useful,
10 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 14 # GNU General Public License for more details.
13 15 #
14 16 # You should have received a copy of the GNU General Public License
15 17 # along with this program; if not, write to the Free Software
16 18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 19
18 20 require File.expand_path('../../test_helper', __FILE__)
19 21
20 22 class PrincipalTest < ActiveSupport::TestCase
21 23 fixtures :users, :projects, :members, :member_roles
22 24
23 25 def test_active_scope_should_return_groups_and_active_users
24 26 result = Principal.active.all
25 27 assert_include Group.first, result
26 28 assert_not_nil result.detect {|p| p.is_a?(User)}
27 29 assert_nil result.detect {|p| p.is_a?(User) && !p.active?}
28 30 assert_nil result.detect {|p| p.is_a?(AnonymousUser)}
29 31 end
30 32
31 33 def test_member_of_scope_should_return_the_union_of_all_members
32 34 projects = Project.find_all_by_id(1, 2)
33 35 assert_equal projects.map(&:principals).flatten.sort, Principal.member_of(projects).sort
34 36 end
35 37
36 38 def test_member_of_scope_should_be_empty_for_no_projects
37 39 assert_equal [], Principal.member_of([]).sort
38 40 end
39 41
40 42 def test_not_member_of_scope_should_return_users_that_have_no_memberships
41 43 projects = Project.find_all_by_id(1, 2)
42 44 expected = (Principal.all - projects.map(&:memberships).flatten.map(&:principal)).sort
43 45 assert_equal expected, Principal.not_member_of(projects).sort
44 46 end
45 47
46 48 def test_not_member_of_scope_should_be_empty_for_no_projects
47 49 assert_equal [], Principal.not_member_of([]).sort
48 50 end
49 51
50 52 context "#like" do
51 53 setup do
52 54 Principal.create!(:login => 'login')
53 55 Principal.create!(:login => 'login2')
54 56
55 57 Principal.create!(:firstname => 'firstname')
56 58 Principal.create!(:firstname => 'firstname2')
57 59
58 60 Principal.create!(:lastname => 'lastname')
59 61 Principal.create!(:lastname => 'lastname2')
60 62
61 63 Principal.create!(:mail => 'mail@example.com')
62 64 Principal.create!(:mail => 'mail2@example.com')
63 65
64 66 @palmer = Principal.create!(:firstname => 'David', :lastname => 'Palmer')
65 67 end
66 68
67 69 should "search login" do
68 70 results = Principal.like('login')
69 71
70 72 assert_equal 2, results.count
71 73 assert results.all? {|u| u.login.match(/login/) }
72 74 end
73 75
74 76 should "search firstname" do
75 77 results = Principal.like('firstname')
76 78
77 79 assert_equal 2, results.count
78 80 assert results.all? {|u| u.firstname.match(/firstname/) }
79 81 end
80 82
81 83 should "search lastname" do
82 84 results = Principal.like('lastname')
83 85
84 86 assert_equal 2, results.count
85 87 assert results.all? {|u| u.lastname.match(/lastname/) }
86 88 end
87 89
88 90 should "search mail" do
89 91 results = Principal.like('mail')
90 92
91 93 assert_equal 2, results.count
92 94 assert results.all? {|u| u.mail.match(/mail/) }
93 95 end
94 96
95 97 should "search firstname and lastname" do
96 98 results = Principal.like('david palm')
97 99
98 100 assert_equal 1, results.count
99 101 assert_equal @palmer, results.first
100 102 end
101 103
102 104 should "search lastname and firstname" do
103 105 results = Principal.like('palmer davi')
104 106
105 107 assert_equal 1, results.count
106 108 assert_equal @palmer, results.first
107 109 end
108 110 end
111
112 def test_like_scope_with_cyrillic_name
113 user = User.generate!(:firstname => 'Соболев', :lastname => 'Денис')
114 results = Principal.like('Собо')
115 assert_equal 1, results.count
116 assert_equal user, results.first
117 end
109 118 end
General Comments 0
You need to be logged in to leave comments. Login now