kaspernj/baza_models

View on GitHub
lib/baza_models/model/validations.rb

Summary

Maintainability
A
1 hr
Test Coverage
module BazaModels::Model::Validations
  def self.included(base)
    base.extend(ClassMethods)
  end

  def valid?
    fire_callbacks(:before_validation)

    if new_record?
      fire_callbacks(:before_validation_on_create)
    else
      fire_callbacks(:before_validation_on_update)
    end

    reset_errors

    validators = self.class.__validators

    merged_data = @data.merge(@changes)
    merged_data.each do |attribute_name, attribute_value|
      next unless validators.key?(attribute_name)

      validators[attribute_name].each do |validator|
        next unless validator.fire?(self)

        validator.validate(self, attribute_value)
      end
    end

    execute_custom_validations
    fire_callbacks(:after_validation)

    if new_record?
      fire_callbacks(:after_validation_on_create)
    else
      fire_callbacks(:after_validation_on_update)
    end

    @errors.empty?
  end

  module ClassMethods
    def validates(*attribute_names, args)
      special_args = {
        if: args.delete(:if)
      }

      attribute_names.each do |attribute_name|
        args.each_key do |validator_name|
          validator_camel_name = StringCases.snake_to_camel(validator_name)
          class_name = "#{validator_camel_name}Validator"

          __validators[attribute_name] ||= []
          __validators[attribute_name] << BazaModels::Validators.const_get(class_name).new(attribute_name, args.merge(special_args))
        end
      end
    end

    def validates_confirmation_of(*args)
      validate_shortcut(:confirmation, args)
    end

    def validates_format_of(*args)
      validate_shortcut(:format, args)
    end

    def validates_length_of(*args)
      validate_shortcut(:length, args)
    end

    def validates_presence_of(*args)
      validate_shortcut(:presence, args)
    end

    def validates_uniqueness_of(*args)
      validate_shortcut(:uniqueness, args)
    end

    def validate_shortcut(type, args)
      if args.last.is_a?(Hash)
        before_opts = args.pop

        opts = {type => before_opts}
        opts[:if] = before_opts.delete(:if) if before_opts.key?(:if)
      else
        opts = {type => true}
      end

      validates(*args, opts)
    end

    def __validators
      @validators ||= {}
    end
  end
end