module TagNormalization
extend ActiveSupport::Concern
included do
before_validation :normalize_tag_list
end
private
def normalize_tag_list
return unless respond_to?(:tag_list)
self.tag_list = tag_list.map { |t| t.to_s.downcase.strip.gsub(/ +/, ' ') }
.reject(&:blank?)
.uniq
end
end
Tags are user input, so normalize aggressively: downcase, strip, collapse whitespace, remove duplicates. Doing this at write time keeps search/filter logic clean and avoids messy edge cases.