hash_cabinet 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.
Files changed (4) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +48 -0
  3. data/lib/hash_cabinet.rb +218 -0
  4. metadata +44 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d284b1a7d996a2e750db02e4db77d2be4afb543ae88da7a385174f00f1533b9c
4
+ data.tar.gz: 270859870c5130c08e057cb7379f74902bf691db52c87ee8dffe592343b7dd14
5
+ SHA512:
6
+ metadata.gz: c3e93b6bc0904c02f003b8c913c7d25989d0526e0233bfdd612faedd75cfeb3fd193bf026066371a98fe26a33d8ae4fc4a3c274f0351eb1fbb31f063b609c9c1
7
+ data.tar.gz: 01d325e99d38b83f73c0e3007d546884af69af974f3193b6908b476ac8cadfb9a10ec16efec49bbd11e75e16aa7886a5e9635128c915ca4be1709f9ec7c93f54
data/README.md ADDED
@@ -0,0 +1,48 @@
1
+ Hash Cabinet - File based key-object store
2
+ ==================================================
3
+
4
+ [![Gem Version](https://badge.fury.io/rb/hash_cabinet.svg)](https://badge.fury.io/rb/hash_cabinet)
5
+
6
+ ---
7
+
8
+ Hash Cabinet is a file-based, key-object store with hash-like access.
9
+
10
+
11
+ Highlights
12
+ --------------------------------------------------
13
+
14
+ - Tiny library, based on Ruby's built in [SDBM].
15
+ - Stores simple values or complex objects through transparent YAML
16
+ serialization.
17
+ - Easy hash-like access: `cabinet['key'] = 'value'`.
18
+ - Mirrors most of the native SDBM methods.
19
+
20
+
21
+ Installation
22
+ --------------------------------------------------
23
+
24
+ $ gem install hash_cabinet
25
+
26
+
27
+
28
+ Usage
29
+ --------------------------------------------------
30
+
31
+ ```ruby
32
+ cabinet = HashCabinet.new 'dbfile'
33
+
34
+ # Store values
35
+ cabinet['some-key'] = 'some=value'
36
+ cabinet['another-key'] = { color: 'yellow' }
37
+
38
+ # Retrieve values
39
+ p cabinet['another-key']
40
+ #=> {:color=>"yellow", :shape=>"circle"}
41
+
42
+ # Show all values
43
+ p cabinet.to_h
44
+ #=> {"some-key"=>"some=value", "another-key"=>{:color=>"yellow"}
45
+
46
+ ```
47
+
48
+ [SDBM]: https://ruby-doc.org/stdlib-2.6.3/libdoc/sdbm/rdoc/SDBM.html
@@ -0,0 +1,218 @@
1
+ require 'sdbm'
2
+ require 'yaml'
3
+
4
+ class HashCabinet
5
+
6
+ # Refinements to allow using +from_yaml+ as the opposite of +to_yaml+.
7
+ module ReverseYAML
8
+ refine String do
9
+ def from_yaml
10
+ YAML.load self
11
+ end
12
+ end
13
+
14
+ refine NilClass do
15
+ def from_yaml
16
+ nil
17
+ end
18
+ end
19
+ end
20
+
21
+ using ReverseYAML
22
+
23
+ # Returns the path to the database file.
24
+ attr_reader :path
25
+
26
+ # Initialize a new database file at {path}.
27
+ def initialize(path)
28
+ @path = path
29
+ end
30
+
31
+ # Yields the +SDBM+ object to the block. Under most circumstances, this
32
+ # method should not be used directly, as it is used by all other methods.
33
+ #
34
+ # Example:
35
+ #
36
+ # cabinet = HashCabinet.new 'filename'
37
+ #
38
+ # cabinet.transaction do |db|
39
+ # db.clear
40
+ # end
41
+ #
42
+ def transaction(&block)
43
+ SDBM.open path, &block
44
+ end
45
+
46
+ # Returns the value in the database associated with the given +key+.
47
+ def [](key)
48
+ transaction { |db| db[key].from_yaml }
49
+ end
50
+
51
+ # Inserts or updates a value in the database with the given key as an index.
52
+ def []=(key, value)
53
+ transaction { |db| db[key] = value.to_yaml }
54
+ end
55
+
56
+ # Deletes all key-value pairs from the database.
57
+ def clear
58
+ transaction { |db| db.clear }
59
+ end
60
+
61
+ # Deletes the given `key` from the database.
62
+ def delete(key)
63
+ transaction { |db| db.delete key }
64
+ end
65
+
66
+ # Iterates over the key-value pairs in the database, deleting those for
67
+ # which the block returns true.
68
+ def delete_if(&block)
69
+ transaction do |db|
70
+ db.delete_if do |key, value|
71
+ yield key, value.from_yaml
72
+ end
73
+ end
74
+ end
75
+
76
+ # Iterates over each key-value pair in the database.
77
+ def each(&block)
78
+ transaction do |db|
79
+ db.each do |key, value|
80
+ yield key, value.from_yaml
81
+ end
82
+ end
83
+ end
84
+
85
+
86
+ # Iterates over each key in the database.
87
+ def each_key(&block)
88
+ transaction { |db| db.each_key &block }
89
+ end
90
+
91
+
92
+ # Iterates over each key-value pair in the database.
93
+ def each_value(&block)
94
+ transaction do |db|
95
+ db.each_value do |value|
96
+ yield value.from_yaml
97
+ end
98
+ end
99
+ end
100
+
101
+ # Returns +true+ if the database is empty.
102
+ def empty?
103
+ transaction { |db| db.empty? }
104
+ end
105
+
106
+ # Returns true if the database contains the given key.
107
+ def has_key?(key)
108
+ transaction { |db| db.has_key? key }
109
+ end
110
+
111
+ # Returns +true+ if the database contains the given value.
112
+ def has_value?(value)
113
+ transaction { |db| db.has_value? value.to_yaml }
114
+ end
115
+
116
+ # Returns +true+ if the database contains the given key.
117
+ def include?(key)
118
+ transaction { |db| db.include? key }
119
+ end
120
+
121
+ # Returns the key associated with the given value. If more than one key
122
+ # corresponds to the given value, then the first key will be returned.
123
+ # If no keys are found, +nil+ will be returned.
124
+ def key(value)
125
+ transaction { |db| db.key value.to_yaml }
126
+ end
127
+
128
+ # Returns +true+ if the database contains the given key.
129
+ def key?(key)
130
+ transaction { |db| db.key? key }
131
+ end
132
+
133
+ # Returns a new Array containing the keys in the database.
134
+ def keys
135
+ transaction { |db| db.keys }
136
+ end
137
+
138
+ # Returns the number of keys in the database.
139
+ def length
140
+ transaction { |db| db.length }
141
+ end
142
+
143
+ # Empties the database, then inserts the given key-value pairs.
144
+ # This method will work with any object which implements an +#each_pair+
145
+ # method, such as a Hash.
146
+ def replace(data)
147
+ data = data.transform_values &:to_yaml
148
+ data = data.transform_keys &:to_s
149
+ transaction { |db| db.replace data }
150
+ end
151
+
152
+ # Returns a new Hash of key-value pairs for which the block returns true.
153
+ def select(&block)
154
+ transaction do |db|
155
+ db.select do |key, value|
156
+ yield key, value.from_yaml
157
+ end.to_h.transform_values &:from_yaml
158
+ end
159
+ end
160
+
161
+ # Removes a key-value pair from the database and returns them as an Array.
162
+ #
163
+ # If the database is empty, returns nil.
164
+ def shift
165
+ transaction do |db|
166
+ result = db.shift
167
+ [result[0], result[1].from_yaml]
168
+ end
169
+ end
170
+
171
+ # Returns the number of keys in the database.
172
+ def size
173
+ transaction { |db| db.size }
174
+ end
175
+
176
+ # Returns a new Array containing each key-value pair in the database.
177
+ def to_a
178
+ transaction do |db|
179
+ db.to_a.map { |pair| [pair[0], pair[1].from_yaml] }
180
+ end
181
+ end
182
+
183
+ # Returns a new Hash containing each key-value pair in the database.
184
+ def to_h
185
+ transaction do |db|
186
+ db.to_h.transform_values &:from_yaml
187
+ end
188
+ end
189
+
190
+ # Insert or update key-value pairs.
191
+ #
192
+ # This method will work with any object which implements an +#each_pair+
193
+ # method, such as a Hash.
194
+ def update(data)
195
+ data = data.transform_values &:to_yaml
196
+ transaction { |db| db.update data }
197
+ end
198
+
199
+ # Returns +true+ if the database contains the given value.
200
+ def value?(value)
201
+ transaction { |db| db.value? value.to_yaml }
202
+ end
203
+
204
+ # Returns a new Array containing the values in the database.
205
+ def values
206
+ transaction do |db|
207
+ db.values.map &:from_yaml
208
+ end
209
+ end
210
+
211
+ # Returns an Array of values corresponding to the given keys.
212
+ def values_at(*key)
213
+ transaction do |db|
214
+ db.values_at(*key).map &:from_yaml
215
+ end
216
+ end
217
+
218
+ end
metadata ADDED
@@ -0,0 +1,44 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hash_cabinet
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Danny Ben Shitrit
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-09-18 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Store objects in a file using hash-like syntax
14
+ email: db@dannyben.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - README.md
20
+ - lib/hash_cabinet.rb
21
+ homepage: https://github.com/dannyben/hash_cabinet
22
+ licenses:
23
+ - MIT
24
+ metadata: {}
25
+ post_install_message:
26
+ rdoc_options: []
27
+ require_paths:
28
+ - lib
29
+ required_ruby_version: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 2.4.0
34
+ required_rubygems_version: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ requirements: []
40
+ rubygems_version: 3.0.4
41
+ signing_key:
42
+ specification_version: 4
43
+ summary: Key-object file database with hash-like access
44
+ test_files: []