* Move static profile fields to profiles columns In order to remove some ambiguity around the availability of certain profile fields, we can designate certain fields as "static." These fields are intended to exist on every Forem regardless of configuration; they contain basic personal info that most Forem's will likely use. Because these fields already exist on some Forems it is necessary to migrate the data from existing profile's data column to their respective columns. This change should behave as expected irrespective of the existence of the static fields having associated ProfileFields, however, the UI that is rendered in a user's settings still depends on the presence of the ProfileFields. We can address that in a future change when we are prepared to delete those ProfileFields entirely. We should make sure the migration occurs without issue before moving to that step, in my opinion. * Apply suggestions from code review Co-authored-by: Michael Kohl <me@citizen428.net> * Add clarifying comments Co-authored-by: Michael Kohl <me@citizen428.net> Co-authored-by: Michael Kohl <me@citizen428.net>
71 lines
2.4 KiB
Ruby
71 lines
2.4 KiB
Ruby
class ProfileValidator < ActiveModel::Validator
|
|
SUMMARY_ATTRIBUTE = "summary".freeze
|
|
MAX_SUMMARY_LENGTH = 200
|
|
|
|
MAX_TEXT_AREA_LENGTH = 200
|
|
MAX_TEXT_FIELD_LENGTH = 100
|
|
|
|
HEX_COLOR_REGEXP = /^#?(?:\h{6}|\h{3})$/.freeze
|
|
|
|
ERRORS = {
|
|
color_field: "is not a valid hex color",
|
|
text_area: "is too long (maximum: #{MAX_TEXT_AREA_LENGTH})",
|
|
text_field: "is too long (maximum: #{MAX_TEXT_FIELD_LENGTH})"
|
|
}.with_indifferent_access.freeze
|
|
|
|
def validate(record)
|
|
# NOTE: @citizen428 The summary is a base profile field, which we add to all
|
|
# new Forem instances, so it should be safe to validate. The method itself
|
|
# also guards against the field's absence.
|
|
record.errors.add(:summary, "is too long") if summary_too_long?(record)
|
|
|
|
ProfileField.all.each do |field|
|
|
attribute = field.attribute_name
|
|
next if attribute == SUMMARY_ATTRIBUTE # validated above
|
|
next unless record.respond_to?(attribute) # avoid caching issues
|
|
next if __send__("#{field.input_type}_valid?", record, attribute)
|
|
|
|
record.errors.add(attribute, ERRORS[field.input_type])
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def summary_too_long?(record)
|
|
# Calling the summary attribute method on record during onboarding
|
|
# throws a NoMethodError
|
|
return unless record.respond_to?(SUMMARY_ATTRIBUTE)
|
|
|
|
# TODO: [@jacobherrington] This will need to be addressed when the summary
|
|
# ProfileField is dropped from production.
|
|
return unless ProfileField.exists?(attribute_name: SUMMARY_ATTRIBUTE)
|
|
return if record.summary.blank?
|
|
|
|
# Grandfather in people who had a too long summary before
|
|
# TODO: [@jacobherrington] `record.data_was` can be removed when we delete
|
|
# the old data and drop the fields from `Profile.static_fields`.
|
|
previous_summary = record.summary_was || record.data_was[SUMMARY_ATTRIBUTE]
|
|
return if previous_summary && previous_summary.size > MAX_SUMMARY_LENGTH
|
|
|
|
record.summary.size > MAX_SUMMARY_LENGTH
|
|
end
|
|
|
|
def check_box_valid?(_record, _attribute)
|
|
true # checkboxes are always valid
|
|
end
|
|
|
|
def color_field_valid?(record, attribute)
|
|
hex_value = record.public_send(attribute)
|
|
hex_value.nil? || hex_value.match?(HEX_COLOR_REGEXP)
|
|
end
|
|
|
|
def text_area_valid?(record, attribute)
|
|
text = record.public_send(attribute)
|
|
text.nil? || text.size <= MAX_TEXT_AREA_LENGTH
|
|
end
|
|
|
|
def text_field_valid?(record, attribute)
|
|
text = record.public_send(attribute)
|
|
text.nil? || text.size <= MAX_TEXT_FIELD_LENGTH
|
|
end
|
|
end
|