]> source.dussan.org Git - redmine.git/commitdiff
Ability to sort the issue list by text, list, date and boolean custom fields (#1139).
authorJean-Philippe Lang <jp_lang@yahoo.fr>
Sun, 11 Jan 2009 16:33:51 +0000 (16:33 +0000)
committerJean-Philippe Lang <jp_lang@yahoo.fr>
Sun, 11 Jan 2009 16:33:51 +0000 (16:33 +0000)
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@2257 e93f8b46-1217-0410-a6f0-8f06a7374b81

app/models/custom_field.rb
app/models/custom_value.rb
app/models/query.rb
test/unit/query_test.rb

index 4759b714bbdf74f7050b0672d13652f50a084ea2..344f277e4f1bfb7554f8c5d4785cd5fd8b9a0436 100644 (file)
@@ -59,11 +59,32 @@ class CustomField < ActiveRecord::Base
     v.custom_field.is_required = false
     errors.add(:default_value, :activerecord_error_invalid) unless v.valid?
   end
+  
+  # Returns a ORDER BY clause that can used to sort customized
+  # objects by their value of the custom field.
+  # Returns false, if the custom field can not be used for sorting.
+  def order_statement
+    case field_format
+      when 'string', 'list', 'date', 'bool'
+        # COALESCE is here to make sure that blank and NULL values are sorted equally
+        "COALESCE((SELECT cv_sort.value FROM #{CustomValue.table_name} cv_sort" + 
+          " WHERE cv_sort.customized_type='#{self.class.customized_class.name}'" +
+          " AND cv_sort.customized_id=#{self.class.customized_class.table_name}.id" +
+          " AND cv_sort.custom_field_id=#{id} LIMIT 1), '')"
+      else
+        nil
+    end
+  end
 
   def <=>(field)
     position <=> field.position
   end
   
+  def self.customized_class
+    self.name =~ /^(.+)CustomField$/
+    begin; $1.constantize; rescue nil; end
+  end
+  
   # to move in project_custom_field
   def self.for_all
     find(:all, :conditions => ["is_for_all=?", true], :order => 'position')
index 1d453baf01fb613004bba30bf608a082b14e5d52..085d242faa3f2f0332efa52528ee48f68f2ccf27 100644 (file)
@@ -30,6 +30,10 @@ class CustomValue < ActiveRecord::Base
     self.value == '1'
   end
   
+  def to_s
+    value.to_s
+  end
+  
 protected
   def validate
     if value.blank?
index 1a4845975cce33f8030c62647c4772995d16b225..0016cb24bf9ed50448395ae26fcb08ca3c48fdf1 100644 (file)
@@ -35,7 +35,7 @@ class QueryCustomFieldColumn < QueryColumn
 
   def initialize(custom_field)
     self.name = "cf_#{custom_field.id}".to_sym
-    self.sortable = false
+    self.sortable = custom_field.order_statement || false
     @cf = custom_field
   end
   
index ac3e3cadc8e8f0577c1d1a628cff7bf6c21d10f3..f4b25e51b72070bf5f988e2585092170898eb510 100644 (file)
@@ -175,6 +175,32 @@ class QueryTest < Test::Unit::TestCase
     assert q.has_column?(c)
   end
   
+  def test_sort_by_string_custom_field_asc
+    q = Query.new
+    c = q.available_columns.find {|col| col.is_a?(QueryCustomFieldColumn) && col.custom_field.field_format == 'string' }
+    assert c
+    assert c.sortable
+    issues = Issue.find :all,
+                        :include => [ :assigned_to, :status, :tracker, :project, :priority ], 
+                        :conditions => q.statement,
+                        :order => "#{c.sortable} ASC"
+    values = issues.collect {|i| i.custom_value_for(c.custom_field).to_s}
+    assert_equal values.sort, values
+  end
+  
+  def test_sort_by_string_custom_field_desc
+    q = Query.new
+    c = q.available_columns.find {|col| col.is_a?(QueryCustomFieldColumn) && col.custom_field.field_format == 'string' }
+    assert c
+    assert c.sortable
+    issues = Issue.find :all,
+                        :include => [ :assigned_to, :status, :tracker, :project, :priority ], 
+                        :conditions => q.statement,
+                        :order => "#{c.sortable} DESC"
+    values = issues.collect {|i| i.custom_value_for(c.custom_field).to_s}
+    assert_equal values.sort.reverse, values
+  end
+  
   def test_label_for
     q = Query.new
     assert_equal 'assigned_to', q.label_for('assigned_to_id')