##// END OF EJS Templates
Rails3: model: replace deprecated before_validation method at CustomField model...
Toshi MARUYAMA -
r8071:f1994ea9c082
parent child
Show More
@@ -1,163 +1,164
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2011 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 CustomField < ActiveRecord::Base
19 19 include Redmine::SubclassFactory
20 20
21 21 has_many :custom_values, :dependent => :delete_all
22 22 acts_as_list :scope => 'type = \'#{self.class}\''
23 23 serialize :possible_values
24 24
25 25 validates_presence_of :name, :field_format
26 26 validates_uniqueness_of :name, :scope => :type
27 27 validates_length_of :name, :maximum => 30
28 28 validates_inclusion_of :field_format, :in => Redmine::CustomFieldFormat.available_formats
29 29
30 30 validate :validate_values
31 before_validation :set_searchable
31 32
32 33 def initialize(attributes = nil)
33 34 super
34 35 self.possible_values ||= []
35 36 end
36 37
37 def before_validation
38 def set_searchable
38 39 # make sure these fields are not searchable
39 40 self.searchable = false if %w(int float date bool).include?(field_format)
40 41 true
41 42 end
42 43
43 44 def validate_values
44 45 if self.field_format == "list"
45 46 errors.add(:possible_values, :blank) if self.possible_values.nil? || self.possible_values.empty?
46 47 errors.add(:possible_values, :invalid) unless self.possible_values.is_a? Array
47 48 end
48 49
49 50 if regexp.present?
50 51 begin
51 52 Regexp.new(regexp)
52 53 rescue
53 54 errors.add(:regexp, :invalid)
54 55 end
55 56 end
56 57
57 58 # validate default value
58 59 v = CustomValue.new(:custom_field => self.clone, :value => default_value, :customized => nil)
59 60 v.custom_field.is_required = false
60 61 errors.add(:default_value, :invalid) unless v.valid?
61 62 end
62 63
63 64 def possible_values_options(obj=nil)
64 65 case field_format
65 66 when 'user', 'version'
66 67 if obj.respond_to?(:project) && obj.project
67 68 case field_format
68 69 when 'user'
69 70 obj.project.users.sort.collect {|u| [u.to_s, u.id.to_s]}
70 71 when 'version'
71 72 obj.project.shared_versions.sort.collect {|u| [u.to_s, u.id.to_s]}
72 73 end
73 74 elsif obj.is_a?(Array)
74 75 obj.collect {|o| possible_values_options(o)}.inject {|memo, v| memo & v}
75 76 else
76 77 []
77 78 end
78 79 else
79 80 read_attribute :possible_values
80 81 end
81 82 end
82 83
83 84 def possible_values(obj=nil)
84 85 case field_format
85 86 when 'user', 'version'
86 87 possible_values_options(obj).collect(&:last)
87 88 else
88 89 read_attribute :possible_values
89 90 end
90 91 end
91 92
92 93 # Makes possible_values accept a multiline string
93 94 def possible_values=(arg)
94 95 if arg.is_a?(Array)
95 96 write_attribute(:possible_values, arg.compact.collect(&:strip).select {|v| !v.blank?})
96 97 else
97 98 self.possible_values = arg.to_s.split(/[\n\r]+/)
98 99 end
99 100 end
100 101
101 102 def cast_value(value)
102 103 casted = nil
103 104 unless value.blank?
104 105 case field_format
105 106 when 'string', 'text', 'list'
106 107 casted = value
107 108 when 'date'
108 109 casted = begin; value.to_date; rescue; nil end
109 110 when 'bool'
110 111 casted = (value == '1' ? true : false)
111 112 when 'int'
112 113 casted = value.to_i
113 114 when 'float'
114 115 casted = value.to_f
115 116 when 'user', 'version'
116 117 casted = (value.blank? ? nil : field_format.classify.constantize.find_by_id(value.to_i))
117 118 end
118 119 end
119 120 casted
120 121 end
121 122
122 123 # Returns a ORDER BY clause that can used to sort customized
123 124 # objects by their value of the custom field.
124 125 # Returns false, if the custom field can not be used for sorting.
125 126 def order_statement
126 127 case field_format
127 128 when 'string', 'text', 'list', 'date', 'bool'
128 129 # COALESCE is here to make sure that blank and NULL values are sorted equally
129 130 "COALESCE((SELECT cv_sort.value FROM #{CustomValue.table_name} cv_sort" +
130 131 " WHERE cv_sort.customized_type='#{self.class.customized_class.name}'" +
131 132 " AND cv_sort.customized_id=#{self.class.customized_class.table_name}.id" +
132 133 " AND cv_sort.custom_field_id=#{id} LIMIT 1), '')"
133 134 when 'int', 'float'
134 135 # Make the database cast values into numeric
135 136 # Postgresql will raise an error if a value can not be casted!
136 137 # CustomValue validations should ensure that it doesn't occur
137 138 "(SELECT CAST(cv_sort.value AS decimal(60,3)) FROM #{CustomValue.table_name} cv_sort" +
138 139 " WHERE cv_sort.customized_type='#{self.class.customized_class.name}'" +
139 140 " AND cv_sort.customized_id=#{self.class.customized_class.table_name}.id" +
140 141 " AND cv_sort.custom_field_id=#{id} AND cv_sort.value <> '' AND cv_sort.value IS NOT NULL LIMIT 1)"
141 142 else
142 143 nil
143 144 end
144 145 end
145 146
146 147 def <=>(field)
147 148 position <=> field.position
148 149 end
149 150
150 151 def self.customized_class
151 152 self.name =~ /^(.+)CustomField$/
152 153 begin; $1.constantize; rescue nil; end
153 154 end
154 155
155 156 # to move in project_custom_field
156 157 def self.for_all
157 158 find(:all, :conditions => ["is_for_all=?", true], :order => 'position')
158 159 end
159 160
160 161 def type_name
161 162 nil
162 163 end
163 164 end
General Comments 0
You need to be logged in to leave comments. Login now