simple-file-db 0.7
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/.gitignore +3 -0
- data/README.md +1 -0
- data/Rakefile +1 -0
- data/TODO.txt +18 -0
- data/lib/simple-file-db/item.rb +55 -0
- data/lib/simple-file-db.rb +163 -0
- data/simple-file-db.gemspec +29 -0
- data/test/main_test.rb +14 -0
- metadata +174 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 92b1837a51f599b3a94500c9c3d8c2f2ff3240e9c2d0d8ba80cb92a72fee8336
|
|
4
|
+
data.tar.gz: 59978523a27ac4a810b69c2b8a0c0e31a2d785c00308215c2c852e21aef64953
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 76a7e8a5c0cc54df4e3039df4d90bc237f075c67621097fe87f309dff79c0cff9a442f525a007c7087aa876c2fbc5551acdd1984bb131f018ef9673845e0dce3
|
|
7
|
+
data.tar.gz: 53d2d7abd6890f4f80c827a3c7787e1b2a4f1311ac3cd0c2e8bd6f84383fc136491af1b2d4f9772860361f7a370c87bce1c67b11897d35eff34b66b0b69acc03
|
data/.gitignore
ADDED
data/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
FIXME
|
data/Rakefile
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require 'simple-rake-tasks'
|
data/TODO.txt
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
- rename to FileDB or SlowDB
|
|
2
|
+
|
|
3
|
+
- make work *only* with files
|
|
4
|
+
- no in-memory database
|
|
5
|
+
- no caching (or optional)
|
|
6
|
+
- #[] reads JSON file, #[]= writes, #delete deletes
|
|
7
|
+
- #keys reads directories/IDs
|
|
8
|
+
- #values parses JSON files
|
|
9
|
+
- #update(item) rewrites item
|
|
10
|
+
|
|
11
|
+
- make include'able, rather than inheritable
|
|
12
|
+
- include Simple::FileDB, include Simple::FileDB::Item
|
|
13
|
+
|
|
14
|
+
- make simpler to-json/from-json converters
|
|
15
|
+
- hash with keys of attributes, values as hash of procs:
|
|
16
|
+
- initialize
|
|
17
|
+
- reader
|
|
18
|
+
- writer (defaults to #to_s unless basic types)
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module Simple
|
|
2
|
+
|
|
3
|
+
class FileDB
|
|
4
|
+
|
|
5
|
+
class Item
|
|
6
|
+
|
|
7
|
+
attr_accessor :json_file
|
|
8
|
+
attr_accessor :id
|
|
9
|
+
attr_accessor :db
|
|
10
|
+
|
|
11
|
+
include SetParams
|
|
12
|
+
|
|
13
|
+
def dir
|
|
14
|
+
@json_file.dirname
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def files
|
|
18
|
+
dir.glob('*') - [json_file]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def to_h
|
|
22
|
+
{
|
|
23
|
+
id: id,
|
|
24
|
+
}
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def to_json(*options)
|
|
28
|
+
as_json(*options).to_json(*options)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def as_json(*options)
|
|
32
|
+
to_h.compact
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def to_pretty_json
|
|
36
|
+
JSON.pretty_generate(self)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def fields(keys)
|
|
40
|
+
keys.map { |k| send(k) }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def <=>(other)
|
|
44
|
+
id <=> other.id
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def save
|
|
48
|
+
@db.save_item(self)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
end
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
require 'csv'
|
|
2
|
+
require 'json'
|
|
3
|
+
require 'path'
|
|
4
|
+
require 'set_params'
|
|
5
|
+
|
|
6
|
+
require_relative 'simple-file-db/item'
|
|
7
|
+
|
|
8
|
+
module Simple
|
|
9
|
+
|
|
10
|
+
class FileDB
|
|
11
|
+
|
|
12
|
+
class Error < Exception; end
|
|
13
|
+
|
|
14
|
+
attr_accessor :root
|
|
15
|
+
|
|
16
|
+
InfoFileName = 'info.json'
|
|
17
|
+
|
|
18
|
+
def self.item_class
|
|
19
|
+
Item
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.search_fields
|
|
23
|
+
[]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def self.convert_id(id)
|
|
27
|
+
id
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def initialize(root:)
|
|
31
|
+
@root = Path.new(root).expand_path
|
|
32
|
+
@items = {}
|
|
33
|
+
if @root.exist?
|
|
34
|
+
@root.glob("*/#{InfoFileName}").each do |info_file|
|
|
35
|
+
raise Error, "Info file does not exist: #{info_file}" unless info_file.exist?
|
|
36
|
+
make_item(**JSON.load(info_file.read))
|
|
37
|
+
end
|
|
38
|
+
# ;;warn "* loaded #{@items.length} items from #{@root}"
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def items
|
|
43
|
+
@items.values
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def as_json(...)
|
|
47
|
+
items
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def to_json(...)
|
|
51
|
+
as_json(...).to_json(...)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def to_csv
|
|
55
|
+
csv = []
|
|
56
|
+
items.each_with_index do |item, i|
|
|
57
|
+
hash = item.to_h
|
|
58
|
+
csv << CSV.generate_line(hash.keys) if i == 0
|
|
59
|
+
csv << CSV.generate_line(hash.values)
|
|
60
|
+
end
|
|
61
|
+
csv.join
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def convert_id(id)
|
|
65
|
+
self.class.convert_id(id)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def [](id)
|
|
69
|
+
@items[convert_id(id)]
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def []=(id, value)
|
|
73
|
+
@items[convert_id(id)] = value
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def <<(item)
|
|
77
|
+
item.db = self
|
|
78
|
+
self[item.id] = item
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def make_item(**params)
|
|
82
|
+
item = self.class.item_class.new(**params)
|
|
83
|
+
item.db = self
|
|
84
|
+
item.json_file = json_file_for_id(item.id)
|
|
85
|
+
@items[item.id] = item
|
|
86
|
+
item
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def find(*selectors)
|
|
90
|
+
selectors = [selectors].compact.flatten
|
|
91
|
+
# warn "searching #{self.class} for: #{selectors.empty? ? 'ALL' : selectors.join(', ')}"
|
|
92
|
+
if selectors.empty?
|
|
93
|
+
@items.values
|
|
94
|
+
else
|
|
95
|
+
selected = Set.new
|
|
96
|
+
selectors.each do |selector|
|
|
97
|
+
if selector.to_i != 0
|
|
98
|
+
selected << convert_id(selector)
|
|
99
|
+
else
|
|
100
|
+
selected += search(selector)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
selected.map { |id| self[id] }.compact.sort
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def search(query)
|
|
108
|
+
words = [query].flatten.join(' ').tokenize.sort.uniq - ['-']
|
|
109
|
+
words.map do |word|
|
|
110
|
+
regexp = Regexp.new(Regexp.quote(word), true)
|
|
111
|
+
@items.values.select do |item|
|
|
112
|
+
self.class.search_fields.find do |field|
|
|
113
|
+
case (value = item.send(field))
|
|
114
|
+
when Array
|
|
115
|
+
value.find { |v| v.to_s =~ regexp }
|
|
116
|
+
else
|
|
117
|
+
value.to_s =~ regexp
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end.flatten.compact.sort.map(&:id)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def json_file_for_id(id)
|
|
125
|
+
@root / id / InfoFileName
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def save_item(item)
|
|
129
|
+
raise Error, "Item does not have ID" unless item.id
|
|
130
|
+
item.json_file = json_file_for_id(item.id)
|
|
131
|
+
# ;;warn "* saving item to #{item.json_file}"
|
|
132
|
+
item.json_file.dirname.mkpath unless item.json_file.dirname.exist?
|
|
133
|
+
item.json_file.write(item.to_pretty_json)
|
|
134
|
+
self[item.id] ||= item
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def save_hash(hash)
|
|
138
|
+
raise Error, "Hash does not have ID" unless hash[:id]
|
|
139
|
+
json_file = json_file_for_id(hash[:id])
|
|
140
|
+
# ;;warn "* saving item to #{json_file}"
|
|
141
|
+
json = JSON.pretty_generate(hash)
|
|
142
|
+
json_file.dirname.mkpath unless json_file.dirname.exist?
|
|
143
|
+
json_file.write(json)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def has_item?(id)
|
|
147
|
+
@items.has_key?(convert_id(id))
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def destroy!
|
|
151
|
+
@items = {}
|
|
152
|
+
@root.rmtree if @root.exist?
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def destroy_item!(item)
|
|
156
|
+
@items.delete(item.id)
|
|
157
|
+
dir = json_file_for_id(item.id).dirname
|
|
158
|
+
dir.rmtree if dir.exist?
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
Gem::Specification.new do |s|
|
|
2
|
+
s.name = 'simple-file-db'
|
|
3
|
+
s.version = '0.7'
|
|
4
|
+
s.summary = 'A database built upon JSON files'
|
|
5
|
+
s.author = 'John Labovitz'
|
|
6
|
+
s.email = 'johnl@johnlabovitz.com'
|
|
7
|
+
s.description = %q{
|
|
8
|
+
Simple::FileDB is a database built upon JSON files.
|
|
9
|
+
}.strip
|
|
10
|
+
s.license = 'MIT'
|
|
11
|
+
s.homepage = 'http://github.com/jslabovitz/simple-file-db'
|
|
12
|
+
s.files = `git ls-files`.split("\n")
|
|
13
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
14
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
|
15
|
+
s.require_path = 'lib'
|
|
16
|
+
|
|
17
|
+
s.add_dependency 'csv', '~> 3.3'
|
|
18
|
+
s.add_dependency 'json', '~> 2.15'
|
|
19
|
+
s.add_dependency 'path', '~> 2.1'
|
|
20
|
+
s.add_dependency 'set_params', '~> 0.3'
|
|
21
|
+
|
|
22
|
+
s.add_development_dependency 'bundler', '~> 2.7'
|
|
23
|
+
s.add_development_dependency 'minitest', '~> 5.26'
|
|
24
|
+
s.add_development_dependency 'minitest-power_assert', '~> 0.3'
|
|
25
|
+
s.add_development_dependency 'rake', '~> 13.3'
|
|
26
|
+
s.add_development_dependency 'simple-rake-tasks', '~> 0.1'
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
end
|
data/test/main_test.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: simple-file-db
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: '0.7'
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- John Labovitz
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: csv
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '3.3'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '3.3'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: json
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '2.15'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '2.15'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: path
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '2.1'
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - "~>"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '2.1'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: set_params
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '0.3'
|
|
61
|
+
type: :runtime
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '0.3'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: bundler
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - "~>"
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '2.7'
|
|
75
|
+
type: :development
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - "~>"
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '2.7'
|
|
82
|
+
- !ruby/object:Gem::Dependency
|
|
83
|
+
name: minitest
|
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
|
85
|
+
requirements:
|
|
86
|
+
- - "~>"
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: '5.26'
|
|
89
|
+
type: :development
|
|
90
|
+
prerelease: false
|
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
92
|
+
requirements:
|
|
93
|
+
- - "~>"
|
|
94
|
+
- !ruby/object:Gem::Version
|
|
95
|
+
version: '5.26'
|
|
96
|
+
- !ruby/object:Gem::Dependency
|
|
97
|
+
name: minitest-power_assert
|
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - "~>"
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: '0.3'
|
|
103
|
+
type: :development
|
|
104
|
+
prerelease: false
|
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - "~>"
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: '0.3'
|
|
110
|
+
- !ruby/object:Gem::Dependency
|
|
111
|
+
name: rake
|
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
|
113
|
+
requirements:
|
|
114
|
+
- - "~>"
|
|
115
|
+
- !ruby/object:Gem::Version
|
|
116
|
+
version: '13.3'
|
|
117
|
+
type: :development
|
|
118
|
+
prerelease: false
|
|
119
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
120
|
+
requirements:
|
|
121
|
+
- - "~>"
|
|
122
|
+
- !ruby/object:Gem::Version
|
|
123
|
+
version: '13.3'
|
|
124
|
+
- !ruby/object:Gem::Dependency
|
|
125
|
+
name: simple-rake-tasks
|
|
126
|
+
requirement: !ruby/object:Gem::Requirement
|
|
127
|
+
requirements:
|
|
128
|
+
- - "~>"
|
|
129
|
+
- !ruby/object:Gem::Version
|
|
130
|
+
version: '0.1'
|
|
131
|
+
type: :development
|
|
132
|
+
prerelease: false
|
|
133
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
134
|
+
requirements:
|
|
135
|
+
- - "~>"
|
|
136
|
+
- !ruby/object:Gem::Version
|
|
137
|
+
version: '0.1'
|
|
138
|
+
description: Simple::FileDB is a database built upon JSON files.
|
|
139
|
+
email: johnl@johnlabovitz.com
|
|
140
|
+
executables: []
|
|
141
|
+
extensions: []
|
|
142
|
+
extra_rdoc_files: []
|
|
143
|
+
files:
|
|
144
|
+
- ".gitignore"
|
|
145
|
+
- README.md
|
|
146
|
+
- Rakefile
|
|
147
|
+
- TODO.txt
|
|
148
|
+
- lib/simple-file-db.rb
|
|
149
|
+
- lib/simple-file-db/item.rb
|
|
150
|
+
- simple-file-db.gemspec
|
|
151
|
+
- test/main_test.rb
|
|
152
|
+
homepage: http://github.com/jslabovitz/simple-file-db
|
|
153
|
+
licenses:
|
|
154
|
+
- MIT
|
|
155
|
+
metadata: {}
|
|
156
|
+
rdoc_options: []
|
|
157
|
+
require_paths:
|
|
158
|
+
- lib
|
|
159
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
160
|
+
requirements:
|
|
161
|
+
- - ">="
|
|
162
|
+
- !ruby/object:Gem::Version
|
|
163
|
+
version: '0'
|
|
164
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
165
|
+
requirements:
|
|
166
|
+
- - ">="
|
|
167
|
+
- !ruby/object:Gem::Version
|
|
168
|
+
version: '0'
|
|
169
|
+
requirements: []
|
|
170
|
+
rubygems_version: 3.7.2
|
|
171
|
+
specification_version: 4
|
|
172
|
+
summary: A database built upon JSON files
|
|
173
|
+
test_files:
|
|
174
|
+
- test/main_test.rb
|