kalkov/rails4_client_side_validations

View on GitHub
lib/rails4_client_side_validations/middleware.rb

Summary

Maintainability
A
0 mins
Test Coverage
# encoding: utf-8

require 'rails4_client_side_validations/core_ext'

module Rails4ClientSideValidations

  module Middleware
    class Validators
      def initialize(app)
        @app = app
      end

      def call(env)
        if matches = /^\/validators\/(\w+)$/.match(env['PATH_INFO'])
          if Rails4ClientSideValidations::Config.disabled_validators.include?(matches[1].to_sym)
            [500, {'Content-Type' => 'application/json', 'Content-Length' => '0'}, ['']]
          else
            "::Rails4ClientSideValidations::Middleware::#{matches[1].camelize}".constantize.new(env).response
          end
        else
          @app.call(env)
        end
      end
    end

    class Base
      attr_accessor :request, :body, :status

      def initialize(env)
        # Filter out cache buster
        env['QUERY_STRING'] = env['QUERY_STRING'].split('&').select { |p| !p.match(/^_=/) }.join('&')
        self.body           = ''
        self.status         = 200
        self.request        = ActionDispatch::Request.new(env)
      end

      def response
        [status, {'Content-Type' => content_type, 'Content-Length' => body.length.to_s}, [body]]
      end

      def content_type
        'application/json'
      end
    end

    class Uniqueness < Base
      IGNORE_PARAMS = %w{case_sensitive id scope}
      REGISTERED_ORMS = []
      class NotValidatable < StandardError; end

      def response
        begin
          if is_unique?
            self.status = 404
            self.body   = 'true'
          else
            self.status = 200
            self.body   = 'false'
          end
        rescue NotValidatable
          self.status = 500
          self.body = ''
        end
        super
      end

      def self.register_orm(orm)
        registered_orms << orm
      end

      def self.registered_orms
        REGISTERED_ORMS
      end

      def registered_orms
        self.class.registered_orms
      end

      private

      def is_unique?
        convert_scope_value_from_null_to_nil
        resource         = extract_resource
        klass            = resource.classify.constantize
        attribute        = request.params[resource].keys.first
        value            = request.params[resource][attribute]
        middleware_class = nil

        unless Array.wrap(klass._validators[attribute.to_sym]).find { |v| v.kind == :uniqueness }
          raise NotValidatable
        end

        registered_orms.each do |orm|
          if orm.is_class?(klass)
            middleware_class = orm
            break
          end
        end

        middleware_class.is_unique?(klass, attribute, value, request.params)
      end

      def convert_scope_value_from_null_to_nil
        if request.params['scope']
          request.params['scope'].each do |key, value|
            if value == 'null'
              request.params['scope'][key] = nil
            end
          end
        end
      end

      def extract_resource
        parent_key = (request.params.keys - IGNORE_PARAMS).first
      end
    end
  end

end