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-2016 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

Class Method Details

.customized_classObject

Since:

  • 0.9.0



217
218
219
220
# File 'app/models/custom_field.rb', line 217

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

.for_allObject

to move in project_custom_field



223
224
225
# File 'app/models/custom_field.rb', line 223

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



266
267
268
269
270
271
272
# File 'app/models/custom_field.rb', line 266

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

.visibility_conditionObject

Deprecated.

Removed at 4.0.0

Since:

  • 2.4.0



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

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

Since:

  • 0.6.1



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

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

#cast_value(value) ⇒ Object

Since:

  • 0.9.0



144
145
146
# File 'app/models/custom_field.rb', line 144

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

#field_format=(arg) ⇒ Object

Since:

  • 2.2.0



74
75
76
77
78
79
80
# File 'app/models/custom_field.rb', line 74

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



70
71
72
# File 'app/models/custom_field.rb', line 70

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

#format_in?(*args) ⇒ Boolean

Returns:

  • (Boolean)

Since:

  • 2.1.0



262
263
264
# File 'app/models/custom_field.rb', line 262

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.

Since:

  • 2.1.0



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

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

#join_for_order_statementObject

Since:

  • 2.1.0



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

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



164
165
166
167
# File 'app/models/custom_field.rb', line 164

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

#possible_custom_value_options(custom_value) ⇒ Object

Since:

  • 2.5.0



110
111
112
# File 'app/models/custom_field.rb', line 110

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

#possible_valuesObject

Since:

  • 1.2.0



122
123
124
125
126
127
128
129
130
131
132
# File 'app/models/custom_field.rb', line 122

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



135
136
137
138
139
140
141
142
# File 'app/models/custom_field.rb', line 135

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



114
115
116
117
118
119
120
# File 'app/models/custom_field.rb', line 114

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



153
154
155
# File 'app/models/custom_field.rb', line 153

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

#set_searchableObject

Since:

  • 1.4.0



82
83
84
85
86
87
88
# File 'app/models/custom_field.rb', line 82

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



157
158
159
# File 'app/models/custom_field.rb', line 157

def totalable?
  format.totalable_supported
end

#type_nameObject



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

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



258
259
260
# File 'app/models/custom_field.rb', line 258

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

#validate_custom_fieldObject

Since:

  • 1.4.0



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'app/models/custom_field.rb', line 90

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



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

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

Since:

  • 1.4.0



253
254
255
# File 'app/models/custom_field.rb', line 253

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



213
214
215
# File 'app/models/custom_field.rb', line 213

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

#value_from_keyword(keyword, customized) ⇒ Object

Since:

  • 2.1.0



148
149
150
# File 'app/models/custom_field.rb', line 148

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



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

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



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

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