IT61/it61-rails

View on GitHub
lib/permalink_for/slug_implementation.rb

Summary

Maintainability
A
45 mins
Test Coverage
module PermalinkFor
  module SlugImplementation
    extend ActiveSupport::Concern

    module ClassMethods
      def permalink_validation_opts
        return super if defined?(super)
        {
          presence: true,
          uniqueness: true,
          format: { with: /\A[a-z0-9_-]+\Z/ },
        }
      end
    end

    included do
      validates :permalink, permalink_validation_opts
      before_validation :build_permalink
    end

    def to_param
      return permalink if permalink.present?
      id
    end

    # rubocop:disable Metrics/AbcSize
    # rubocop:disable Metrics/PerceivedComplexity
    def build_permalink
      target_field_value = send(permalink_configuration[:target_field])

      return if permalink.present? || target_field_value.blank?
      permalink_base = I18n.transliterate(target_field_value).parameterize.downcase
      permalink_candidate = permalink_base
      generated_permalink = nil

      attempts_number = 100
      attempts = attempts_number
      while attempts.positive? && generated_permalink.nil?
        if self.class.find_by(permalink: permalink_candidate)
          attempts -= 1
          permalink_candidate = permalink_base + (attempts_number - attempts).to_s
        else
          generated_permalink = permalink_candidate
        end
      end

      fail "Failed to generate permalink" if generated_permalink.nil?
      self.permalink = generated_permalink
    end

    module ClassMethods
      def find(id)
        if id.is_a?(Array) || id.is_a?(Integer) || (id.is_a?(String) && id[/^\d+$/])
          super
        else
          find_by!(permalink: id.to_s.downcase)
        end
      end
    end
  end
end