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 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