kigster/arduino-library

View on GitHub
lib/arduino/library/database.rb

Summary

Maintainability
A
1 hr
Test Coverage
require 'json'
require 'forwardable'
require 'arduino/library/model'
require 'arduino/library/utilities'
require 'colored2'

module Arduino
  module Library
    # This class represents a single entry into the library-index.json file,
    # in other words — a `library.properties` file.
    class Database

      include Utilities
      extend Forwardable

      class << self
        alias from new
      end

      def_delegators :@db_list,
                     *(Array.new.methods -
                       Object.methods - [:search])

      attr_accessor :local_file,
                    :db_list

      def initialize(file_or_url)
        self.local_file = read_file_or_url(file_or_url)
        load_json
      end

      # Usage: search(attr1: value, attr2: /regexp/, ... )
      def search(**opts)
        limit = opts[:limit]
        opts.delete(:limit)
        match_list = []

        db_list.select do |entry|
          matches = entry_matches?(entry, opts)
          match_list << entry if matches
          break if limit && match_list.size >= limit
        end

        match_list.each { |entry| yield(entry) } if block_given?
        match_list
      end

      protected

      def entry_matches?(entry, opts)
        matches = true
        opts.each_pair do |attr, check|
          value   = entry.send(attr)
          matches &= case check
                       when String
                         value == check
                       when Regexp
                         value =~ check
                       when Array
                         value = value.split(',') unless value.is_a?(Array)
                         value.eql?(check) || value.include?(check) || value.first == '*'
                       when Proc
                         check.call(value)
                       else
                         raise ::OptionParser::InvalidArgument, "Class #{check.class.name} is unsupported for value checks"
                     end
          break unless matches
        end
      end

      private

      def load_json
        hash         = JSON.load(local_file.read)
        self.db_list = hash['libraries'].map { |lib| Model.from_hash(lib) }
      end
    end
  end
end