From da01ee7c37f2544c84a08a53f7a42f34e5be3877 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Sun, 11 Jan 2009 18:38:07 +0000 Subject: [PATCH] Ability to sort the issue list by text, int and float custom fields (#1139). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@2258 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/models/custom_field.rb | 10 ++++- test/fixtures/custom_fields.yml | 12 ++++++ test/fixtures/custom_fields_trackers.yml | 9 +++++ test/fixtures/custom_values.yml | 48 +++++++++++++++++++----- test/unit/query_test.rb | 16 ++++++++ 5 files changed, 85 insertions(+), 10 deletions(-) diff --git a/app/models/custom_field.rb b/app/models/custom_field.rb index 344f277e..79d12376 100644 --- a/app/models/custom_field.rb +++ b/app/models/custom_field.rb @@ -65,12 +65,20 @@ class CustomField < ActiveRecord::Base # Returns false, if the custom field can not be used for sorting. def order_statement case field_format - when 'string', 'list', 'date', 'bool' + when 'string', 'text', '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), '')" + when 'int', 'float' + # Make the database cast values into numeric + # Postgresql will raise an error if a value can not be casted! + # CustomValue validations should ensure that it doesn't occur + "(SELECT CAST(cv_sort.value AS decimal(60,3)) 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} AND cv_sort.value <> '' AND cv_sort.value IS NOT NULL LIMIT 1)" else nil end diff --git a/test/fixtures/custom_fields.yml b/test/fixtures/custom_fields.yml index 1005edae..b7718b16 100644 --- a/test/fixtures/custom_fields.yml +++ b/test/fixtures/custom_fields.yml @@ -69,4 +69,16 @@ custom_fields_005: is_required: false field_format: float default_value: "" +custom_fields_006: + name: Float field + min_length: 0 + regexp: "" + is_for_all: true + type: IssueCustomField + max_length: 0 + possible_values: "" + id: 6 + is_required: false + field_format: float + default_value: "" \ No newline at end of file diff --git a/test/fixtures/custom_fields_trackers.yml b/test/fixtures/custom_fields_trackers.yml index cb06d2fc..bfbe0d24 100644 --- a/test/fixtures/custom_fields_trackers.yml +++ b/test/fixtures/custom_fields_trackers.yml @@ -8,3 +8,12 @@ custom_fields_trackers_002: custom_fields_trackers_003: custom_field_id: 2 tracker_id: 3 +custom_fields_trackers_004: + custom_field_id: 6 + tracker_id: 1 +custom_fields_trackers_005: + custom_field_id: 6 + tracker_id: 2 +custom_fields_trackers_006: + custom_field_id: 6 + tracker_id: 3 diff --git a/test/fixtures/custom_values.yml b/test/fixtures/custom_values.yml index 57214288..0e2b454a 100644 --- a/test/fixtures/custom_values.yml +++ b/test/fixtures/custom_values.yml @@ -3,54 +3,84 @@ custom_values_006: customized_type: Issue custom_field_id: 2 customized_id: 3 - id: 9 + id: 6 value: "125" custom_values_007: customized_type: Project custom_field_id: 3 customized_id: 1 - id: 10 + id: 7 value: Stable custom_values_001: customized_type: User custom_field_id: 4 customized_id: 3 - id: 2 + id: 1 value: "" custom_values_002: customized_type: User custom_field_id: 4 customized_id: 4 - id: 3 + id: 2 value: 01 23 45 67 89 custom_values_003: customized_type: User custom_field_id: 4 customized_id: 2 - id: 4 + id: 3 value: "" custom_values_004: customized_type: Issue custom_field_id: 2 customized_id: 1 - id: 7 + id: 4 value: "125" custom_values_005: customized_type: Issue custom_field_id: 2 customized_id: 2 - id: 8 + id: 5 value: "" custom_values_008: customized_type: Issue custom_field_id: 1 customized_id: 3 - id: 11 + id: 8 value: "MySQL" custom_values_009: customized_type: Issue custom_field_id: 2 customized_id: 3 - id: 12 + id: 9 value: "this is a stringforcustomfield search" +custom_values_010: + customized_type: Issue + custom_field_id: 6 + customized_id: 1 + id: 10 + value: "2.1" +custom_values_011: + customized_type: Issue + custom_field_id: 6 + customized_id: 2 + id: 11 + value: "2.05" +custom_values_012: + customized_type: Issue + custom_field_id: 6 + customized_id: 3 + id: 12 + value: "11.65" +custom_values_013: + customized_type: Issue + custom_field_id: 6 + customized_id: 7 + id: 13 + value: "" +custom_values_014: + customized_type: Issue + custom_field_id: 6 + customized_id: 5 + id: 14 + value: "-7.6" \ No newline at end of file diff --git a/test/unit/query_test.rb b/test/unit/query_test.rb index f4b25e51..3bdc4a7a 100644 --- a/test/unit/query_test.rb +++ b/test/unit/query_test.rb @@ -185,6 +185,7 @@ class QueryTest < Test::Unit::TestCase :conditions => q.statement, :order => "#{c.sortable} ASC" values = issues.collect {|i| i.custom_value_for(c.custom_field).to_s} + assert !values.empty? assert_equal values.sort, values end @@ -198,9 +199,24 @@ class QueryTest < Test::Unit::TestCase :conditions => q.statement, :order => "#{c.sortable} DESC" values = issues.collect {|i| i.custom_value_for(c.custom_field).to_s} + assert !values.empty? assert_equal values.sort.reverse, values end + def test_sort_by_float_custom_field_asc + q = Query.new + c = q.available_columns.find {|col| col.is_a?(QueryCustomFieldColumn) && col.custom_field.field_format == 'float' } + 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| begin; Kernel.Float(i.custom_value_for(c.custom_field).to_s); rescue; nil; end}.compact + assert !values.empty? + assert_equal values.sort, values + end + def test_label_for q = Query.new assert_equal 'assigned_to', q.label_for('assigned_to_id')