macool/id_ecuador

View on GitHub
lib/id_ecuador/model_additions.rb

Summary

Maintainability
B
5 hrs
Test Coverage
# encoding: utf-8

module IdEcuador
  # Módulo que agrega funcionalidad a los modelos de Rails
  # Permite llamar a <tt>validates_id</tt> dentro de un modelo de Rails
  module ModelAdditions

    # @param [Symbol] attribute Atributo que va a validar IdEcuador::Id
    # @param [Hash] options Opciones para la validación
    # @option options [Boolean] :allow_blank Poner (o no) errores si el atributo es nulo
    # @option options [String] :message Mensaje de error que se va a poner en el atributo
    # @option options [Array] :only Tipos de ID que se va a permitir: <tt>[:cedula, :ruc, :sociedad_publica, :sociedad_privada]</tt>
    def validates_id(attribute, options={})

      # parse options:
      defaults = {
        allow_blank: true,
        message: nil,
        only: []
      }
      # options for :only: [:cedula, :ruc, :sociedad_publica, :sociedad_privada]
      options = defaults.merge options

      # transform options[:only] to array if it's not:
      options[:only] = Array options[:only]


      # poner métodos:

      # getter del atributo que siempre retorna una instancia de IdEcuador::Id y se encarga de hacer cache basado en el valor del atributo
      class_eval <<-EVAL
        def #{attribute}_id_validator
          if not @id_ecuador_validator or (send(:#{attribute}) != @id_ecuador_validator_last_id)
            @id_ecuador_validator = IdEcuador::Id.new(send(:#{attribute}))
            @id_ecuador_validator_last_id = send(:#{attribute})
          end
          @id_ecuador_validator
        end
      EVAL

      # extensiones para #tipo_id, #tipo_id_sym y #codigo_provincia
      class_eval <<-EVAL
        def #{attribute}_tipo_id
          #{attribute}_id_validator.tipo_id
        end
        def #{attribute}_tipo_id_sym
          #{attribute}_id_validator.tipo_id_sym
        end
        def #{attribute}_codigo_provincia
          #{attribute}_id_validator.codigo_provincia
        end
      EVAL

      # método de validación
      validate do
        # Agregar error si <tt>allow_blank</tt> es <tt>false</tt> y <tt>attribute</tt> está en blanco
        if not options[:allow_blank] and send(:"#{attribute}").blank?
          errors.add attribute.to_sym, (options[:message] or "No puede quedar en blanco")
        else
          # normal validations:
          if not send(:"#{attribute}").blank? and not send(:"#{attribute}_id_validator").valid?
            if options[:message]
              # poner <tt>options[:message]</tt> si algo está mal
              errors.add attribute.to_sym, options[:message]
            else
              # poner los mensajes por defecto si no hay un <tt>options[:message]</tt>
              send(:"#{attribute}_id_validator").errors.each do |error|
                errors.add attribute.to_sym, error
              end
            end
          end
          # for options:
          if not options[:only].empty? and not send(:"#{attribute}").blank?
            unless options[:only].include?(send(:"#{attribute}_id_validator").tipo_id_sym)
              # si está especificado <tt>options[:only]</tt>, validar que el tipo de ID esté permitido
              errors.add attribute.to_sym, (options[:message] or "Tipo de identificación no permitido")
            end
          end
        end
      end

    end
  end
end