Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
uoy-faculty-sinatra / lib / sinatra / validator.rb
Size: Mime:
# frozen_string_literal: true

require 'sinatra/flash'
require 'sinatra/param'

# Top-level module documentation comment goes here...
module Sinatra
  # Shared helpers for validating parameters and forms
  module Validator
    # Helpers for Sinatra
    module Helpers
      def filter_params
        # Filter params, replace empty strings/arrays with nil
        params.each do |(param, value)|
          params[param] = nil if value == ''
          params[param] = [nil] if value == ['']
        end
      rescue StandardError => e
        raise "Filter params failed: #{e}"
      end

      def validate(validator, args)
        validator.context = self
        validator.run(*args)
        validator.handle_failure unless validator.success?
      end
    end

    # A validator for a form. Essentially holds a list of methods to call and their arguments for parameter validation.
    class Validator
      VALID_METHODS = %i[block param one_of any_of].freeze
      attr_writer :context

      def initialize(definition)
        @definition = definition
        clear
      end

      def method_missing(name, *args, &block)
        super unless VALID_METHODS.include? name

        @methods.push({ name: name, args: args, block: block })
      end

      def respond_to_missing?(method, *)
        VALID_METHODS.include?(method) || super
      end

      def run(*args)
        clear
        save_params_copy
        run_definition(*args)
        @methods.each do |method|
          run_method method
        rescue Sinatra::Param::InvalidParameterError => e
          save_method_error method, e
        end
      end

      def success?
        @errors.empty?
      end

      def handle_failure
        raise 'Validation Failed'
      end

      private

      def clear
        @methods = []
        @errors = {}
      end

      # Run the validator definition block in the route context
      # Pass in this validator object and any arguments
      def run_definition(*args)
        @context.instance_exec self, *args, &@definition
      end

      # Run a defined method in the route context
      def run_method(method)
        # :block is a placeholder to just run the given block, not a specific validation method
        @context.instance_exec(*method[:args], &@context.method(method[:name])) unless method[:name] == :block
        @context.instance_eval(&method[:block]) if method[:block]
      end

      def save_method_error(method, error)
        key = method[:name] == :param ? method[:args][0] : :global_errors
        @errors[key] ||= []
        @errors[key].push error.options&.key?(:message) ? error.options[:message].dup : error.to_s.dup
      end

      def save_params_copy
        @params = @context.params.dup
      end
    end

    # Holds a validator method identifier and any arguments to pass to the validator
    class ValidatorIdentifier
      attr_reader :identifier, :args

      def initialize(identifier, *args)
        @identifier = identifier
        @args = args
      end
    end

    def self.registered(app)
      app.helpers Helpers
      app.helpers Sinatra::Param
      app.enable :raise_sinatra_param_exceptions
    end
  end

  register Sinatra::Validator
end