* Page unique_cross_model_slug seems misconfigured * Update validator test * More verbose invalid attribute message * Try dynamic model/attribute registration * Rubocop * Use the cross-model-slug existence check * Register with the dynamic cross-model-slug checker * Cleanup * Add missing keys to fr * Update format regex * Adjust validation: always presence, unique if changed * Tests can create reserved-word pages when they need to * Slugs can be mixed case? * Case-sensitive is better, actually * Refactor to use CrossModel check * Refactor, rename for clarity * Refactor, avoid mocking oneself * Refactor, injectable everything * Add reservedword check to extracted exists? checker * Move to concerns * Without dynamic registration * extend when needed * Cleanup comments, remove registration references --------- Co-authored-by: Goran <gorang.pub@gmail.com>
37 lines
1.3 KiB
Ruby
37 lines
1.3 KiB
Ruby
#
|
|
# We have a simple top-level route equivalent to `/slug`. Because of this,
|
|
# we want to verify that newly created records don't overlap with a previously-
|
|
# defined `slug` -- in other words, slug values should be unique across all
|
|
# relevant models. Except also, models might use "username" instead of "slug".
|
|
#
|
|
# "Slug-like" models are all included in a cross-model-uniqueness check. An
|
|
# impacted models are checked for the existence of a record matching a given
|
|
# value. Additionally, we have some special cases (eg, sitemap) that we want to
|
|
# apply across all registered models.
|
|
#
|
|
class CrossModelSlug
|
|
MODELS = {
|
|
"User" => :username,
|
|
"Page" => :slug,
|
|
"Podcast" => :slug,
|
|
"Organization" => :slug
|
|
}.freeze
|
|
|
|
class << self
|
|
def exists?(value)
|
|
# Presence check is likely redundant, but is **much** cheaper than the
|
|
# cross-model check
|
|
return false if value.blank?
|
|
|
|
value = value.downcase
|
|
|
|
# Reserved check may be redundant, but allows this to be used outside of Validator
|
|
return true if ReservedWords.all.include?(value)
|
|
return true if value.include?("sitemap-") # https://github.com/forem/forem/pull/6704
|
|
|
|
MODELS.detect do |class_name, attribute|
|
|
class_name.constantize.exists?({ attribute => value })
|
|
end
|
|
end
|
|
end
|
|
end
|