Class: S3DB::FileBackend
Constant Summary collapse
- PATH_BLACKLIST =
[ 'bin', 'boot', 'cdrom', 'data', 'dev', 'docker', 'etc', 'home', 'lib', 'lib64', 'media', 'mnt', 'opt', 'proc', 'root', 'run', 'sbin', 'srv', 'sys', 'usr', 'var', 'badpath', #this is just to be VERY sure we don't trash a real dir in tests ]
Instance Attribute Summary collapse
-
#errors ⇒ Object
readonly
Returns the value of attribute errors.
-
#path ⇒ Object
readonly
Returns the value of attribute path.
Class Method Summary collapse
-
.create(path) ⇒ Object
Create a new base path for a file backend storage location.
-
.create!(path) ⇒ Object
Create a new base path for a file backend storage location.
-
.delete(path) ⇒ Object
Destroy a base path, whether or not it’s empty.
-
.destroy(path) ⇒ Object
Destroy a base path for data storage.
Instance Method Summary collapse
-
#collection_path(db_name, collection_name) ⇒ Object
Build a full path to a collection from the base path, database name and collection name.
-
#data_path(db_name, collection_name) ⇒ Object
Build a full path to the data dir from the base path, database name and collection name.
- #db_exist?(db_name) ⇒ Boolean
-
#db_path(db_name) ⇒ Object
Build a full path from the base path and database name.
-
#delete_collection(db_name, collection_name) ⇒ Object
Delete a collection directory from disk.
-
#delete_db(db_name) ⇒ Object
Delete a database directory from disk.
-
#delete_record(db_name, collection_name, filename) ⇒ Object
Delete a collection directory from disk.
-
#delete_record!(db_name, collection_name, filename) ⇒ Object
Delete a collection directory from disk.
-
#destroy ⇒ Object
Destroy a FileBackend basepath.
-
#destroy! ⇒ Object
Destroy a FileBackend basepath.
-
#initialize(path) ⇒ FileBackend
constructor
Create a new FileBackend.
-
#list_collections(db_name) ⇒ Object
List all available collections in a database.
-
#list_records(db_name, coll_name) ⇒ Object
List all available records for a database/collection.
-
#read_record(db_name, coll_name, filename) ⇒ Object
Read the contents of a record in a database/collection.
-
#read_schema(db_name, collection_name) ⇒ Object
Read the contents of the schema file.
-
#record_path(db_name, collection_name, filename) ⇒ Object
Build a full path to a record from the base path, database name, collection name, and filename.
-
#save ⇒ Object
Save a FileBackend, which means writing its root path directory to the filesystem.
-
#save! ⇒ Object
Save a FileBackend, which means writing its root path directory to the filesystem.
-
#schema_path(db_name, collection_name) ⇒ Object
Build a full path to a scema from the base path, database name and collection name.
-
#valid! ⇒ Object
Confirm that the backend is in a consistent state.
-
#valid? ⇒ Boolean
Check to see whether the backend is in a valid state.
-
#validate_path ⇒ Object
Check a path to ensure it does not violate basic sanity rules, such as being a linux system path, or having weird characters in the name.
-
#write_collection(db_name, collection_name) ⇒ Object
Write a directory to disk for the name of the collection.
-
#write_db(db_name) ⇒ Object
Write a directory to disk for the name of the database.
-
#write_record(db_name, coll_name, filename, data) ⇒ Object
Write a record to a database/collection.
-
#write_schema(db_name, collection_name, schema) ⇒ Object
Write a file to disk for the schema for a database/collection.
Constructor Details
#initialize(path) ⇒ FileBackend
Create a new FileBackend.
path - String path to use as the base storage location.
returns a new FileBackend.
94 95 96 97 98 |
# File 'lib/s3db/file_backend.rb', line 94 def initialize(path) @errors = [] @path = path.strip end |
Instance Attribute Details
#errors ⇒ Object (readonly)
Returns the value of attribute errors.
5 6 7 |
# File 'lib/s3db/file_backend.rb', line 5 def errors @errors end |
#path ⇒ Object (readonly)
Returns the value of attribute path.
5 6 7 |
# File 'lib/s3db/file_backend.rb', line 5 def path @path end |
Class Method Details
.create(path) ⇒ Object
Create a new base path for a file backend storage location. This method will create the basepath if it doesn’t exist, but also use an existing path if it does exest.
path - String base path. Required.
returns a new FileBackend.
40 41 42 43 44 45 |
# File 'lib/s3db/file_backend.rb', line 40 def create(path) be = new(path) be.save be end |
.create!(path) ⇒ Object
Create a new base path for a file backend storage location. This method will throw an error if the path already exists. This is safer.
path - String base path. Required.
returns a new FileBackend.
53 54 55 56 57 58 |
# File 'lib/s3db/file_backend.rb', line 53 def create!(path) be = new(path) be.save! be end |
.delete(path) ⇒ Object
Destroy a base path, whether or not it’s empty. This is dangerous, and should be used with great care.
path - String path to delete. Required.
returns itself on success, and raises an error on failure.
78 79 80 81 82 83 84 85 86 |
# File 'lib/s3db/file_backend.rb', line 78 def delete(path) be = new(path) if be.valid! FileUtils.rm_rf(path) end self end |
.destroy(path) ⇒ Object
Destroy a base path for data storage. This method will raise an error if the directory is not empty.
path - String base path. Required.
returns the String path that was removed.
66 67 68 69 70 |
# File 'lib/s3db/file_backend.rb', line 66 def destroy(path) be = new(path).destroy be end |
Instance Method Details
#collection_path(db_name, collection_name) ⇒ Object
Build a full path to a collection from the base path, database name and collection name.
db_name - String name of database. Required. collection_name - String name of collection. Required.
returns a String path.
219 220 221 |
# File 'lib/s3db/file_backend.rb', line 219 def collection_path(db_name, collection_name) File.join(@path, db_name, collection_name) end |
#data_path(db_name, collection_name) ⇒ Object
Build a full path to the data dir from the base path, database name and collection name.
db_name - String name of database. Required. collection_name - String name of collection. Required.
returns a String path.
241 242 243 |
# File 'lib/s3db/file_backend.rb', line 241 def data_path(db_name, collection_name) File.join(@path, db_name, collection_name, 'data') end |
#db_exist?(db_name) ⇒ Boolean
488 489 490 |
# File 'lib/s3db/file_backend.rb', line 488 def db_exist?(db_name) Dir.exist?(db_path(db_name)) end |
#db_path(db_name) ⇒ Object
Build a full path from the base path and database name.
db_name - String name of database. Required.
returns a String path.
208 209 210 |
# File 'lib/s3db/file_backend.rb', line 208 def db_path(db_name) File.join(@path, db_name) end |
#delete_collection(db_name, collection_name) ⇒ Object
Delete a collection directory from disk. Will only succed if the collection is empty.
db_name - String name of database to remove. Required. collection_name - String name of collection to remove. Required.
returns an Array of the databases deleted, or empty if the database did not exist.
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 |
# File 'lib/s3db/file_backend.rb', line 420 def delete_collection(db_name, collection_name) path = collection_path(db_name, collection_name) if File.exist?(schema_path(db_name, collection_name)) File.delete(schema_path(db_name, collection_name)) end if Dir.exist?(data_path(db_name, collection_name)) begin Dir.rmdir(data_path(db_name, collection_name)) rescue Errno::ENOTEMPTY raise ArgumentError, 'collection/data is not empty!' end end if Dir.exist?(path) begin Dir.rmdir(path) rescue Errno::ENOTEMPTY raise ArgumentError, 'collection is not empty!' end return [collection_name] end [] end |
#delete_db(db_name) ⇒ Object
Delete a database directory from disk. Will only succed if the database is empty.
db_name - String name of database to remove. Required.
returns an Array of the databases deleted, or empty if the database did not exist.
396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 |
# File 'lib/s3db/file_backend.rb', line 396 def delete_db(db_name) path = db_path(db_name) if Dir.exist?(path) begin Dir.rmdir(path) rescue Errno::ENOTEMPTY raise ArgumentError, 'database is not empty!' end return [db_name] end [] end |
#delete_record(db_name, collection_name, filename) ⇒ Object
Delete a collection directory from disk. Will only succed if the collection is empty.
db_name - String name of database to remove. Required. collection_name - String name of collection to remove. Required.
returns an Array of the databases deleted, or empty if the database did not exist.
456 457 458 459 460 461 462 463 464 465 466 |
# File 'lib/s3db/file_backend.rb', line 456 def delete_record(db_name, collection_name, filename) path = record_path(db_name, collection_name, filename) begin File.delete(path) rescue Errno::ENOENT return '' end filename end |
#delete_record!(db_name, collection_name, filename) ⇒ Object
Delete a collection directory from disk. Will only succed if the collection is empty.
db_name - String name of database to remove. Required. collection_name - String name of collection to remove. Required.
returns an Array of the databases deleted, or empty if the database did not exist.
476 477 478 479 480 481 482 483 484 485 486 |
# File 'lib/s3db/file_backend.rb', line 476 def delete_record!(db_name, collection_name, filename) path = record_path(db_name, collection_name, filename) begin File.delete(path) rescue Errno::ENOENT raise ArgumentError, 'record does not exist!' end filename end |
#destroy ⇒ Object
Destroy a FileBackend basepath. The directory must be empty (which means you must destroy all collections/dbs in the basepath first).
returns itself on success, false on failure.
173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/s3db/file_backend.rb', line 173 def destroy return false unless valid? begin Dir.rmdir(@path) rescue Errno::ENOTEMPTY, Errno::ENOENT return false end self end |
#destroy! ⇒ Object
Destroy a FileBackend basepath. The directory must be empty (which means you must destroy all collections/dbs in the basepath first).
returns itself on success, raises an error on failure.
189 190 191 192 193 194 195 196 197 198 199 200 201 |
# File 'lib/s3db/file_backend.rb', line 189 def destroy! valid! begin Dir.rmdir(@path) rescue Errno::ENOENT raise ArgumentError, 'basepath does not exist!' rescue Errno::ENOTEMPTY raise ArgumentError, 'basepath not empty!' end self end |
#list_collections(db_name) ⇒ Object
List all available collections in a database.
db_name - String name of database to look in. Required.
returns an Array of String collection names.
330 331 332 333 334 |
# File 'lib/s3db/file_backend.rb', line 330 def list_collections(db_name) Dir.entries(db_path(db_name)).select do |dir| !File.directory?(dir) end end |
#list_records(db_name, coll_name) ⇒ Object
List all available records for a database/collection.
db_name - String name of database to look in. Required. collection_name - String name of collection to look in. Required.
returns an Array of String record file names.
342 343 344 345 346 347 348 349 350 351 352 |
# File 'lib/s3db/file_backend.rb', line 342 def list_records(db_name, coll_name) output = [] Dir.open(data_path(db_name, coll_name)) do |dir| dir.each do |file| output << file unless File.directory?(file) end end output end |
#read_record(db_name, coll_name, filename) ⇒ Object
Read the contents of a record in a database/collection
db_name - String name of database to look in. Required. collection_name - String name of collection to look in. Required. filename - String name of the file to read w/extension. Required.
returns the String contents of the record file. Raises an error if the file is missing.
379 380 381 382 383 384 385 386 387 |
# File 'lib/s3db/file_backend.rb', line 379 def read_record(db_name, coll_name, filename) file = record_path(db_name, coll_name, filename) begin File.read(file) rescue Errno::ENOENT raise ArgumentError, 'record does not exist!' end end |
#read_schema(db_name, collection_name) ⇒ Object
Read the contents of the schema file.
db_name - String name of database to look in. Required. collection_name - String name of collection to look in. Required.
returns the String contents of the schema file. Raises an error if the file is missing.
361 362 363 364 365 366 367 368 369 |
# File 'lib/s3db/file_backend.rb', line 361 def read_schema(db_name, collection_name) file = schema_path(db_name, collection_name) begin File.read(file) rescue Errno::ENOENT raise ArgumentError, 'schema does not exist!' end end |
#record_path(db_name, collection_name, filename) ⇒ Object
Build a full path to a record from the base path, database name, collection name, and filename.
db_name - String name of database. Required. collection_name - String name of collection. Required.
returns a String path.
252 253 254 |
# File 'lib/s3db/file_backend.rb', line 252 def record_path(db_name, collection_name, filename) File.join(@path, db_name, collection_name, 'data', filename) end |
#save ⇒ Object
Save a FileBackend, which means writing its root path directory to the filesystem.
returns itself on success, returns false on failure.
144 145 146 147 148 149 150 |
# File 'lib/s3db/file_backend.rb', line 144 def save return false unless valid? FileUtils.mkdir_p(@path) self end |
#save! ⇒ Object
Save a FileBackend, which means writing its root path directory to the filesystem.
returns itself on success, raises an error on failure.
156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/s3db/file_backend.rb', line 156 def save! valid! begin Dir.mkdir(@path) rescue Errno::EEXIST raise ArgumentError, 'base path exists!' end self end |
#schema_path(db_name, collection_name) ⇒ Object
Build a full path to a scema from the base path, database name and collection name.
db_name - String name of database. Required. collection_name - String name of collection. Required.
returns a String path.
230 231 232 |
# File 'lib/s3db/file_backend.rb', line 230 def schema_path(db_name, collection_name) File.join(@path, db_name, collection_name, 'schema.json') end |
#valid! ⇒ Object
Confirm that the backend is in a consistent state. Raises an error on failure.
returns true on success, raises an error on failure.
132 133 134 135 136 137 138 |
# File 'lib/s3db/file_backend.rb', line 132 def valid! if !valid? raise ArgumentError, @errors.join(', ') end true end |
#valid? ⇒ Boolean
Check to see whether the backend is in a valid state.
returns Bool.
120 121 122 123 124 125 126 |
# File 'lib/s3db/file_backend.rb', line 120 def valid? @errors = [] validate_path !@errors.any? end |
#validate_path ⇒ Object
Check a path to ensure it does not violate basic sanity rules, such as being a linux system path, or having weird characters in the name.
path - String path to check. Required.
returns true if it checks out, false otherwise. It will raise an error for dangerous exceptions.
107 108 109 110 111 112 113 114 115 |
# File 'lib/s3db/file_backend.rb', line 107 def validate_path PATH_BLACKLIST.each do |p| @errors << "`#{p}` is insane to use as a base path!" if @path =~ /#{p}/i end if @path !~ /^(\w|\/)+$/ @errors << "path does not match /^(\w|\/)+$/" end end |
#write_collection(db_name, collection_name) ⇒ Object
Write a directory to disk for the name of the collection. Will ignore the write if the directory exists.
db_name - String name of database. Required. collection_name - String name of collection. Required.
returns collection_name on success; raises an error on failure.
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 |
# File 'lib/s3db/file_backend.rb', line 275 def write_collection(db_name, collection_name) dir = collection_path(db_name, collection_name) unless Dir.exist?(dir) Dir.mkdir(dir) end dir = data_path(db_name, collection_name) unless Dir.exist?(dir) Dir.mkdir(dir) end collection_name end |
#write_db(db_name) ⇒ Object
Write a directory to disk for the name of the database. Will fail if the database already exists.
db_name - String name of database. Required.
returns db_name on success; raises an error on failure.
262 263 264 265 266 |
# File 'lib/s3db/file_backend.rb', line 262 def write_db(db_name) FileUtils.mkdir_p(db_path(db_name)) db_name end |
#write_record(db_name, coll_name, filename, data) ⇒ Object
Write a record to a database/collection. The record can be in any format. No parsing of the file is performed. Data must be sent as a string.
db_name - String name of database. Required. collection_name - String name of collection. Required. filename - String name of file to write, w/extension. Required. data - String data to write to the file. Required.
returns the data written.
315 316 317 318 319 320 321 322 323 |
# File 'lib/s3db/file_backend.rb', line 315 def write_record(db_name, coll_name, filename, data) raise ArgumentError, 'data must be a string!' unless data.is_a?(String) File.open(record_path(db_name, coll_name, filename), 'w') do |f| f.puts data end data end |
#write_schema(db_name, collection_name, schema) ⇒ Object
Write a file to disk for the schema for a database/collection.
db_name - String name of database. Required. collection_name - String name of collection. Required. schema - String schema contents. Required.
returns the schema on success; raises an error on failure.
298 299 300 301 302 303 304 |
# File 'lib/s3db/file_backend.rb', line 298 def write_schema(db_name, collection_name, schema) File.open(schema_path(db_name, collection_name), 'w') do |f| f.puts schema end schema end |