comparison app/models/.svn/text-base/custom_field.rb.svn-base @ 0:513646585e45

* Import Redmine trunk SVN rev 3859
author Chris Cannam
date Fri, 23 Jul 2010 15:52:44 +0100
parents
children 8661b858af72
comparison
equal deleted inserted replaced
-1:000000000000 0:513646585e45
1 # redMine - project management software
2 # Copyright (C) 2006 Jean-Philippe Lang
3 #
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
18 class CustomField < ActiveRecord::Base
19 has_many :custom_values, :dependent => :delete_all
20 acts_as_list :scope => 'type = \'#{self.class}\''
21 serialize :possible_values
22
23 validates_presence_of :name, :field_format
24 validates_uniqueness_of :name, :scope => :type
25 validates_length_of :name, :maximum => 30
26 validates_format_of :name, :with => /^[\w\s\.\'\-]*$/i
27 validates_inclusion_of :field_format, :in => Redmine::CustomFieldFormat.available_formats
28
29 def initialize(attributes = nil)
30 super
31 self.possible_values ||= []
32 end
33
34 def before_validation
35 # make sure these fields are not searchable
36 self.searchable = false if %w(int float date bool).include?(field_format)
37 true
38 end
39
40 def validate
41 if self.field_format == "list"
42 errors.add(:possible_values, :blank) if self.possible_values.nil? || self.possible_values.empty?
43 errors.add(:possible_values, :invalid) unless self.possible_values.is_a? Array
44 end
45
46 # validate default value
47 v = CustomValue.new(:custom_field => self.clone, :value => default_value, :customized => nil)
48 v.custom_field.is_required = false
49 errors.add(:default_value, :invalid) unless v.valid?
50 end
51
52 # Makes possible_values accept a multiline string
53 def possible_values=(arg)
54 if arg.is_a?(Array)
55 write_attribute(:possible_values, arg.compact.collect(&:strip).select {|v| !v.blank?})
56 else
57 self.possible_values = arg.to_s.split(/[\n\r]+/)
58 end
59 end
60
61 def cast_value(value)
62 casted = nil
63 unless value.blank?
64 case field_format
65 when 'string', 'text', 'list'
66 casted = value
67 when 'date'
68 casted = begin; value.to_date; rescue; nil end
69 when 'bool'
70 casted = (value == '1' ? true : false)
71 when 'int'
72 casted = value.to_i
73 when 'float'
74 casted = value.to_f
75 end
76 end
77 casted
78 end
79
80 # Returns a ORDER BY clause that can used to sort customized
81 # objects by their value of the custom field.
82 # Returns false, if the custom field can not be used for sorting.
83 def order_statement
84 case field_format
85 when 'string', 'text', 'list', 'date', 'bool'
86 # COALESCE is here to make sure that blank and NULL values are sorted equally
87 "COALESCE((SELECT cv_sort.value FROM #{CustomValue.table_name} cv_sort" +
88 " WHERE cv_sort.customized_type='#{self.class.customized_class.name}'" +
89 " AND cv_sort.customized_id=#{self.class.customized_class.table_name}.id" +
90 " AND cv_sort.custom_field_id=#{id} LIMIT 1), '')"
91 when 'int', 'float'
92 # Make the database cast values into numeric
93 # Postgresql will raise an error if a value can not be casted!
94 # CustomValue validations should ensure that it doesn't occur
95 "(SELECT CAST(cv_sort.value AS decimal(60,3)) FROM #{CustomValue.table_name} cv_sort" +
96 " WHERE cv_sort.customized_type='#{self.class.customized_class.name}'" +
97 " AND cv_sort.customized_id=#{self.class.customized_class.table_name}.id" +
98 " AND cv_sort.custom_field_id=#{id} AND cv_sort.value <> '' AND cv_sort.value IS NOT NULL LIMIT 1)"
99 else
100 nil
101 end
102 end
103
104 def <=>(field)
105 position <=> field.position
106 end
107
108 def self.customized_class
109 self.name =~ /^(.+)CustomField$/
110 begin; $1.constantize; rescue nil; end
111 end
112
113 # to move in project_custom_field
114 def self.for_all
115 find(:all, :conditions => ["is_for_all=?", true], :order => 'position')
116 end
117
118 def type_name
119 nil
120 end
121 end