43 lines
1.4 KiB
Ruby
43 lines
1.4 KiB
Ruby
##
|
|
# Validates if the give attribute is used across the reserved spaces.
|
|
class UniqueCrossModelSlugValidator < ActiveModel::EachValidator
|
|
class_attribute :model_and_attribute_name_for_uniqueness_test
|
|
|
|
# Why a class attribute? Allow for other implementations to extend
|
|
# this behavior.
|
|
self.model_and_attribute_name_for_uniqueness_test = {
|
|
Organization => :slug,
|
|
Page => :slug,
|
|
Podcast => :slug,
|
|
User => :username
|
|
}
|
|
|
|
def validate_each(record, attribute, value)
|
|
return unless already_exists?(value: value, record: record)
|
|
|
|
record.errors.add(attribute, options[:message] || I18n.t("validators.unique_cross_model_slug_validator.is_taken"))
|
|
end
|
|
|
|
private
|
|
|
|
##
|
|
# Answers the question if it's okay for the record to use the given value.
|
|
#
|
|
# @param value [String] the value we're to check in the various classes
|
|
# @param record [ActiveRecord::Base] the record that we're attempting to validate
|
|
#
|
|
# @return [TrueClass] if the value already exists across the various classes.
|
|
# @return [FalseClass] if the given value is not already used.
|
|
#
|
|
# @see CLASS_AND_ATTRIBUTE_NAME_FOR_UNIQUENESS_TEST
|
|
def already_exists?(value:, record:)
|
|
return false unless value
|
|
return true if value.include?("sitemap-")
|
|
|
|
model_and_attribute_name_for_uniqueness_test.detect do |model, attribute|
|
|
next if record.is_a?(model)
|
|
|
|
model.exists?(attribute => value)
|
|
end
|
|
end
|
|
end
|