class BBS::Store
A small thread-safe table keyed by session id, for keeping what callers entered, in a BBS::SQLite file. The file and the table are created on first use; a column added to headers later is added to the table.
store = BBS::Store.new(path: 'data/callers.csv', headers: %w[session_id timestamp name]) store.upsert(session_id: ctx[:session_id], name: 'Ada')
A path ending in .csv names the CSV file of earlier versions: the database is the .sqlite3 file beside it, and on first use (or at boot, with open!) the rows of the CSV file (when it exists and the table is empty) are imported in one transaction and the CSV file is renamed to <name>.csv.imported. A row that is not CSV, has more fields than the header or no session_id is skipped and set aside in <name>.csv.rejected (see Store::CsvImport).
The session_id column is the key; a timestamp column, when present, is filled with the UTC time a row is created.
Constants
- KEY
-
The key column, kept even when
headersleave it out. - TABLE
-
The table that holds the rows.
Attributes
The column names (an Array of String) and the path the store was made with (see the class description for the database file).
The column names (an Array of String) and the path the store was made with (see the class description for the database file).
Public Class Methods
Source
# File lib/bbs/store.rb, line 36 def initialize(path:, headers:) @path = path.to_s @headers = headers.map(&:to_s) @mutex = Mutex.new end
Creates a store at path with the column names headers. The file is not touched until the first read or write.
Public Instance Methods
Source
# File lib/bbs/store.rb, line 73 def all = db.query("SELECT * FROM #{TABLE} ORDER BY rowid").map { |row| project(row) }
Returns every row as an Array of Hash, oldest first.
Source
# File lib/bbs/store.rb, line 52 def database_path = @path.sub(/\.csv\z/, '.sqlite3')
The path of the SQLite file: path, or the .sqlite3 file beside it when path names a CSV file.
Source
# File lib/bbs/store.rb, line 76 def delete(session_id) db.change("DELETE FROM #{TABLE} WHERE #{KEY} = ?", session_id.to_s) nil end
Removes the row of session_id, if there is one.
Source
# File lib/bbs/store.rb, line 67 def find(session_id) row = db.get("SELECT * FROM #{TABLE} WHERE #{KEY} = ?", session_id.to_s) row && project(row) end
Returns the row of session_id as a Hash of column name to value, or nil.
Source
# File lib/bbs/store.rb, line 45 def open! db self end
Opens the database now (creating the file and the table, importing a CSV file) instead of on first use, so a board can do it at boot. Returns self.
# File lib/bbs/store.rb, line 59 def upsert(session_id:, **fields) values = fields.filter_map { |name, value| [name.to_s, clean(value)] if @headers.include?(name.to_s) }.to_h db.transaction { find(session_id) ? update(session_id, values) : add(session_id, fields) } self end
Updates the row of session_id with fields, or adds a new row when there is none. Keys that are not columns are ignored; values are stored as strings cleaned with BBS::Text.clean.
Returns self.