Class: CustomField

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

Overview

Redmine - project management software Copyright (C) 2006-2017 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.

Since:

  • 0.4.0

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Redmine::SafeAttributes

#delete_unsafe_attributes, #safe_attribute?, #safe_attribute_names, #safe_attributes=

Class Method Details

.customized_classObject

Since:

  • 0.9.0



236
237
238
239
# File 'app/models/custom_field.rb', line 236

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

.for_allObject

to move in project_custom_field



242
243
244
# File 'app/models/custom_field.rb', line 242

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

.human_attribute_name(attribute_key_name, *args) ⇒ Object

Since:

  • 3.2.3



292
293
294
295
296
297
298
# File 'app/models/custom_field.rb', line 292

def self.human_attribute_name(attribute_key_name, *args)
  attr_name = attribute_key_name.to_s
  if attr_name == 'url_pattern'
    attr_name = "url"
  end
  super(attr_name, *args)
end

Instance Method Details

#<=>(field) ⇒ Object

Since:

  • 0.6.1



227
228
229
# File 'app/models/custom_field.rb', line 227

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

#after_save_custom_value(custom_value) ⇒ Object

Since:

  • 3.4.0



284
285
286
# File 'app/models/custom_field.rb', line 284

def after_save_custom_value(custom_value)
  format.after_save_custom_value(self, custom_value)
end

#cast_value(value) ⇒ Object

Since:

  • 0.9.0



172
173
174
# File 'app/models/custom_field.rb', line 172

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

#field_format=(arg) ⇒ Object

Since:

  • 2.2.0



98
99
100
101
102
103
104
# File 'app/models/custom_field.rb', line 98

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

#formatObject

Since:

  • 2.5.0



94
95
96
# File 'app/models/custom_field.rb', line 94

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

#format_in?(*args) ⇒ Boolean

Returns:

  • (Boolean)

Since:

  • 2.1.0



288
289
290
# File 'app/models/custom_field.rb', line 288

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

#full_width_layout?Boolean

Returns:

  • (Boolean)

Since:

  • 3.4.0



189
190
191
# File 'app/models/custom_field.rb', line 189

def full_width_layout?
  full_width_layout == '1'
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.

Since:

  • 2.1.0



203
204
205
206
# File 'app/models/custom_field.rb', line 203

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

#join_for_order_statementObject

Since:

  • 2.1.0



208
209
210
# File 'app/models/custom_field.rb', line 208

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.

Since:

  • 0.9.0



196
197
198
199
# File 'app/models/custom_field.rb', line 196

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

#possible_custom_value_options(custom_value) ⇒ Object

Since:

  • 2.5.0



134
135
136
# File 'app/models/custom_field.rb', line 134

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

#possible_valuesObject

Since:

  • 1.2.0



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

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

#possible_values=(arg) ⇒ Object

Makes possible_values accept a multiline string

Since:

  • 0.9.0



159
160
161
162
163
164
165
166
# File 'app/models/custom_field.rb', line 159

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

#possible_values_options(object = nil) ⇒ Object

Since:

  • 1.2.0



138
139
140
141
142
143
144
# File 'app/models/custom_field.rb', line 138

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

#query_filter_options(query) ⇒ Object

Returns the options hash used to build a query filter for the field

Since:

  • 3.2.0



181
182
183
# File 'app/models/custom_field.rb', line 181

def query_filter_options(query)
  format.query_filter_options(self, query)
end

#set_custom_field_value(custom_field_value, value) ⇒ Object

Since:

  • 3.4.0



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

def set_custom_field_value(custom_field_value, value)
  format.set_custom_field_value(self, custom_field_value, value)
end

#set_searchableObject

Since:

  • 1.4.0



106
107
108
109
110
111
112
# File 'app/models/custom_field.rb', line 106

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

#totalable?Boolean

Returns:

  • (Boolean)

Since:

  • 3.2.0



185
186
187
# File 'app/models/custom_field.rb', line 185

def totalable?
  format.totalable_supported
end

#type_nameObject



246
247
248
# File 'app/models/custom_field.rb', line 246

def type_name
  nil
end

#valid_field_value?(value) ⇒ Boolean

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

Returns:

  • (Boolean)

Since:

  • 1.4.0



280
281
282
# File 'app/models/custom_field.rb', line 280

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

#validate_custom_fieldObject

Since:

  • 1.4.0



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'app/models/custom_field.rb', line 114

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

Since:

  • 2.5.0



252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
# File 'app/models/custom_field.rb', line 252

def validate_custom_value(custom_value)
  value = custom_value.value
  errs = format.validate_custom_value(custom_value)

  unless errs.any?
    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
  end

  errs
end

#validate_field_value(value) ⇒ Object

Returns the error messages for the default custom field value

Since:

  • 1.4.0



275
276
277
# File 'app/models/custom_field.rb', line 275

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

#value_classObject

Returns the class that values represent

Since:

  • 2.1.0



232
233
234
# File 'app/models/custom_field.rb', line 232

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

#value_from_keyword(keyword, customized) ⇒ Object

Since:

  • 2.1.0



176
177
178
# File 'app/models/custom_field.rb', line 176

def value_from_keyword(keyword, customized)
  format.value_from_keyword(self, keyword, customized)
end

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

Since:

  • 2.4.0



212
213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'app/models/custom_field.rb', line 212

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)

Since:

  • 2.4.0



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

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