kotas/json_schema_rails

View on GitHub
lib/json_schema_rails/loaders/hyper_schema.rb

Summary

Maintainability
A
25 mins
Test Coverage
module JsonSchemaRails
  module Loaders
    class HyperSchema < Base
      attr_accessor :path

      def initialize(path, options = {})
        @path = path
        super(options)
      end

      def load_schema!(schema_path)
        with_cache(schema_path) do
          schema_index.find(schema_path) or raise SchemaNotFound
        end
      end

      protected

      def schema_index
        with_cache(:_schema_index) do
          schema = load_schema_file(@path).tap(&:expand_references!)
          SchemaIndex.new(schema)
        end
      end

      class SchemaIndex
        def initialize(schema)
          @index = { _schema: schema }
          build(schema)
        end

        def build(schema)
          schema.links.each do |link|
            if link.href
              keys = index_keys("#{link.method || 'GET'}/#{link.href}", true)
              tail = keys.reduce(@index) { |hash, key| hash[key] ||= {} }
              tail[:_schema] = schema
            end
          end
          schema.properties.each do |key, subschema|
            build(subschema)
          end
        end

        def find(schema_path)
          keys = index_keys(schema_path, false)
          tail = keys.reduce(@index) do |hash, key|
            if hash.key?(key)
              hash[key]
            else
              next_key = hash.keys.find { |k| k === key } or break
              hash[next_key]
            end
          end
          tail[:_schema] if tail
        end

        private

        def index_keys(path, for_build)
          keys = path.to_s.downcase.split('/').reject(&:empty?)
          keys.map! { |k| k.gsub!(/\{(.*?)\}/, '[^/]+') ? %r/^#{k}$/ : k } if for_build
          keys
        end
      end
    end
  end
end