<commit_before>require 'sequel'
require 'ostruct'
require 'yaml'

# This Module provides key/value storage methods to a database powered by Sequel
# Once created, a nosequel container works much like a Hash, but stores the data
# in a database behind the scenes.
module NoSequel

  class << self
    def make_config_string(opt_config)
      config = OpenStruct.new( NoSequel::Configuration.default_config.merge(opt_config.to_hash) )

      # Start our connection string
      connect_string = "#{config.db_type || 'sqlite'}://"

      # Add user:password if supplied
      if config.db_user
        connect_string += "#{config.db_user}"

        # Add either a @ or / depending on if a host was provided too
        connect_string += config.db_host ? '@' : '/'

        # Add host:port if supplied
        connect_string += "#{config.db_host}/" if config.db_host
      end

      connect_string + config.db_name
    end

    # Creates and returns a nosequel container
    def register( table, config = {} )
      # Create the Sequel connection
      @sequel = Sequel.connect( make_config_string(config) )
      Container.new(@sequel, table)
    end

    # Permanently deletes table from the underlying database
    def drop!( table )
      raise RuntimeError, 'You must call register first' unless @sequel
      @sequel.drop_table( table.to_sym ) if exists?(table)
    end

    # Tests if table exists in the database, returns true or false
    def exists?( table )
      raise RuntimeError, 'You must call register first' unless @sequel
      @sequel.table_exists?( table.to_sym )
    end
  end # Class << self

  # NoSequel::Container class defines the methods to
  class Container

    # Create and/or retrieve a table from our database
    # and returns a nosequel container class.
    # called via NoSequel.register(:table)
    def initialize(db, table)

      unless db.table_exists?(table.to_sym)
        db.create_table table do
          primary_key :id
          String      :key
          String      :value
        end
        db.add_index table, :key
        db.add_index table, :value
      end

      @db    = db[table]
      @table = table
    end

    attr_reader :table, :db

    # Assigns the <value> to a given <:key>
    def []=(key, value)
      obj = value.is_a?(String) ? value : YAML::dump(value)
      if exists?(key) # column already exists
        data(key).update(value: obj)
      else
        @db.insert(key: key.to_s, value: obj)
      end
    end

    # Returns the value stored in :key, or nil of the data wasn't found.
    def [](key)
      exists?(key) ? YAML::load(value(key)) : nil
    end

    # Deletes :key from the nosequel container
    def delete(key)
      if exists?(key)
        value = value(key)
        data(key).delete
      end
      value
    end
    alias_method :remove, :delete

    # Checks if a given key exists in the container
    def has_key?(key)
      validate_key(key)
      data(key).count == 1 ? true : false
    end
    alias_method :exist?, :has_key?
    alias_method :exists?, :has_key?

    # Handle all other Hash methods
    def method_missing(meth, *args, &block)
      @db.to_hash(:key, :value).send(meth, *args, &block)
    end

    # Make sure we respond to all Hash methods
    def respond_to?(meth)
      @db.to_hash(:key, :value).respond_to?(meth)
    end


    private

    # Returns a single record which matches key
    def data(key)
      validate_key(key)
      @db.where(key: key.to_s)
    end

    def value(key)
      data(key).get(:value)
    end

    def validate_key(key)<commit_msg>use db class method instead of attribute<commit_after>require 'sequel'
require 'ostruct'
require 'yaml'

# This Module provides key/value storage methods to a database powered by Sequel
# Once created, a nosequel container works much like a Hash, but stores the data
# in a database behind the scenes.
module NoSequel

  class << self
    def make_config_string(opt_config)
      config = OpenStruct.new( NoSequel::Configuration.default_config.merge(opt_config.to_hash) )

      # Start our connection string
      connect_string = "#{config.db_type || 'sqlite'}://"

      # Add user:password if supplied
      if config.db_user
        connect_string += "#{config.db_user}"

        # Add either a @ or / depending on if a host was provided too
        connect_string += config.db_host ? '@' : '/'

        # Add host:port if supplied
        connect_string += "#{config.db_host}/" if config.db_host
      end

      connect_string + config.db_name
    end

    # Creates and returns a nosequel container
    def register( table, config = {} )
      # Create the Sequel connection
      @sequel = Sequel.connect( make_config_string(config) )
      Container.new(@sequel, table)
    end

    # Permanently deletes table from the underlying database
    def drop!( table )
      raise RuntimeError, 'You must call register first' unless @sequel
      @sequel.drop_table( table.to_sym ) if exists?(table)
    end

    # Tests if table exists in the database, returns true or false
    def exists?( table )
      raise RuntimeError, 'You must call register first' unless @sequel
      @sequel.table_exists?( table.to_sym )
    end
  end # Class << self

  # NoSequel::Container class defines the methods to
  class Container

    # Create and/or retrieve a table from our database
    # and returns a nosequel container class.
    # called via NoSequel.register(:table)
    def initialize(db, table)

      unless db.table_exists?(table.to_sym)
        db.create_table table do
          primary_key :id
          String      :key
          String      :value
        end
        db.add_index table, :key
        db.add_index table, :value
      end

      @db    = db[table]
      @table = table
    end

    attr_reader :table, :db

    # Assigns the <value> to a given <:key>
    def []=(key, value)
      obj = value.is_a?(String) ? value : YAML::dump(value)
      if exists?(key) # column already exists
        data(key).update(value: obj)
      else
        db.insert(key: key.to_s, value: obj)
      end
    end

    # Returns the value stored in :key, or nil of the data wasn't found.
    def [](key)
      exists?(key) ? YAML::load(value(key)) : nil
    end

    # Deletes :key from the nosequel container
    def delete(key)
      if exists?(key)
        value = value(key)
        data(key).delete
      end
      value
    end
    alias_method :remove, :delete

    # Checks if a given key exists in the container
    def has_key?(key)
      validate_key(key)
      data(key).count == 1 ? true : false
    end
    alias_method :exist?, :has_key?
    alias_method :exists?, :has_key?

    # Handle all other Hash methods
    def method_missing(meth, *args, &block)
      db.to_hash(:key, :value).send(meth, *args, &block)
    end

    # Make sure we respond to all Hash methods
    def respond_to?(meth)
      db.to_hash(:key, :value).respond_to?(meth)
    end


    private

    # Returns a single record which matches key
    def data(key)
      validate_key(key)
      db.where(key: key.to_s)
    end

    def value(key)
      data(key).get(:value)
    end

    def validate_key(key)
{'fraction_non_alphanumeric': 0.09289998605105315, 'fraction_numerical': 0.0002789789370902497, 'mean_word_length': 2.516429622363904, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7216378', 'n_tokens_mistral': 2193, 'n_tokens_neox': 2145, 'n_words': 709}