Class: CustomField

Inherits:
ActiveRecord::Base
  • Object
show all
Includes:
Redmine::SubclassFactory
Defined in:
app/models/custom_field.rb

Overview

Redmine - project management software Copyright (C) 2006-2014 Jean-Philippe Lang

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.

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.

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 Method Summary collapse

Instance Method Summary collapse

Methods included from Redmine::SubclassFactory

included

Class Method Details

.customized_classObject


215
216
217
218
# File 'app/models/custom_field.rb', line 215

def self.customized_class
  self.name =~ /^(.+)CustomField$/
  $1.constantize rescue nil
end

.for_allObject

to move in project_custom_field


221
222
223
# File 'app/models/custom_field.rb', line 221

def self.for_all
  where(:is_for_all => true).order('position').to_a
end

.visibility_conditionObject


193
194
195
196
197
198
199
200
201
202
203
204
# File 'app/models/custom_field.rb', line 193

def self.visibility_condition
  if user.admin?
    "1=1"
  elsif user.anonymous?
    "#{table_name}.visible"
  else
    "#{project_key} IN (SELECT DISTINCT m.project_id FROM #{Member.table_name} m" +
      " INNER JOIN #{MemberRole.table_name} mr ON mr.member_id = m.id" +
      " INNER JOIN #{table_name_prefix}custom_fields_roles#{table_name_suffix} cfr ON cfr.role_id = mr.role_id" +
      " WHERE m.user_id = #{user.id} AND cfr.custom_field_id = #{id})"
  end
end

Instance Method Details

#<=>(field) ⇒ Object


206
207
208
# File 'app/models/custom_field.rb', line 206

def <=>(field)
  position <=> field.position
end

#cast_value(value) ⇒ Object


139
140
141
# File 'app/models/custom_field.rb', line 139

def cast_value(value)
  format.cast_value(self, value)
end

#field_format=(arg) ⇒ Object


69
70
71
72
73
74
75
# File 'app/models/custom_field.rb', line 69

def field_format=(arg)
  # cannot change format of a saved custom field
  if new_record?
    @format = nil
    super
  end
end

#formatObject


65
66
67
# File 'app/models/custom_field.rb', line 65

def format
  @format ||= Redmine::FieldFormat.find(field_format)
end

#format_in?(*args) ⇒ Boolean

Returns:

  • (Boolean)

260
261
262
# File 'app/models/custom_field.rb', line 260

def format_in?(*args)
  args.include?(field_format)
end

#group_statementObject

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.


169
170
171
172
# File 'app/models/custom_field.rb', line 169

def group_statement
  return nil if multiple?
  format.group_statement(self)
end

#join_for_order_statementObject


174
175
176
# File 'app/models/custom_field.rb', line 174

def join_for_order_statement
  format.join_for_order_statement(self)
end

#order_statementObject

Returns a ORDER BY clause that can used to sort customized objects by their value of the custom field. Returns nil if the custom field can not be used for sorting.


162
163
164
165
# File 'app/models/custom_field.rb', line 162

def order_statement
  return nil if multiple?
  format.order_statement(self)
end

#possible_custom_value_options(custom_value) ⇒ Object


105
106
107
# File 'app/models/custom_field.rb', line 105

def possible_custom_value_options(custom_value)
  format.possible_custom_value_options(custom_value)
end

#possible_valuesObject


117
118
119
120
121
122
123
124
125
126
127
# File 'app/models/custom_field.rb', line 117

def possible_values
  values = read_attribute(:possible_values)
  if values.is_a?(Array)
    values.each do |value|
      value.force_encoding('UTF-8')
    end
    values
  else
    []
  end
end

#possible_values=(arg) ⇒ Object

Makes possible_values accept a multiline string


130
131
132
133
134
135
136
137
# File 'app/models/custom_field.rb', line 130

def possible_values=(arg)
  if arg.is_a?(Array)
    values = arg.compact.collect(&:strip).select {|v| !v.blank?}
    write_attribute(:possible_values, values)
  else
    self.possible_values = arg.to_s.split(/[\n\r]+/)
  end
end

#possible_values_options(object = nil) ⇒ Object


109
110
111
112
113
114
115
# File 'app/models/custom_field.rb', line 109

def possible_values_options(object=nil)
  if object.is_a?(Array)
    object.map {|o| format.possible_values_options(self, o)}.reduce(:&) || []
  else
    format.possible_values_options(self, object) || []
  end
end

#set_searchableObject


77
78
79
80
81
82
83
# File 'app/models/custom_field.rb', line 77

def set_searchable  # make sure these fields are not searchable

  self.searchable = false unless format.class.searchable_supported  # make sure only these fields can have multiple values

  self.multiple = false unless format.class.multiple_supported
  true
end

#type_nameObject


225
226
227
# File 'app/models/custom_field.rb', line 225

def type_name
  nil
end

#valid_field_value?(value) ⇒ Boolean

Returns true if value is a valid value for the custom field

Returns:

  • (Boolean)

256
257
258
# File 'app/models/custom_field.rb', line 256

def valid_field_value?(value)
  validate_field_value(value).empty?
end

#validate_custom_fieldObject


85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'app/models/custom_field.rb', line 85

def validate_custom_field
  format.validate_custom_field(self).each do |attribute, message|
    errors.add attribute, message
  end

  if regexp.present?
    begin
      Regexp.new(regexp)
    rescue
      errors.add(:regexp, :invalid)
    end
  end

  if default_value.present?
    validate_field_value(default_value).each do |message|
      errors.add :default_value, message
    end
  end
end

#validate_custom_value(custom_value) ⇒ Object

Returns the error messages for the given value or an empty array if value is a valid value for the custom field


231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
# File 'app/models/custom_field.rb', line 231

def validate_custom_value(custom_value)
  value = custom_value.value
  errs = []
  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
  else
    if is_required? && value.blank?
      errs << ::I18n.t('activerecord.errors.messages.blank')
    end
  end
  errs += format.validate_custom_value(custom_value)
  errs
end

#validate_field_value(value) ⇒ Object

Returns the error messages for the default custom field value


251
252
253
# File 'app/models/custom_field.rb', line 251

def validate_field_value(value)
  validate_custom_value(CustomValue.new(:custom_field => self, :value => value))
end

#value_classObject

Returns the class that values represent


211
212
213
# File 'app/models/custom_field.rb', line 211

def value_class
  format.target_class if format.respond_to?(:target_class)
end

#value_from_keyword(keyword, customized) ⇒ Object


143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'app/models/custom_field.rb', line 143

def value_from_keyword(keyword, customized)
  possible_values_options = possible_values_options(customized)
  if possible_values_options.present?
    keyword = keyword.to_s.downcase
    if v = possible_values_options.detect {|text, id| text.downcase == keyword}
      if v.is_a?(Array)
        v.last
      else
        v
      end
    end
  else
    keyword
  end
end

#visibility_by_project_condition(project_key = nil, user = User.current, id_column = nil) ⇒ Object


178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'app/models/custom_field.rb', line 178

def visibility_by_project_condition(project_key=nil, user=User.current, id_column=nil)
  if visible? || user.admin?
    "1=1"
  elsif user.anonymous?
    "1=0"
  else
    project_key ||= "#{self.class.customized_class.table_name}.project_id"
    id_column ||= id
    "#{project_key} IN (SELECT DISTINCT m.project_id FROM #{Member.table_name} m" +
      " INNER JOIN #{MemberRole.table_name} mr ON mr.member_id = m.id" +
      " INNER JOIN #{table_name_prefix}custom_fields_roles#{table_name_suffix} cfr ON cfr.role_id = mr.role_id" +
      " WHERE m.user_id = #{user.id} AND cfr.custom_field_id = #{id_column})"
  end
end

#visible_by?(project, user = User.current) ⇒ Boolean

Returns:

  • (Boolean)

61
62
63
# File 'app/models/custom_field.rb', line 61

def visible_by?(project, user=User.current)
  visible? || user.admin?
end