Skip to content
Snippets Groups Projects
with_slug.rb 1.01 KiB
Newer Older
pabois's avatar
pabois committed
module WithSlug
  extend ActiveSupport::Concern

  included do
pabois's avatar
pabois committed
    validates :slug, presence: true
Sébastien Gaya's avatar
Sébastien Gaya committed
    validate :slug_must_be_unique
    validates :slug, format: { with: /\A[a-z0-9\-]+\z/, message: I18n.t('slug_error') }
Arnaud Levy's avatar
Arnaud Levy committed
    before_validation :regenerate_slug, :make_path

    def regenerate_slug
Sébastien Gaya's avatar
Sébastien Gaya committed
      current_slug = self.slug
      n = 0
      while slug_unavailable?(self.slug)
        n += 1
        self.slug = [current_slug, n].join('-')
      end
    end

    def generated_path
      "#{parent&.path}/#{slug}".gsub(/\/+/, '/')
    end

    protected

    def slug_unavailable?(slug)
Arnaud Levy's avatar
Arnaud Levy committed
      self.class.unscoped
                .where(university_id: self.university_id, slug: slug)
                .where.not(id: self.id)
                .exists?
    end

    def make_path
Arnaud Levy's avatar
Arnaud Levy committed
      return unless respond_to?(:path) && respond_to?(:parent)
      self.path = generated_path
Sébastien Gaya's avatar
Sébastien Gaya committed

    def slug_must_be_unique
      errors.add(:slug, ActiveRecord::Errors.default_error_messages[:taken]) if slug_unavailable?(slug)
    end
pabois's avatar
pabois committed
  end
end