summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGo MAEDA <maeda@farend.jp>2023-06-29 14:42:54 +0000
committerGo MAEDA <maeda@farend.jp>2023-06-29 14:42:54 +0000
commit945a82b5c0aad6bd6af656865015277d3e0e612b (patch)
treed6bf1c4e7fdf2bb5d32b55ae7e5c0477b31377c9
parentebf3fb3b4fa53f3bc6f9cbbcd529c6b296d4f6fc (diff)
downloadredmine-945a82b5c0aad6bd6af656865015277d3e0e612b.tar.gz
redmine-945a82b5c0aad6bd6af656865015277d3e0e612b.zip
<=> operator should return nil when invoked with an incomparable object (#38772).
Patch by Go MAEDA. git-svn-id: https://svn.redmine.org/redmine/trunk@22269 e93f8b46-1217-0410-a6f0-8f06a7374b81
-rw-r--r--app/models/custom_field.rb2
-rw-r--r--app/models/enumeration.rb2
-rw-r--r--app/models/issue.rb6
-rw-r--r--app/models/issue_category.rb2
-rw-r--r--app/models/issue_relation.rb2
-rw-r--r--app/models/issue_status.rb2
-rw-r--r--app/models/member.rb2
-rw-r--r--app/models/principal.rb8
-rw-r--r--app/models/project.rb2
-rw-r--r--app/models/repository.rb2
-rw-r--r--app/models/role.rb14
-rw-r--r--app/models/tracker.rb2
-rw-r--r--app/models/version.rb2
-rw-r--r--lib/redmine/plugin.rb2
-rw-r--r--lib/redmine/themes.rb2
-rw-r--r--test/unit/enumeration_test.rb6
16 files changed, 45 insertions, 13 deletions
diff --git a/app/models/custom_field.rb b/app/models/custom_field.rb
index 24300c6d2..be9cf550f 100644
--- a/app/models/custom_field.rb
+++ b/app/models/custom_field.rb
@@ -263,6 +263,8 @@ class CustomField < ActiveRecord::Base
end
def <=>(field)
+ return nil unless field.is_a?(CustomField)
+
position <=> field.position
end
diff --git a/app/models/enumeration.rb b/app/models/enumeration.rb
index 762cddc9a..f2f63372a 100644
--- a/app/models/enumeration.rb
+++ b/app/models/enumeration.rb
@@ -91,6 +91,8 @@ class Enumeration < ActiveRecord::Base
end
def <=>(enumeration)
+ return nil unless enumeration.is_a?(Enumeration)
+
position <=> enumeration.position
end
diff --git a/app/models/issue.rb b/app/models/issue.rb
index d6d6c7c8b..e23b02647 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -1435,9 +1435,9 @@ class Issue < ActiveRecord::Base
end
def <=>(issue)
- if issue.nil?
- -1
- elsif root_id != issue.root_id
+ return nil unless issue.is_a?(Issue)
+
+ if root_id != issue.root_id
(root_id || 0) <=> (issue.root_id || 0)
else
(lft || 0) <=> (issue.lft || 0)
diff --git a/app/models/issue_category.rb b/app/models/issue_category.rb
index 626bb1449..eadb44891 100644
--- a/app/models/issue_category.rb
+++ b/app/models/issue_category.rb
@@ -43,6 +43,8 @@ class IssueCategory < ActiveRecord::Base
end
def <=>(category)
+ return nil unless category.is_a?(IssueCategory)
+
name <=> category.name
end
diff --git a/app/models/issue_relation.rb b/app/models/issue_relation.rb
index f33b75568..2caaca9ba 100644
--- a/app/models/issue_relation.rb
+++ b/app/models/issue_relation.rb
@@ -198,6 +198,8 @@ class IssueRelation < ActiveRecord::Base
end
def <=>(relation)
+ return nil unless relation.is_a?(IssueRelation)
+
r = TYPES[self.relation_type][:order] <=> TYPES[relation.relation_type][:order]
r == 0 ? id <=> relation.id : r
end
diff --git a/app/models/issue_status.rb b/app/models/issue_status.rb
index c41e7a739..3080fea8a 100644
--- a/app/models/issue_status.rb
+++ b/app/models/issue_status.rb
@@ -82,6 +82,8 @@ class IssueStatus < ActiveRecord::Base
end
def <=>(status)
+ return nil unless status.is_a?(IssueStatus)
+
position <=> status.position
end
diff --git a/app/models/member.rb b/app/models/member.rb
index 21c623408..9e623d5f3 100644
--- a/app/models/member.rb
+++ b/app/models/member.rb
@@ -81,6 +81,8 @@ class Member < ActiveRecord::Base
end
def <=>(member)
+ return nil unless member.is_a?(Member)
+
a, b = roles.sort, member.roles.sort
if a == b
if principal
diff --git a/app/models/principal.rb b/app/models/principal.rb
index e62b5f320..4cce97e26 100644
--- a/app/models/principal.rb
+++ b/app/models/principal.rb
@@ -151,9 +151,11 @@ class Principal < ActiveRecord::Base
end
def <=>(principal)
- if principal.nil?
- -1
- elsif self.class.name == principal.class.name
+ # avoid an error when sorting members without roles (#10053)
+ return -1 if principal.nil?
+ return nil unless principal.is_a?(Principal)
+
+ if self.class.name == principal.class.name
self.to_s.casecmp(principal.to_s)
else
# groups after users
diff --git a/app/models/project.rb b/app/models/project.rb
index 5f45896fc..11f4a953d 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -671,6 +671,8 @@ class Project < ActiveRecord::Base
end
def <=>(project)
+ return nil unless project.is_a?(Project)
+
name.casecmp(project.name)
end
diff --git a/app/models/repository.rb b/app/models/repository.rb
index be10fa3cf..bc570f2f8 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -141,6 +141,8 @@ class Repository < ActiveRecord::Base
end
def <=>(repository)
+ return nil unless repository.is_a?(Repository)
+
if is_default?
-1
elsif repository.is_default?
diff --git a/app/models/role.rb b/app/models/role.rb
index 604bcd712..078419c60 100644
--- a/app/models/role.rb
+++ b/app/models/role.rb
@@ -155,14 +155,14 @@ class Role < ActiveRecord::Base
end
def <=>(role)
- if role
- if builtin == role.builtin
- position <=> role.position
- else
- builtin <=> role.builtin
- end
+ # returns -1 for nil since r2726
+ return -1 if role.nil?
+ return nil unless role.is_a?(Role)
+
+ if builtin == role.builtin
+ position <=> role.position
else
- -1
+ builtin <=> role.builtin
end
end
diff --git a/app/models/tracker.rb b/app/models/tracker.rb
index bfec75e70..ef2f48b04 100644
--- a/app/models/tracker.rb
+++ b/app/models/tracker.rb
@@ -93,6 +93,8 @@ class Tracker < ActiveRecord::Base
def to_s; name end
def <=>(tracker)
+ return nil unless tracker.is_a?(Tracker)
+
position <=> tracker.position
end
diff --git a/app/models/version.rb b/app/models/version.rb
index f5ac64b74..77228826c 100644
--- a/app/models/version.rb
+++ b/app/models/version.rb
@@ -316,6 +316,8 @@ class Version < ActiveRecord::Base
# Versions are sorted by effective_date and name
# Those with no effective_date are at the end, sorted by name
def <=>(version)
+ return nil unless version.is_a?(Version)
+
if self.effective_date
if version.effective_date
if self.effective_date == version.effective_date
diff --git a/lib/redmine/plugin.rb b/lib/redmine/plugin.rb
index b7f243354..79e310f31 100644
--- a/lib/redmine/plugin.rb
+++ b/lib/redmine/plugin.rb
@@ -187,6 +187,8 @@ module Redmine
end
def <=>(plugin)
+ return nil unless plugin.is_a?(Plugin)
+
self.id.to_s <=> plugin.id.to_s
end
diff --git a/lib/redmine/themes.rb b/lib/redmine/themes.rb
index a73184090..ff51f0083 100644
--- a/lib/redmine/themes.rb
+++ b/lib/redmine/themes.rb
@@ -61,6 +61,8 @@ module Redmine
end
def <=>(theme)
+ return nil unless theme.is_a?(Theme)
+
name <=> theme.name
end
diff --git a/test/unit/enumeration_test.rb b/test/unit/enumeration_test.rb
index 25dfb14c4..a9d0e8eb3 100644
--- a/test/unit/enumeration_test.rb
+++ b/test/unit/enumeration_test.rb
@@ -179,4 +179,10 @@ class EnumerationTest < ActiveSupport::TestCase
override.destroy
assert_equal [1, 2, 3], [a, b, c].map(&:reload).map(&:position)
end
+
+ def test_spaceship_operator_with_incomparable_value_should_return_nil
+ e = Enumeration.first
+ assert_nil e <=> nil
+ assert_nil e <=> 'foo'
+ end
end