discourse/lib/validators/unique_among_validator.rb
Jarek Radosz a54e3208cb
DEV: Hand-pick Rails/WhereNot autofixes (#35117)
We can't enable `Rails/WhereNot` lint/autofix, because it would break
code that uses mini_sql instead of AR (which rubocop, and tbh also we,
can't easily differentiate)

Those are safe because they either:
* are executed in AR model scope definitions
* are clearly chained starting from a AR model
* are less-clearly chained, but still can be traced to a AR model/scope

---------

Co-authored-by: Loïc Guitaut <loic@discourse.org>
2025-10-03 13:29:22 +02:00

27 lines
988 B
Ruby

# frozen_string_literal: true
class UniqueAmongValidator < ActiveRecord::Validations::UniquenessValidator
def validate_each(record, attribute, value)
old_errors = []
record.errors.each { |error| old_errors << error if error.attribute == attribute }
# look for any duplicates at all
super
new_errors = []
record.errors.each { |error| new_errors << error if error.attribute == attribute }
# do nothing further unless there were some duplicates.
if new_errors.size - old_errors.size != 0
# now look only in the collection we care about.
dupes = options[:collection].call(record).where("lower(#{attribute}) = ?", value.downcase)
dupes = dupes.where.not(id: record.id) if record.persisted?
# pop off the error, if it was a false positive
if !dupes.exists?
record.errors.delete(attribute)
old_errors.each { |error| record.errors.add(error.attribute, error.type, **error.options) }
end
end
end
end