db-struct 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +125 -0
- data/Rakefile +35 -0
- data/db-struct.gemspec +37 -0
- data/doc/DBStruct/BogoHash.html +1384 -0
- data/doc/DBStruct/ErrorHelpers.html +288 -0
- data/doc/DBStruct/Failure.html +139 -0
- data/doc/DBStruct/FieldError.html +143 -0
- data/doc/DBStruct/MissingRowError.html +143 -0
- data/doc/DBStruct/TypeError.html +143 -0
- data/doc/DBStruct.html +1652 -0
- data/doc/_index.html +189 -0
- data/doc/class_list.html +54 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +58 -0
- data/doc/css/style.css +503 -0
- data/doc/file.README.html +187 -0
- data/doc/file_list.html +59 -0
- data/doc/frames.html +22 -0
- data/doc/index.html +187 -0
- data/doc/js/app.js +344 -0
- data/doc/js/full_list.js +242 -0
- data/doc/js/jquery.js +4 -0
- data/doc/method_list.html +342 -0
- data/doc/top-level-namespace.html +110 -0
- data/gem.deps.rb +7 -0
- data/lib/dbstruct.rb +29 -0
- data/lib/internal/bogohash.rb +226 -0
- data/lib/internal/dbstruct_base.rb +144 -0
- data/lib/internal/dbstruct_class.rb +301 -0
- data/lib/internal/error.rb +44 -0
- data/lib/internal/util.rb +11 -0
- data/spec/dbstruct_spec.rb +452 -0
- data/spec/spec_helper.rb +48 -0
- metadata +138 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2cafa77dd62d6126979c75a2453805e5ae07a9537e664e73da4fb1530159ace5
|
4
|
+
data.tar.gz: 7e1b5397788a38864f6d07c8c14ba9cd75da0a00bd33f83c2d1e239442ba794f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: aba9d9fad1a29bebf9b9d538d8b723254558e34648d4280f7d397aae930c3b4f3c4c438d07cc75cfc30c9b70de5a009a091a59e70d92548561bef0837b7f352f
|
7
|
+
data.tar.gz: ed5362fe8a6b51a32c0957c526b4a8d67b9cc21f04c4ef7c78fc35ee3ef14c08dafe64787df09a45711714efbf57b4bf9363c0fdc6a9608fea430a861ee00860
|
data/README.md
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
# Persistant Sets of Structured Data
|
2
|
+
|
3
|
+
`db-struct` is a Ruby gem that provides class `DBStruct`, a class that
|
4
|
+
is similar to Ruby's built-in `Struct` class but stores its data in a
|
5
|
+
SQLite database. In addition, each subclass also provides access to
|
6
|
+
the database via an interface that closely mimics a Ruby Hash,
|
7
|
+
including support for enumeration.
|
8
|
+
|
9
|
+
It is currently at the "experimental toy" stage of development.
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Simply install it via `gem`:
|
14
|
+
|
15
|
+
gem install --prerelease db-struct
|
16
|
+
|
17
|
+
Note that you will also need to install SQLite3 separately. On stock
|
18
|
+
Ruby, that's:
|
19
|
+
|
20
|
+
gem install sqlite3
|
21
|
+
|
22
|
+
while with JRuby, it's:
|
23
|
+
|
24
|
+
gem install jdbc-sqlite3
|
25
|
+
|
26
|
+
It uses [Sequel](https://sequel.jeremyevans.net/) to do the heavy
|
27
|
+
lifting. This is installed as a dependency, but you'll need to know
|
28
|
+
how to open a database with it.
|
29
|
+
|
30
|
+
|
31
|
+
## Overview
|
32
|
+
|
33
|
+
Let's start with a simple example, a table of books. The first thing
|
34
|
+
we need to do is create a database connection:
|
35
|
+
|
36
|
+
DB = Sequel.sqlite("books.sqlite3")
|
37
|
+
|
38
|
+
We can then define the structure and the underlying table:
|
39
|
+
|
40
|
+
Book = DBStruct.with(DB, :books) do
|
41
|
+
field :title, String
|
42
|
+
field :author, String
|
43
|
+
field :date, Time
|
44
|
+
field :edition, Integer
|
45
|
+
end
|
46
|
+
|
47
|
+
`Book` is now a subclass of `DBStruct`; creating it will also create a
|
48
|
+
table named `:books` if it doesn't exist.
|
49
|
+
|
50
|
+
We can create an instance of `Book` like this:
|
51
|
+
|
52
|
+
b1 = Book.new(title: "Diseases of the Dragon",
|
53
|
+
author: "Lady Sybil Ramkin",
|
54
|
+
date: Time.new(1989, 11, 1),
|
55
|
+
edition: 1)
|
56
|
+
|
57
|
+
The contents are immediately written to the database, but this object
|
58
|
+
behaves more or less like a Ruby `Struct`:
|
59
|
+
|
60
|
+
puts b1.title
|
61
|
+
b1.author = "Lady Sybil Ramkin-Vimes"
|
62
|
+
puts b1.author
|
63
|
+
|
64
|
+
Note that these are not part of a transaction. If you need that (and
|
65
|
+
you probably will), you can the `transaction` method:
|
66
|
+
|
67
|
+
Book.transaction {
|
68
|
+
puts b1.title
|
69
|
+
b1.author = "Lady Sybil Ramkin-Vimes"
|
70
|
+
puts b1.author
|
71
|
+
}
|
72
|
+
|
73
|
+
This starts a transaction, evaluates the block and commits. If there
|
74
|
+
is an exception inside the block, the transaction is rolled back
|
75
|
+
instead. Transactions can be safely nested. (`DBStruct#transaction`
|
76
|
+
is simply a thin wrapper around `Sequel::Database#transaction`.)
|
77
|
+
|
78
|
+
The class method `items` returns a `DBStruct::BogoHash`, which behaves
|
79
|
+
like a Hash mapping numeric row IDs to corresponding `Book` objects:
|
80
|
+
|
81
|
+
puts Book.items[b1.rowid].title
|
82
|
+
|
83
|
+
The usual enumeration operations are also available:
|
84
|
+
|
85
|
+
Book.items.values.each{|book|
|
86
|
+
puts " #{book.title} by #{book.author}"
|
87
|
+
}
|
88
|
+
|
89
|
+
first_editions = Book.items
|
90
|
+
.select{|id, book| book.edition == 1}
|
91
|
+
.map{|id, _| id}
|
92
|
+
|
93
|
+
You can also add a special field type called a `group`. This can be
|
94
|
+
used to subdivide the table:
|
95
|
+
|
96
|
+
Book = DBStruct.with(DB, :books) do
|
97
|
+
group :category, String
|
98
|
+
field :title, String
|
99
|
+
field :author, String
|
100
|
+
field :date, Time
|
101
|
+
field :edition, Integer
|
102
|
+
end
|
103
|
+
|
104
|
+
b1 = Book.new(category:"non-fiction",
|
105
|
+
title: "Diseases of the Dragon",
|
106
|
+
author: "Lady Sybil Ramkin",
|
107
|
+
date: Time.new(1989, 11, 1),
|
108
|
+
edition: 1)
|
109
|
+
|
110
|
+
A `group` is just an ordinary field except that `Books.items` will
|
111
|
+
filter by them:
|
112
|
+
|
113
|
+
non_fiction = Book.items("non-fiction")
|
114
|
+
|
115
|
+
Multiple groups are allowed and `nil` can be used as a wildcard when
|
116
|
+
selection them.
|
117
|
+
|
118
|
+
Alternately, you can filter using a `Sequel` `where` clause:
|
119
|
+
|
120
|
+
dragon_books = Book.where(Sequel.like(:title, "%Dragon%"))
|
121
|
+
|
122
|
+
but if you need that often, you may well be better off dealing with
|
123
|
+
`Sequel` directly.
|
124
|
+
|
125
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# Starter Rakefile for a gem.
|
2
|
+
#
|
3
|
+
|
4
|
+
require 'rake'
|
5
|
+
require 'rspec/core/rake_task'
|
6
|
+
require 'yard'
|
7
|
+
|
8
|
+
RSpec::Core::RakeTask.new(:test) do |t|
|
9
|
+
t.pattern = Dir.glob('spec/*_spec.rb')
|
10
|
+
end
|
11
|
+
|
12
|
+
YARD::Rake::YardocTask.new(:docs_via_yard)
|
13
|
+
|
14
|
+
# Install dependencies
|
15
|
+
task :install_deps do
|
16
|
+
sh "gem install -g"
|
17
|
+
end
|
18
|
+
|
19
|
+
task gem: [:docs_via_yard] do
|
20
|
+
sh "gem build db-struct.gemspec"
|
21
|
+
end
|
22
|
+
|
23
|
+
task :clean do
|
24
|
+
gems = Dir.glob("db-struct-*.gem")
|
25
|
+
rm gems if gems.size > 0
|
26
|
+
rm_rf "doc"
|
27
|
+
end
|
28
|
+
|
29
|
+
task :clobber => [:clean] do
|
30
|
+
rm_rf ".yardoc"
|
31
|
+
end
|
32
|
+
|
33
|
+
task :doc => :docs_via_yard
|
34
|
+
|
35
|
+
task :default => [:docs_via_yard, :test, :gem]
|
data/db-struct.gemspec
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = "db-struct"
|
5
|
+
s.version = '0.1.0'
|
6
|
+
s.date = '2024-09-09'
|
7
|
+
s.summary = "Persistant storage of sets of structured records."
|
8
|
+
s.description = <<-EOF
|
9
|
+
DBStruct is a class that, like Struct, provides a convenient way
|
10
|
+
to create subclasses with named fields that can be accessed via
|
11
|
+
the usual Ruby setters and getters. Unlike Struct, their contents
|
12
|
+
are stored in a SQLite3 database.
|
13
|
+
|
14
|
+
In addition, each subclass also provides access to the database
|
15
|
+
via an interface that closely mimics a Ruby Hash, including
|
16
|
+
support for enumeration.
|
17
|
+
EOF
|
18
|
+
s.authors = ["Chris Reuter"]
|
19
|
+
s.email = 'chris@remove-this-part.blit.ca'
|
20
|
+
|
21
|
+
# I'm just going to add everything so that if you've got the gem,
|
22
|
+
# you've also got the source distribution. Yay! Open source!
|
23
|
+
s.files =
|
24
|
+
Dir.glob('doc/**/*') +
|
25
|
+
`git ls-files`.split.reject {|f| f =~ /\.org$/}
|
26
|
+
|
27
|
+
s.required_ruby_version = '>= 3.0.0'
|
28
|
+
s.requirements << "Sequel"
|
29
|
+
|
30
|
+
s.add_runtime_dependency "sequel", '~> 5.76.0'
|
31
|
+
|
32
|
+
s.add_development_dependency "rspec", '~> 3.10', '>= 3.10.0'
|
33
|
+
s.add_development_dependency "yard", '~> 0.9.25', '>= 0.9.25'
|
34
|
+
|
35
|
+
s.homepage = 'https://codeberg.org/suetanvil/db-struct'
|
36
|
+
s.license = 'MIT'
|
37
|
+
end
|