cabi 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
+ SHA1:
3
+ metadata.gz: 83fa2db5429675243c8acd14559770b0f65fd5f2
4
+ data.tar.gz: 5fb58665d172b8e4ba324fc316fea0fc50ec2436
5
+ SHA512:
6
+ metadata.gz: b4d55e6e7c80c0c49565eeffe659866662adac9b4668faab05f11c73b315816af9902044cd313e6814b26069a3dea09727ccf85960cd2210c15104801af40b90
7
+ data.tar.gz: 34b74e174b4396ec9d7073bb501549e8a98e8c0dd7eca7d92882aad6d0bc2e26b592ae87abb3449485f9859a9c05bf8feabbb1122030e1fe4fd74c28d4c9dc9a
data/README.md ADDED
@@ -0,0 +1,67 @@
1
+ # <img src="https://rawgithub.com/briangonzalez/cabi-gem/master/data/cabi.svg" width=30 style="margin-right: 10px"> Cabi
2
+
3
+ A simple, flat-file datastore for Ruby.
4
+
5
+ ### Getting Started
6
+
7
+ Cabi is a flat-file datastore where data is stored by directory stucture and accessed by colon-delimited strings. Here's how to get started:
8
+
9
+ ``` bash
10
+ $ gem install cabi
11
+ $ cabi init --mock
12
+ ```
13
+
14
+ Then access your data like so:
15
+
16
+ ```bash
17
+ $ irb
18
+ > require 'cabi'
19
+ > Cabi::Cache.read('pages:about:body')
20
+ => "<h1>Hello, Cabi!</h1>"
21
+ ```
22
+
23
+ ### Usage
24
+
25
+ Assuming your `cabi-cache` folder has the following structure:
26
+
27
+ - my-project
28
+ |
29
+ |--cabi-cache
30
+ |-- info.yml
31
+ |-- pages
32
+ | |-- about
33
+ | |-- body.html
34
+ | |-- meta.yml
35
+ |
36
+ |-- posts
37
+ |-- some-article
38
+ |-- index.html
39
+ |-- nav.html
40
+
41
+
42
+ You could then query your data like so:
43
+
44
+ ```ruby
45
+ Cabi.read('pages:about:body') # returns contents of page/about/body.html
46
+ Cabi.read('pages:about:meta:foo:bar') # returns contents of ['foo']['bar'] in page/about/meta.yml hash
47
+ Cabi.read('info:foo:bar:baz') # returns contents of ['foo']['bar']['baz'] in info.yml hash
48
+ Cabi.read('posts:some-article:index') # returns contents of posts/some-article/index.html
49
+ Cabi.read('posts:some-article:index.html') # returns contents of posts/some-article/index.html
50
+ ```
51
+
52
+ ### Custom Cache Directory
53
+
54
+ Cabi assumes that your cache directory is either a folder at the top level of your project with a `.cabi-cache` file in it (to indicate that it's the cache directory). If one is not found, the cache directory defaults to `./cabi-cache`.
55
+
56
+ For instance, if you had a folder called `super-cache` located inside of your project's root that had a file called `.cabi-cache` inside of it, this folder would be treated as your cache directory.
57
+
58
+ ### Questions?
59
+
60
+ Find me online [@brianmgonzalez](http://twitter.com/brianmgonzalez)
61
+
62
+ ### Icon <img src="https://rawgithub.com/briangonzalez/cabi-gem/master/data/cabi.svg" width=20 style="margin-right: 10px">
63
+
64
+ [Cabi Icon](http://thenounproject.com/noun/file-cabinet/#icon-No22117) designed by Michela Tannoia, from The Noun Project.
65
+
66
+ ### Tests
67
+ Run the test suite by running `rake test` in the parent directory.
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.libs << 'test'
5
+ end
6
+
7
+ desc "Run tests"
8
+ task :default => :test
data/bin/cabi ADDED
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env ruby
2
+ require "thor"
3
+ require "fileutils"
4
+
5
+ CACHE_DIR = 'cabi-cache'
6
+
7
+ class CabiCLI < Thor
8
+
9
+ desc "init", "Initialize Cabi cache directory (use --mock to create fake data, use --target to specify your own directory)"
10
+ method_options :mock => :boolean, :target => :string
11
+ def init
12
+
13
+ target = options[:target] || CACHE_DIR
14
+ FileUtils.mkdir( target )
15
+
16
+ if options[:mock]
17
+ f = File.expand_path( "../../data/cabi-cache.tar.gz", __FILE__ )
18
+ `tar -xf #{f} --strip-components=1 -C #{target}`
19
+ end
20
+
21
+ end
22
+
23
+ desc "clean", "Remove Cabi cache directory"
24
+ method_options :force => :boolean
25
+ def clean
26
+ if options[:force]
27
+ FileUtils.rm_rf( CACHE_DIR ) if options[:force]
28
+ else
29
+ puts "Not cleaning without --force"
30
+ end
31
+ end
32
+
33
+ end
34
+
35
+ CabiCLI.start
data/cabi.gemspec ADDED
@@ -0,0 +1,18 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'cabi'
3
+ s.version = '0.1.0'
4
+ s.summary = "A simple, flat-file datastore for Ruby."
5
+
6
+ s.description = "Cabi is a flat-file datastore where data is stored by directory stucture and accessed by colon-delimited strings."
7
+ s.authors = ["Brian Gonzalez"]
8
+ s.email = 'me@briangonzalez.org'
9
+ s.homepage = 'http://github.com/briangonzalez/cabi-gem'
10
+ s.license = 'MIT'
11
+
12
+ s.files = Dir['[A-Z]*', 'cabi.gemspec', '{bin,lib,conf,web,data}/**/*'] - ['Gemfile.lock']
13
+ s.executables << 'cabi'
14
+
15
+ s.add_dependency "thor", "~> 0.18", ">= 0.18.1"
16
+
17
+ s.required_ruby_version = '>= 1.9.3'
18
+ end
Binary file
data/data/cabi.svg ADDED
@@ -0,0 +1,21 @@
1
+ <svg xmlns:x="http://ns.adobe.com/Extensibility/1.0/" xmlns:i="http://ns.adobe.com/AdobeIllustrator/10.0/" xmlns:graph="http://ns.adobe.com/Graphs/1.0/" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Your_Icon" x="0px" y="0px" width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
2
+ <switch>
3
+ <foreignObject requiredExtensions="http://ns.adobe.com/AdobeIllustrator/10.0/" x="0" y="0" width="1" height="1">
4
+ </foreignObject>
5
+ <g i:extraneous="self">
6
+ <g>
7
+ <path d="M88.743,10.01c-0.054-5.781-7.651-9.701-7.982-9.869C80.576,0.048,80.373,0,80.166,0H19.71 c-0.208,0-0.411,0.048-0.595,0.141c-0.338,0.171-8.269,4.245-7.996,10.223c0.001,0.012,0.008,0.023,0.008,0.035 C11.047,10.753,11,11.12,11,11.496v76.741c0,2.899,2.522,5.259,5.622,5.259h4.202v1.245c0,2.899,2.523,5.259,5.623,5.259h0.71 c3.1,0,5.622-2.359,5.622-5.259v-1.245h34.441v1.245c0,2.899,2.522,5.259,5.622,5.259h0.71c3.1,0,5.623-2.359,5.623-5.259v-1.245 h4.202c3.099,0,5.622-2.359,5.622-5.259V11.496C89,10.977,88.895,10.485,88.743,10.01z M86.275,30.158H13.725V11.496 c0-1.403,1.301-2.545,2.897-2.545h66.756c1.598,0,2.897,1.142,2.897,2.545V30.158z M13.725,31.803h72.551v21.769H13.725V31.803z M20.035,2.616h59.807c1.205,0.652,3.23,2.016,4.652,3.728c-0.361-0.068-0.734-0.105-1.116-0.105H16.622 c-0.435,0-0.854,0.058-1.261,0.145C16.784,4.658,18.822,3.274,20.035,2.616z M30.055,94.741c0,1.403-1.301,2.546-2.897,2.546 h-0.71c-1.598,0-2.898-1.143-2.898-2.546v-1.245h6.506V94.741z M76.451,94.741c0,1.403-1.301,2.546-2.898,2.546h-0.71 c-1.597,0-2.897-1.143-2.897-2.546v-1.245h6.506V94.741z M83.378,90.783H16.622c-1.597,0-2.897-1.143-2.897-2.546V55.215h72.551 v33.022C86.275,89.641,84.976,90.783,83.378,90.783z"/>
8
+ <path d="M60.804,20.102c0,0.675-0.677,1.244-1.478,1.244H40.508c-0.802,0-1.479-0.569-1.479-1.244v-4.228h-2.725v4.228 c0,2.181,1.886,3.956,4.203,3.956h18.818c2.316,0,4.202-1.775,4.202-3.956v-4.228h-2.725V20.102z"/>
9
+ <path d="M26.328,34.064H16.162c-0.455,0-0.824,0.367-0.824,0.82v3.602c0,0.453,0.369,0.821,0.824,0.821s0.825-0.368,0.825-0.821 v-2.779h9.341c0.455,0,0.826-0.369,0.826-0.822S26.783,34.064,26.328,34.064z"/>
10
+ <path d="M16.162,41.133c-0.455,0-0.824,0.368-0.824,0.82v3.254c0,0.453,0.369,0.821,0.824,0.821s0.825-0.368,0.825-0.821v-3.254 C16.987,41.501,16.617,41.133,16.162,41.133z"/>
11
+ <path d="M60.43,39.273v4.228c0,0.675-0.678,1.243-1.48,1.243H40.131c-0.801,0-1.479-0.568-1.479-1.243v-4.228h-2.724v4.228 c0,2.181,1.886,3.956,4.202,3.956h18.818c2.318,0,4.205-1.775,4.205-3.956v-4.228H60.43z"/>
12
+ <path d="M60.43,65.609c0,0.675-0.678,1.245-1.48,1.245H40.131c-0.801,0-1.479-0.57-1.479-1.245v-4.228h-2.724v4.228 c0,2.182,1.886,3.957,4.202,3.957h18.818c2.318,0,4.205-1.775,4.205-3.957v-4.228H60.43V65.609z"/>
13
+ <path d="M16.622,21.19c-0.455,0-0.825,0.368-0.825,0.821v2.6c0,0.454,0.37,0.822,0.825,0.822s0.825-0.368,0.825-0.822v-2.6 C17.447,21.558,17.077,21.19,16.622,21.19z"/>
14
+ <path d="M28.698,10.675H16.622c-0.455,0-0.825,0.368-0.825,0.821v5.963c0,0.454,0.37,0.822,0.825,0.822s0.825-0.368,0.825-0.822 v-5.141h11.251c0.455,0,0.825-0.368,0.825-0.822C29.523,11.043,29.153,10.675,28.698,10.675z"/>
15
+ <path d="M28.698,57.475H16.622c-0.455,0-0.825,0.369-0.825,0.822v4.252c0,0.453,0.37,0.82,0.825,0.82s0.825-0.367,0.825-0.82 v-3.432h11.251c0.455,0,0.825-0.367,0.825-0.82S29.153,57.475,28.698,57.475z"/>
16
+ <path d="M16.622,65.628c-0.455,0-0.825,0.368-0.825,0.822v5.853c0,0.453,0.37,0.821,0.825,0.821s0.825-0.368,0.825-0.821V66.45 C17.447,65.996,17.077,65.628,16.622,65.628z"/>
17
+ <path d="M16.622,77.12c-0.455,0-0.825,0.368-0.825,0.822v3.034c0,0.452,0.37,0.82,0.825,0.82s0.825-0.368,0.825-0.82v-3.034 C17.447,77.488,17.077,77.12,16.622,77.12z"/>
18
+ </g>
19
+ </g>
20
+ </switch>
21
+ </svg>
data/lib/cabi.rb ADDED
@@ -0,0 +1,23 @@
1
+
2
+ require 'yaml'
3
+
4
+ Dir.glob( File.expand_path( '..', __FILE__) + '/*.rb' ).each do |f|
5
+ require File.join( File.expand_path( '..', f), File.basename(f, File.extname(f)) )
6
+ end
7
+
8
+ module Cabi
9
+
10
+ DELIMITER = ':'
11
+ YAML_EXT = '.yml'
12
+ CABI_CACHE_ID = '.cabi-cache'
13
+ CABI_CACHE_DIR = './cabi-cache'
14
+
15
+ def self.read(id)
16
+ Cache.read(id)
17
+ end
18
+
19
+ def self.write(id, content)
20
+ Cache.write(id, content)
21
+ end
22
+
23
+ end
data/lib/cache.rb ADDED
@@ -0,0 +1,40 @@
1
+ module Cabi
2
+
3
+ class Cache
4
+
5
+ def self.read(id)
6
+ DataFile.contents(id) || nil
7
+ end
8
+
9
+ def self.write(id, content)
10
+ file = DataFile.write(id, content)
11
+ end
12
+
13
+ def self.user_cache_dir
14
+ dir = false
15
+
16
+ Dir.foreach('.') do |item|
17
+ next if item == '.' or item == '..'
18
+ if File.directory?(item) and File.exists?( File.join(item, CABI_CACHE_ID) )
19
+ dir = item
20
+ end
21
+ break if dir
22
+ end
23
+
24
+ dir
25
+ end
26
+
27
+ end
28
+
29
+ # Helpers for setting/getting cache dir.
30
+ def self.cache_dir
31
+ @@cache_dir ||= Cache.user_cache_dir || CABI_CACHE_DIR
32
+ raise LoadError.new "Could not find cabi cache folder!" unless File.exists? @@cache_dir
33
+ @@cache_dir
34
+ end
35
+
36
+ def self.reset_cache_dir
37
+ @@cache_dir = nil
38
+ end
39
+
40
+ end
data/lib/datafile.rb ADDED
@@ -0,0 +1,92 @@
1
+ module Cabi
2
+
3
+ class DataFile
4
+
5
+ def self.contents(id)
6
+ return File.read( self.file(id) ) if self.file_exists?(id)
7
+ return File.read( self.yaml_file(id) ) if self.yaml_exists?(id)
8
+ return File.read( self.non_extension_file(id) ) if self.non_extension_file(id)
9
+ return self.sub_yaml(id)
10
+ end
11
+
12
+ def self.write(id, content)
13
+ file = self.file_yaml_or_non_extension_file(id)
14
+ new_file = self.file(id)
15
+
16
+ if not file
17
+ parent = File.expand_path( '..', new_file )
18
+ FileUtils.mkdir_p(parent) unless File.exists?(parent)
19
+ FileUtils.touch(new_file) unless File.exists?(new_file)
20
+ file = new_file
21
+ end
22
+
23
+ File.open( file, 'w') {|f| f.write(content) }
24
+ end
25
+
26
+ def self.exists?(id)
27
+ self.file_exists?(id) or self.yaml_exists?(id)
28
+ end
29
+
30
+ def self.file_exists?(id)
31
+ File.exists?( self.file(id) )
32
+ end
33
+
34
+ def self.yaml_exists?(id)
35
+ File.exists?( self.yaml_file(id) )
36
+ end
37
+
38
+ def self.file_yaml_or_non_extension_file(id)
39
+ return self.file(id) if self.file_exists?(id)
40
+ return self.yaml_file(id) if self.yaml_exists?(id)
41
+ return self.non_extension_file(id) if self.non_extension_file(id)
42
+ nil
43
+ end
44
+
45
+ def self.file(id)
46
+ id = id.split( DELIMITER )
47
+ id = [Cabi.cache_dir] + id
48
+ File.join( *id )
49
+ end
50
+
51
+ def self.yaml_file(id)
52
+ File.join( self.file(id) + YAML_EXT )
53
+ end
54
+
55
+ def self.file_parent(id)
56
+ File.dirname( self.file(id) )
57
+ end
58
+
59
+ def self.non_extension_file(id)
60
+ base = id.split( DELIMITER ).last
61
+
62
+ file = false
63
+ Dir.glob( self.file_parent(id) + '/*' ).each do |f|
64
+ file = File.join(f) if File.basename(f, File.extname(f)) == base
65
+ break if file
66
+ end
67
+
68
+ file
69
+ end
70
+
71
+ def self.sub_yaml(id)
72
+ id = id.split( DELIMITER )
73
+ val = false
74
+ id.each_with_index do |key, index|
75
+ break if val
76
+
77
+ a = [Cabi.cache_dir] + id[0..index]
78
+ a[ a.length - 1 ] = a[a.length - 1 ] + YAML_EXT
79
+ f = File.join( *a )
80
+
81
+ if File.exists? f
82
+ data = YAML.load( File.read(f) )
83
+ val = data.access( id[index+1..-1].join(DELIMITER) )
84
+ end
85
+ end
86
+
87
+ val
88
+ end
89
+
90
+ end
91
+
92
+ end
data/lib/hash.rb ADDED
@@ -0,0 +1,19 @@
1
+
2
+ class Hash
3
+
4
+ def access(path)
5
+ val = false
6
+
7
+ path.split( Cabi::DELIMITER ).each do |p|
8
+ if p.to_i.to_s == p
9
+ val = self[p.to_i]
10
+ else
11
+ val = self[p.to_s] || self[p.to_sym]
12
+ end
13
+ break unless val
14
+ end
15
+
16
+ val
17
+ end
18
+
19
+ end
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cabi
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Brian Gonzalez
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-09-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '0.18'
20
+ - - '>='
21
+ - !ruby/object:Gem::Version
22
+ version: 0.18.1
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '0.18'
30
+ - - '>='
31
+ - !ruby/object:Gem::Version
32
+ version: 0.18.1
33
+ description: Cabi is a flat-file datastore where data is stored by directory stucture
34
+ and accessed by colon-delimited strings.
35
+ email: me@briangonzalez.org
36
+ executables:
37
+ - cabi
38
+ extensions: []
39
+ extra_rdoc_files: []
40
+ files:
41
+ - Rakefile
42
+ - README.md
43
+ - cabi.gemspec
44
+ - bin/cabi
45
+ - lib/cabi.rb
46
+ - lib/cache.rb
47
+ - lib/datafile.rb
48
+ - lib/hash.rb
49
+ - data/cabi-cache.tar.gz
50
+ - data/cabi.svg
51
+ homepage: http://github.com/briangonzalez/cabi-gem
52
+ licenses:
53
+ - MIT
54
+ metadata: {}
55
+ post_install_message:
56
+ rdoc_options: []
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - '>='
62
+ - !ruby/object:Gem::Version
63
+ version: 1.9.3
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ requirements: []
70
+ rubyforge_project:
71
+ rubygems_version: 2.0.3
72
+ signing_key:
73
+ specification_version: 4
74
+ summary: A simple, flat-file datastore for Ruby.
75
+ test_files: []