Serialize_to_db

database Link to heading

PRAGMA encoding = 'UTF-8';

CREATE TABLE object(
id integer not null primary key,
name string unique,
type string,
obj blob
);

ser_db.rb Link to heading

require 'sqlite3'
require 'base64'

module Vault
  extend self
  DB_FILE = '»>PATH_TO_DATABASE<<'
  DB      = SQLite3::Database.new(DB_FILE)
 
  def sto(name, obj)
    b64md = Base64.encode64 Marshal.dump(obj)
    DB.execute <<~SQL
      INSERT OR IGNORE INTO object(name, type, obj)
      VALUES('#{name}', '#{obj.class}', '#{b64md}')
      ON CONFLICT(name) DO UPDATE SET
      type = '#{obj.class}',
      obj = '#{b64md}'
      WHERE name = '#{name}';
    SQL
  end

  def rec(name)
    Marshal.load(
      Base64.decode64(DB.execute(
        %|SELECT obj FROM object WHERE name = '#{name}';|)[0][0]
      )
    )
  end

  def ls(*filter, table: false)
    DB.execute(%|SELECT id, name, type FROM object#{where_str(filter)}|)
      .then { table ? to_table(it) : it }
  end

  def rm(*filter)
    DB.execute(%|DELETE FROM object#{where_str(filter)}|)
  end
 
  private 
  
  def where_str(filter)
    case filter
    in [Integer, *] then %|\nWHERE id IN (#{filter.join(', ')});|
    in [Range]      then %|\nWHERE id BETWEEN #{filter[0].first} AND #{filter[0].last};|
    in [String]     then %|\nWHERE name GLOB '#{filter[0]}';|
    else ';'
    end
  end

  def to_table(arr)
    require 'table_tennis'
    TableTennis.new(arr, headers: {'0': 'id', '1': 'name', '2': 'type'}, zebra: true)
  end

end

usage Link to heading

require 'ser_db.rb'

# store an object
Vault::sto :name, obj

# recall an object
obj = Vault::rec :name

# list objects in database
p Vault::ls # list all
p Vault::ls 2, 3, 8 # id:s
p Vault::ls (2..8) # range
p Vault::ls '[A-D]*_[0-9]' # match name

# show list as table-tennis table
puts Vault::ls '[A-D]*_[0-9]', table: true

# remove objects in database
Vault::rm # remove all
Vault::rm 2, 3, 8
Vault::rm (1..9)
Vault::rm '[A-D]*_[0-9]'

I made some changes just before posting.. hope it still wotks.

tip Link to heading

# put all objects with name beginning with 'proj1_' in a Hash of Struct(:type, :value)

Obj = Struct.new(:type, :value)

pp Vault::ls('proj1_*')
  .inject({}) {|ac, el| ac[el[1]] = Obj.new(el[2], Vault::rec(el[1])); ac }

update 2025-09-27 Link to heading

Added new ‘mod’ method

def mod(name) = ( sto(name, rec(name).tap { yield(it) }) if block_given? )

Now I can modify an object in the database without doing:
Vault::sto(:the_key, Vault::rec(:the_ley)[:hash_key] = 88)

Instead:

Vault::mod(:the_key) { it[:hash_key] = 88 }