##// END OF EJS Templates
Update the issue subject when choosing an issue from the drop down menu....
Update the issue subject when choosing an issue from the drop down menu. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@11083 e93f8b46-1217-0410-a6f0-8f06a7374b81

File last commit:

r10763:0a773bcbb3ec
r10853:6be315c1ff8e
Show More
custom_field.rb
328 lines | 11.1 KiB | text/x-ruby | RubyLexer
Jean-Philippe Lang
Adds User and Version custom field format that can be used to reference a project member or version in custom fields (#2096)....
r5152 # Redmine - project management software
Jean-Philippe Lang
Extracts custom field values validation from CustomValue so that they can be validated globally from the customized object (#1189)....
r8597 # Copyright (C) 2006-2012 Jean-Philippe Lang
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 #
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
Toshi MARUYAMA
remove trailing white-spaces from app/models/custom_field.rb....
r6393 #
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
Toshi MARUYAMA
remove trailing white-spaces from app/models/custom_field.rb....
r6393 #
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class CustomField < ActiveRecord::Base
Jean-Philippe Lang
Extracted new_subclass_instance method to a module....
r8063 include Redmine::SubclassFactory
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 has_many :custom_values, :dependent => :delete_all
Jean-Philippe Lang
Custom fields can now be reordered....
r888 acts_as_list :scope => 'type = \'#{self.class}\''
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 serialize :possible_values
Toshi MARUYAMA
remove trailing white-spaces from app/models/custom_field.rb....
r6393
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 validates_presence_of :name, :field_format
Jean-Philippe Lang
Allow same name for custom fields on different object types....
r1729 validates_uniqueness_of :name, :scope => :type
Jean-Philippe Lang
Added several validates_length_of...
r590 validates_length_of :name, :maximum => 30
Eric Davis
Replace the hardcoded CustomField::FIELD_FORMATS with a class....
r3558 validates_inclusion_of :field_format, :in => Redmine::CustomFieldFormat.available_formats
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330
Jean-Philippe Lang
Extracts custom field values validation from CustomValue so that they can be validated globally from the customized object (#1189)....
r8597 validate :validate_custom_field
Toshi MARUYAMA
Rails3: model: replace deprecated before_validation method at CustomField model...
r8071 before_validation :set_searchable
Toshi MARUYAMA
Rails3: replace deprecated 'validate' method at CustomField model....
r6792
Jean-Baptiste Barth
Use lambda form in model scopes (#12499)...
r10722 scope :sorted, lambda { order("#{table_name}.position ASC") }
Jean-Philippe Lang
Replaces find(:all) calls....
r10689
Toshi MARUYAMA
move CustomFieldsHelper tabs variable to model constant for common use (#12018)...
r10343 CUSTOM_FIELDS_TABS = [
{:name => 'IssueCustomField', :partial => 'custom_fields/index',
:label => :label_issue_plural},
{:name => 'TimeEntryCustomField', :partial => 'custom_fields/index',
:label => :label_spent_time},
{:name => 'ProjectCustomField', :partial => 'custom_fields/index',
:label => :label_project_plural},
{:name => 'VersionCustomField', :partial => 'custom_fields/index',
:label => :label_version_plural},
{:name => 'UserCustomField', :partial => 'custom_fields/index',
:label => :label_user_plural},
{:name => 'GroupCustomField', :partial => 'custom_fields/index',
:label => :label_group_plural},
{:name => 'TimeEntryActivityCustomField', :partial => 'custom_fields/index',
:label => TimeEntryActivity::OptionName},
{:name => 'IssuePriorityCustomField', :partial => 'custom_fields/index',
:label => IssuePriority::OptionName},
{:name => 'DocumentCategoryCustomField', :partial => 'custom_fields/index',
:label => DocumentCategory::OptionName}
]
Toshi MARUYAMA
sort custom field issue filter by type and position (#12018)...
r10344 CUSTOM_FIELDS_NAMES = CUSTOM_FIELDS_TABS.collect{|v| v[:name]}
Jean-Philippe Lang
Make sure that custom field format cannot be changed....
r10413 def field_format=(arg)
# cannot change format of a saved custom field
super if new_record?
end
Toshi MARUYAMA
Rails3: model: replace deprecated before_validation method at CustomField model...
r8071 def set_searchable
Jean-Philippe Lang
Search engine: issue custom fields can now be searched....
r981 # make sure these fields are not searchable
self.searchable = false if %w(int float date bool).include?(field_format)
Jean-Philippe Lang
Adds support for multiselect custom fields (#1189)....
r8601 # make sure only these fields can have multiple values
self.multiple = false unless %w(list user version).include?(field_format)
Jean-Philippe Lang
Fixed: can not save numeric, date and boolean custom fields (broken by r994)....
r983 true
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 end
Toshi MARUYAMA
remove trailing white-spaces from app/models/custom_field.rb....
r6393
Jean-Philippe Lang
Extracts custom field values validation from CustomValue so that they can be validated globally from the customized object (#1189)....
r8597 def validate_custom_field
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 if self.field_format == "list"
Jean-Philippe Lang
Merged Rails 2.2 branch. Redmine now requires Rails 2.2.2....
r2430 errors.add(:possible_values, :blank) if self.possible_values.nil? || self.possible_values.empty?
errors.add(:possible_values, :invalid) unless self.possible_values.is_a? Array
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 end
Toshi MARUYAMA
remove trailing white-spaces from app/models/custom_field.rb....
r6393
Jean-Philippe Lang
Validate custom field regexp (#8865)....
r6178 if regexp.present?
begin
Regexp.new(regexp)
rescue
errors.add(:regexp, :invalid)
end
end
Toshi MARUYAMA
remove trailing white-spaces from app/models/custom_field.rb....
r6393
Jean-Philippe Lang
Do not validate blank default custom field value....
r8602 if default_value.present? && !valid_field_value?(default_value)
Jean-Philippe Lang
Extracts custom field values validation from CustomValue so that they can be validated globally from the customized object (#1189)....
r8597 errors.add(:default_value, :invalid)
end
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 end
Toshi MARUYAMA
remove trailing white-spaces from app/models/custom_field.rb....
r6393
Jean-Philippe Lang
Adds User and Version custom field format that can be used to reference a project member or version in custom fields (#2096)....
r5152 def possible_values_options(obj=nil)
case field_format
when 'user', 'version'
Jean-Philippe Lang
Fixes #possible_values_options when given an object with nil project....
r5153 if obj.respond_to?(:project) && obj.project
Jean-Philippe Lang
Adds User and Version custom field format that can be used to reference a project member or version in custom fields (#2096)....
r5152 case field_format
when 'user'
obj.project.users.sort.collect {|u| [u.to_s, u.id.to_s]}
when 'version'
Jean-Philippe Lang
Fixed: Custom 'version' field don't show shared versions (#8615)....
r7652 obj.project.shared_versions.sort.collect {|u| [u.to_s, u.id.to_s]}
Jean-Philippe Lang
Adds User and Version custom field format that can be used to reference a project member or version in custom fields (#2096)....
r5152 end
Jean-Philippe Lang
Fixed: empty list for user/version custom fields on bulk edit form (#2096)....
r5234 elsif obj.is_a?(Array)
Jean-Philippe Lang
Use #reduce instead of #inject for getting the intersection of arrays....
r8707 obj.collect {|o| possible_values_options(o)}.reduce(:&)
Jean-Philippe Lang
Adds User and Version custom field format that can be used to reference a project member or version in custom fields (#2096)....
r5152 else
[]
end
Jean-Philippe Lang
Bulk-edit custom fields through context menu (#6296)....
r8704 when 'bool'
[[l(:general_text_Yes), '1'], [l(:general_text_No), '0']]
Jean-Philippe Lang
Adds User and Version custom field format that can be used to reference a project member or version in custom fields (#2096)....
r5152 else
Jean-Philippe Lang
Merged rails-3.2 branch....
r9346 possible_values || []
Jean-Philippe Lang
Adds User and Version custom field format that can be used to reference a project member or version in custom fields (#2096)....
r5152 end
end
Toshi MARUYAMA
remove trailing white-spaces from app/models/custom_field.rb....
r6393
Jean-Philippe Lang
Adds User and Version custom field format that can be used to reference a project member or version in custom fields (#2096)....
r5152 def possible_values(obj=nil)
case field_format
Jean-Philippe Lang
Fixes #possible_values for version custom field....
r5233 when 'user', 'version'
Jean-Philippe Lang
Adds User and Version custom field format that can be used to reference a project member or version in custom fields (#2096)....
r5152 possible_values_options(obj).collect(&:last)
Jean-Philippe Lang
Bulk-edit custom fields through context menu (#6296)....
r8704 when 'bool'
['1', '0']
Jean-Philippe Lang
Adds User and Version custom field format that can be used to reference a project member or version in custom fields (#2096)....
r5152 else
Jean-Philippe Lang
Merged rails-3.2 branch....
r9346 values = super()
if values.is_a?(Array)
values.each do |value|
value.force_encoding('UTF-8') if value.respond_to?(:force_encoding)
end
end
Jean-Philippe Lang
Code cleanup....
r9723 values || []
Jean-Philippe Lang
Adds User and Version custom field format that can be used to reference a project member or version in custom fields (#2096)....
r5152 end
end
Toshi MARUYAMA
remove trailing white-spaces from app/models/custom_field.rb....
r6393
Jean-Philippe Lang
Use a textarea for custom fields possible values (#2472)....
r2265 # Makes possible_values accept a multiline string
def possible_values=(arg)
if arg.is_a?(Array)
Jean-Philippe Lang
Merged rails-3.2 branch....
r9346 super(arg.compact.collect(&:strip).select {|v| !v.blank?})
Jean-Philippe Lang
Use a textarea for custom fields possible values (#2472)....
r2265 else
self.possible_values = arg.to_s.split(/[\n\r]+/)
end
end
Toshi MARUYAMA
remove trailing white-spaces from app/models/custom_field.rb....
r6393
Jean-Philippe Lang
Fixed: "None" category issue count is empty while grouping by category (#4308)....
r2998 def cast_value(value)
casted = nil
unless value.blank?
case field_format
when 'string', 'text', 'list'
casted = value
when 'date'
casted = begin; value.to_date; rescue; nil end
when 'bool'
casted = (value == '1' ? true : false)
when 'int'
casted = value.to_i
when 'float'
casted = value.to_f
Jean-Philippe Lang
Adds User and Version custom field format that can be used to reference a project member or version in custom fields (#2096)....
r5152 when 'user', 'version'
casted = (value.blank? ? nil : field_format.classify.constantize.find_by_id(value.to_i))
Jean-Philippe Lang
Fixed: "None" category issue count is empty while grouping by category (#4308)....
r2998 end
end
casted
end
Toshi MARUYAMA
remove trailing white-spaces from app/models/custom_field.rb....
r6393
Jean-Philippe Lang
Fixed: Custom fields of type version not proper handled in receiving e-mails (#11571)....
r9974 def value_from_keyword(keyword, customized)
possible_values_options = possible_values_options(customized)
if possible_values_options.present?
keyword = keyword.to_s.downcase
Jean-Philippe Lang
Fixed that validation fails when receiving an email with list custom fields (#12400)....
r10763 if v = possible_values_options.detect {|text, id| text.downcase == keyword}
if v.is_a?(Array)
v.last
else
v
end
end
Jean-Philippe Lang
Fixed: Custom fields of type version not proper handled in receiving e-mails (#11571)....
r9974 else
keyword
end
end
Jean-Philippe Lang
Ability to sort the issue list by text, list, date and boolean custom fields (#1139)....
r2255 # Returns a ORDER BY clause that can used to sort customized
# objects by their value of the custom field.
Jean-Philippe Lang
Adds CustomField#group_statement....
r9888 # Returns nil if the custom field can not be used for sorting.
Jean-Philippe Lang
Ability to sort the issue list by text, list, date and boolean custom fields (#1139)....
r2255 def order_statement
Jean-Philippe Lang
Adds support for multiselect custom fields (#1189)....
r8601 return nil if multiple?
Jean-Philippe Lang
Ability to sort the issue list by text, list, date and boolean custom fields (#1139)....
r2255 case field_format
Jean-Philippe Lang
Ability to sort the issue list by text, int and float custom fields (#1139)....
r2256 when 'string', 'text', 'list', 'date', 'bool'
Jean-Philippe Lang
Ability to sort the issue list by text, list, date and boolean custom fields (#1139)....
r2255 # COALESCE is here to make sure that blank and NULL values are sorted equally
Toshi MARUYAMA
remove trailing white-spaces from app/models/custom_field.rb....
r6393 "COALESCE((SELECT cv_sort.value FROM #{CustomValue.table_name} cv_sort" +
Etienne Massip
Use base class name as customized type to fix @UserCustomField#order_statement@....
r9697 " WHERE cv_sort.customized_type='#{self.class.customized_class.base_class.name}'" +
Jean-Philippe Lang
Ability to sort the issue list by text, list, date and boolean custom fields (#1139)....
r2255 " AND cv_sort.customized_id=#{self.class.customized_class.table_name}.id" +
" AND cv_sort.custom_field_id=#{id} LIMIT 1), '')"
Jean-Philippe Lang
Ability to sort the issue list by text, int and float custom fields (#1139)....
r2256 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
Toshi MARUYAMA
remove trailing white-spaces from app/models/custom_field.rb....
r6393 "(SELECT CAST(cv_sort.value AS decimal(60,3)) FROM #{CustomValue.table_name} cv_sort" +
Etienne Massip
Use base class name as customized type to fix @UserCustomField#order_statement@....
r9697 " WHERE cv_sort.customized_type='#{self.class.customized_class.base_class.name}'" +
Jean-Philippe Lang
Ability to sort the issue list by text, int and float custom fields (#1139)....
r2256 " 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)"
Jean-Philippe Lang
Ability to group and sort the issue list by user/version custom field (#9419)....
r9890 when 'user', 'version'
value_class.fields_for_order_statement(value_join_alias)
Jean-Philippe Lang
Ability to sort the issue list by text, list, date and boolean custom fields (#1139)....
r2255 else
nil
end
end
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330
Jean-Philippe Lang
Adds CustomField#group_statement....
r9888 # Returns a GROUP BY clause that can used to group by custom value
# Returns nil if the custom field can not be used for grouping.
def group_statement
return nil if multiple?
case field_format
when 'list', 'date', 'bool', 'int'
order_statement
Jean-Philippe Lang
Ability to group and sort the issue list by user/version custom field (#9419)....
r9890 when 'user', 'version'
"COALESCE((SELECT cv_sort.value FROM #{CustomValue.table_name} cv_sort" +
" WHERE cv_sort.customized_type='#{self.class.customized_class.base_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 join_for_order_statement
case field_format
when 'user', 'version'
"LEFT OUTER JOIN #{CustomValue.table_name} #{join_alias}" +
" ON #{join_alias}.customized_type = '#{self.class.customized_class.base_class.name}'" +
" AND #{join_alias}.customized_id = #{self.class.customized_class.table_name}.id" +
" AND #{join_alias}.custom_field_id = #{id}" +
" AND #{join_alias}.value <> ''" +
" AND #{join_alias}.id = (SELECT max(#{join_alias}_2.id) FROM #{CustomValue.table_name} #{join_alias}_2" +
" WHERE #{join_alias}_2.customized_type = #{join_alias}.customized_type" +
" AND #{join_alias}_2.customized_id = #{join_alias}.customized_id" +
" AND #{join_alias}_2.custom_field_id = #{join_alias}.custom_field_id)" +
" LEFT OUTER JOIN #{value_class.table_name} #{value_join_alias}" +
" ON CAST(#{join_alias}.value as decimal(60,0)) = #{value_join_alias}.id"
Jean-Philippe Lang
Adds CustomField#group_statement....
r9888 else
nil
end
end
Jean-Philippe Lang
Ability to group and sort the issue list by user/version custom field (#9419)....
r9890 def join_alias
"cf_#{id}"
end
def value_join_alias
join_alias + "_" + field_format
end
Jean-Philippe Lang
Custom fields can now be reordered....
r888 def <=>(field)
position <=> field.position
end
Toshi MARUYAMA
remove trailing white-spaces from app/models/custom_field.rb....
r6393
Jean-Philippe Lang
Ability to group and sort the issue list by user/version custom field (#9419)....
r9890 # Returns the class that values represent
def value_class
case field_format
when 'user', 'version'
field_format.classify.constantize
else
nil
end
end
Jean-Philippe Lang
Ability to sort the issue list by text, list, date and boolean custom fields (#1139)....
r2255 def self.customized_class
self.name =~ /^(.+)CustomField$/
begin; $1.constantize; rescue nil; end
end
Toshi MARUYAMA
remove trailing white-spaces from app/models/custom_field.rb....
r6393
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 # to move in project_custom_field
def self.for_all
Jean-Philippe Lang
Replaces find(:all) calls....
r10690 where(:is_for_all => true).order('position').all
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 end
Toshi MARUYAMA
remove trailing white-spaces from app/models/custom_field.rb....
r6393
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 def type_name
nil
end
Jean-Philippe Lang
Extracts custom field values validation from CustomValue so that they can be validated globally from the customized object (#1189)....
r8597
Jean-Philippe Lang
Adds support for multiselect custom fields (#1189)....
r8601 # Returns the error messages for the given value
Jean-Philippe Lang
Extracts custom field values validation from CustomValue so that they can be validated globally from the customized object (#1189)....
r8597 # or an empty array if value is a valid value for the custom field
def validate_field_value(value)
errs = []
Jean-Philippe Lang
Adds support for multiselect custom fields (#1189)....
r8601 if value.is_a?(Array)
if !multiple?
errs << ::I18n.t('activerecord.errors.messages.invalid')
end
if is_required? && value.detect(&:present?).nil?
errs << ::I18n.t('activerecord.errors.messages.blank')
end
value.each {|v| errs += validate_field_value_format(v)}
else
if is_required? && value.blank?
errs << ::I18n.t('activerecord.errors.messages.blank')
end
errs += validate_field_value_format(value)
Jean-Philippe Lang
Extracts custom field values validation from CustomValue so that they can be validated globally from the customized object (#1189)....
r8597 end
errs
end
# Returns true if value is a valid value for the custom field
def valid_field_value?(value)
validate_field_value(value).empty?
end
Jean-Philippe Lang
Update the new custom field form with remotely....
r9980 def format_in?(*args)
args.include?(field_format)
end
Jean-Philippe Lang
Extracts custom field values validation from CustomValue so that they can be validated globally from the customized object (#1189)....
r8597 protected
# Returns the error message for the given value regarding its format
def validate_field_value_format(value)
errs = []
if value.present?
errs << ::I18n.t('activerecord.errors.messages.invalid') unless regexp.blank? or value =~ Regexp.new(regexp)
errs << ::I18n.t('activerecord.errors.messages.too_short', :count => min_length) if min_length > 0 and value.length < min_length
errs << ::I18n.t('activerecord.errors.messages.too_long', :count => max_length) if max_length > 0 and value.length > max_length
# Format specific validations
case field_format
when 'int'
errs << ::I18n.t('activerecord.errors.messages.not_a_number') unless value =~ /^[+-]?\d+$/
when 'float'
begin; Kernel.Float(value); rescue; errs << ::I18n.t('activerecord.errors.messages.invalid') end
when 'date'
errs << ::I18n.t('activerecord.errors.messages.not_a_date') unless value =~ /^\d{4}-\d{2}-\d{2}$/ && begin; value.to_date; rescue; false end
when 'list'
errs << ::I18n.t('activerecord.errors.messages.inclusion') unless possible_values.include?(value)
end
end
errs
end
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 end