tmsu_file_db 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +142 -0
- data/lib/tmsu_file_db.rb +50 -9
- data/lib/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 910c386ec16296462c430627b29d00ce9c718874
|
4
|
+
data.tar.gz: 60c51e32d1ddd33291fe0cbc930b09dd18c6f706
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a9f561e9efc1c6180264896d66d1bab28d8c8a5ac5b5b16c1f8ed1dd08c668e19f1b596e418ed7a0b288ebda99dfac566ff75066b834b7d50acaec78147f6b41
|
7
|
+
data.tar.gz: e81b583feb2a1bdadf8c433d38193c9f5965078a080c34e0a4c919c16e51e9e60e0bb12d016f200dc329d4aacd193840c9627e255c8d0518e4feeb83b1fc7683
|
data/README.md
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
This is an ORM similar to ActiveRecord, but uses the filesystem instead.
|
2
|
+
|
3
|
+
It uses TMSU which is a "non-hierarchical" filesystem tagging system.
|
4
|
+
|
5
|
+
Usage:
|
6
|
+
|
7
|
+
**Install the gem**
|
8
|
+
|
9
|
+
```sh
|
10
|
+
gem install tmsu_file_db
|
11
|
+
```
|
12
|
+
|
13
|
+
**Define a model**
|
14
|
+
|
15
|
+
```rb
|
16
|
+
require 'tmsu_file_db'
|
17
|
+
|
18
|
+
class User < TmsuModel
|
19
|
+
|
20
|
+
# this configure block is optional, it defaults to the current directory
|
21
|
+
configure root_path: "./db/users"
|
22
|
+
|
23
|
+
# Validations must return an array
|
24
|
+
validate do |record|
|
25
|
+
record.name.nil? ? ["name can't be blank"] : []
|
26
|
+
end
|
27
|
+
|
28
|
+
# Specific attributes can be validated as well
|
29
|
+
validate(:email) do |email, record|
|
30
|
+
email&.include?("@") ? ["email isn't valid"] : []
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
```
|
35
|
+
|
36
|
+
**Create instances**
|
37
|
+
|
38
|
+
# create, update, and delete
|
39
|
+
u = User.new name: "max"
|
40
|
+
u.valid? # => false
|
41
|
+
u.errors # => ["email isn't valid"]
|
42
|
+
u.save # => false
|
43
|
+
u.email = "maxpleaner@gmail.com"
|
44
|
+
u.valid? # => true
|
45
|
+
u.save # => true
|
46
|
+
u.update(email: "max.pleaner@gmail.com") # => true
|
47
|
+
u.update(email: "") # => false
|
48
|
+
|
49
|
+
# There are getter/setter methods for convenience
|
50
|
+
u.name # => "max"
|
51
|
+
u["name"] # => "max"
|
52
|
+
u[:name] # => "max"
|
53
|
+
u.name = "max p."
|
54
|
+
u[:name] # => "max p."
|
55
|
+
|
56
|
+
# All these getter/setters are working on 'attributes' under the hood.
|
57
|
+
u.attributes[:name] # => "max p."
|
58
|
+
|
59
|
+
# each record is assigned a filesystem path
|
60
|
+
u.path
|
61
|
+
|
62
|
+
# creating a new record will create a new file in the root_path
|
63
|
+
# but will not add anything to the file unless .write is called
|
64
|
+
u.write "hello"
|
65
|
+
|
66
|
+
# The content of the file is not part of the "attributes" i.e. name and email
|
67
|
+
# Those are stored using TMSU tags
|
68
|
+
u.tags # => { email: "max.pleaner@gmail.com", name: "max" }
|
69
|
+
|
70
|
+
# Attributes can be deleted
|
71
|
+
u.delete :name
|
72
|
+
u.tags # => { email: "max.pleaner@gmail.com" }
|
73
|
+
```
|
74
|
+
|
75
|
+
**Use class-level query methods**
|
76
|
+
|
77
|
+
_Note that this does not use Arel or any of that jazz. So chaining queries or using joins will not work._
|
78
|
+
|
79
|
+
_Note also that there is no `id` on models, only `path`, which is an absolute path._
|
80
|
+
|
81
|
+
```rb
|
82
|
+
User.where(name: "max p.")[0].name == "max p." # => true
|
83
|
+
User.find_by(name: "max p.").name == "max p." # => true
|
84
|
+
User.update_all(name: "max") # => true
|
85
|
+
User.all[0].name == "max" # => true
|
86
|
+
|
87
|
+
# You can make arbitrary queries using TMSU syntax
|
88
|
+
# e.g. select all users with email set that are not named melvin
|
89
|
+
User.query("name != 'melvin' and email")[0].name == "max" # => true
|
90
|
+
```
|
91
|
+
|
92
|
+
You can also skip `TmsuModel` and use `TmsuRuby.file` instead. This does _not_ handle creation / deletion of files. It should only be used with files that already exist.
|
93
|
+
|
94
|
+
Note that these methods are technically available on `TmsuModel` instances, callable on the `tmsu_file` attribute. But this shoudln't be done, because it will cause the in-memory attributes to be out of sync.
|
95
|
+
|
96
|
+
```rb
|
97
|
+
file_path = './my_pic.jpg' # this should already exist
|
98
|
+
|
99
|
+
tmsu_file = TmsuRuby.file file_path
|
100
|
+
tmsu_file.tags # => {}
|
101
|
+
|
102
|
+
tmsu_file.tag "foo" # .tag can be passed a string
|
103
|
+
tmsu_file.tags # => { foo: nil }
|
104
|
+
|
105
|
+
tmsu_file.untag "foo"
|
106
|
+
tmsu_file.tags # => { }
|
107
|
+
|
108
|
+
tmsu_file.tag ["foo", "bar"] # .tag can also be passed an array
|
109
|
+
tmsu_file.tags # => { foo: nil, bar: nil }
|
110
|
+
|
111
|
+
tmsu_file.tag(a: 1, b: 2) # .tag can also be passed a hash
|
112
|
+
tmsu_file.tags # => { foo: nil, bar: nil, a: 1, b: 2 }
|
113
|
+
```
|
114
|
+
|
115
|
+
It's also possible to use `TmsuRuby` to work on multiple files instead of just one:
|
116
|
+
|
117
|
+
```rb
|
118
|
+
glob_selector = "./**/*.jpg"
|
119
|
+
|
120
|
+
tmsu_file = TmsuRuby.file glob_selector
|
121
|
+
|
122
|
+
# there is a special method used to add tags in this case
|
123
|
+
tmsu_file.tag_selector "foo"
|
124
|
+
tmsu_file.tag_selector ["a", "b"]
|
125
|
+
tmsu_file.tag_selector c: 1, d: 2
|
126
|
+
|
127
|
+
# Simiarly to untag
|
128
|
+
tmsu_file.untag_selector "c"
|
129
|
+
|
130
|
+
# check that the tags were added to files
|
131
|
+
TmsuRuby.file("./my_pic.jpg").tags
|
132
|
+
# => { foo: nil, a: nil, b: nil, d: 2 }
|
133
|
+
```
|
134
|
+
|
135
|
+
Using `TmsuRuby.file` you can search by tag as well:
|
136
|
+
|
137
|
+
```rb
|
138
|
+
# Returns array of paths (files with the tag, systemwide)
|
139
|
+
TmsuRuby.file("name")
|
140
|
+
```
|
141
|
+
|
142
|
+
|
data/lib/tmsu_file_db.rb
CHANGED
@@ -18,7 +18,7 @@ class TmsuModel
|
|
18
18
|
|
19
19
|
def self.configure(root_path:)
|
20
20
|
Config[:root_path] = root_path || "./db".tap do |path|
|
21
|
-
`mkdir #{path}`
|
21
|
+
`mkdir -p #{path}`
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
@@ -51,16 +51,31 @@ class TmsuModel
|
|
51
51
|
query opts_to_query opts
|
52
52
|
end
|
53
53
|
|
54
|
+
def self.all
|
55
|
+
|
56
|
+
end
|
57
|
+
|
54
58
|
def self.query string
|
55
|
-
TmsuFile.new(query_glob).paths_query(query)
|
59
|
+
TmsuFile.new(query_glob).paths_query(query).map do |path|
|
60
|
+
new TmsuFile.new(path).tags
|
61
|
+
end
|
56
62
|
end
|
57
63
|
|
58
64
|
def self.update_all opts={}
|
59
|
-
Dir.glob(query_glob).each
|
65
|
+
Dir.glob(query_glob).each do |path|
|
66
|
+
errors = new(path).tap { |inst| inst.update(opts) }.errors
|
67
|
+
unless errors.empty?
|
68
|
+
raise(
|
69
|
+
ArgumentError, "couldn't update all. Path #{path} caused errors: #{errors.join(", ")}"
|
70
|
+
)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
true
|
60
74
|
end
|
61
75
|
|
62
76
|
def self.destroy_all opts={}
|
63
77
|
Dir.glob(query_glob).each { |path| `rm #{path}` }
|
78
|
+
true
|
64
79
|
end
|
65
80
|
|
66
81
|
attr_reader :attributes, :errors, :path
|
@@ -92,7 +107,10 @@ class TmsuModel
|
|
92
107
|
end
|
93
108
|
|
94
109
|
def method_missing(sym, *arguments, &blk)
|
95
|
-
|
110
|
+
attr_name = sym.to_s[0..-1]
|
111
|
+
if sym.to_s[-1] == "=" && attributes.keys.include?(attr_name)
|
112
|
+
attributes[attr_name] = arguments[0]
|
113
|
+
elsif attributes.keys.include? sym
|
96
114
|
attributes[sym]
|
97
115
|
else
|
98
116
|
super
|
@@ -138,14 +156,22 @@ class TmsuModel
|
|
138
156
|
|
139
157
|
def save
|
140
158
|
ensure_persisted
|
159
|
+
return false unless valid?
|
141
160
|
tag attributes
|
142
|
-
|
161
|
+
true
|
143
162
|
end
|
144
163
|
|
145
164
|
def update attrs={}
|
165
|
+
original_attrs = attributes.clone
|
146
166
|
attrs.each_key { |k| self[k] = attrs[k] }
|
167
|
+
unless valid?
|
168
|
+
# rollback attribute change
|
169
|
+
self.attributes.clear
|
170
|
+
original_attrs.each { |k,v| self[k] = v }
|
171
|
+
return false
|
172
|
+
end
|
147
173
|
save
|
148
|
-
|
174
|
+
true
|
149
175
|
end
|
150
176
|
|
151
177
|
def destroy
|
@@ -153,6 +179,12 @@ class TmsuModel
|
|
153
179
|
self
|
154
180
|
end
|
155
181
|
|
182
|
+
def delete(attr)
|
183
|
+
untag(attr)
|
184
|
+
attributes.delete attr
|
185
|
+
attr
|
186
|
+
end
|
187
|
+
|
156
188
|
end
|
157
189
|
|
158
190
|
module SystemPatch
|
@@ -172,7 +204,7 @@ module TmsuRubyInitializer
|
|
172
204
|
puts "initializing tmsu"
|
173
205
|
puts system "tmsu init"
|
174
206
|
puts "making vfs_path #{vfs_path}"
|
175
|
-
puts system "mkdir #{vfs_path}"
|
207
|
+
puts system "mkdir -p #{vfs_path}"
|
176
208
|
puts "mounting vfs path"
|
177
209
|
puts system "tmsu mount #{vfs_path}"
|
178
210
|
end
|
@@ -186,7 +218,6 @@ module TmsuFileAPI
|
|
186
218
|
using SystemPatch
|
187
219
|
|
188
220
|
def tags
|
189
|
-
ensure_persisted
|
190
221
|
system("tmsu tags #{path}").split(" ")[1..-1].reduce({}) do |res, tag|
|
191
222
|
key, val = tag.split("=")
|
192
223
|
res.tap { res[key] = val }
|
@@ -202,7 +233,6 @@ module TmsuFileAPI
|
|
202
233
|
|
203
234
|
def untag tag_list
|
204
235
|
`touch #{path}` unless persisted?
|
205
|
-
attributes.delete
|
206
236
|
system "tmsu untag #{path} #{tag_list}"
|
207
237
|
tags
|
208
238
|
end
|
@@ -231,6 +261,17 @@ module TmsuFileAPI
|
|
231
261
|
files tag_obj
|
232
262
|
end
|
233
263
|
|
264
|
+
def untag_selector(tag_obj)
|
265
|
+
tag_arg = case tag_obj
|
266
|
+
when String
|
267
|
+
tag_obj
|
268
|
+
when Array
|
269
|
+
tag_obj.join(" ")
|
270
|
+
end
|
271
|
+
system "tmsu tag --tags '#{build_tag_arg tag_obj}' #{path}"
|
272
|
+
files tag_obj
|
273
|
+
end
|
274
|
+
|
234
275
|
def merge_tag(source, dest)
|
235
276
|
source_files = files source
|
236
277
|
dest_files = files dest
|
data/lib/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tmsu_file_db
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- maxpleaner
|
@@ -31,6 +31,7 @@ executables:
|
|
31
31
|
extensions: []
|
32
32
|
extra_rdoc_files: []
|
33
33
|
files:
|
34
|
+
- README.md
|
34
35
|
- bin/tmsu_file_db
|
35
36
|
- lib/tmsu_file_db.rb
|
36
37
|
- lib/version.rb
|