dyoder-filebase 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/attributes.rb ADDED
@@ -0,0 +1,46 @@
1
+ module Attributes
2
+
3
+ def initialize(hash={})
4
+ # copy the hash, converting all keys to strings
5
+ @attrs = hash.inject({}) { |h,p| k,v = p; h[k.to_s] = v; h }
6
+ end
7
+
8
+ def method_missing(name,*args)
9
+ name = name.to_s
10
+ if name =~/=$/ and args.length == 1
11
+ set(name[0..-2], args[0] )
12
+ else
13
+ get(name)
14
+ end
15
+ end
16
+
17
+ def [](name)
18
+ get(name)
19
+ end
20
+
21
+ def []=(name,val)
22
+ set(name,val)
23
+ end
24
+
25
+ def set(name, val)
26
+ @attrs[name.to_s] = val
27
+ end
28
+
29
+ def get(name)
30
+ rval = ( @attrs[name.to_s] )
31
+ if Hash === rval
32
+ Dynamo.new(rval)
33
+ else
34
+ rval
35
+ end
36
+ end
37
+
38
+ def to_h
39
+ @attrs
40
+ end
41
+
42
+ alias_method :to_hash, :to_h
43
+
44
+ end
45
+
46
+
data/lib/filebase.rb ADDED
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require 'lib/yaml'
3
+ require 'lib/symbol'
4
+ require 'lib/string'
5
+ class Filebase
6
+ class << self ; attr_accessor :storage ; end
7
+ self.storage = YAML
8
+ def initialize( root = '.', storage = nil )
9
+ @storage = ( storage || Filebase.storage ).new( root )
10
+ end
11
+ # delegate everything to the storage object ...
12
+ def method_missing( name,*args ) ; @storage.send( name, *args ) ; end
13
+ end
data/lib/model.rb ADDED
@@ -0,0 +1,82 @@
1
+ require 'lib/filebase'
2
+ require 'lib/attributes'
3
+
4
+ class Filebase
5
+
6
+ Error = RuntimeError
7
+
8
+ module Model
9
+
10
+ def self.[]( path )
11
+ Module.new do |mixin|
12
+ ( class << mixin ; self ; end ).module_eval do
13
+ define_method( :included ) do | model |
14
+ model.module_eval do
15
+ @db = Filebase.new( path )
16
+ extend Mixins::ClassMethods ; include Attributes ; include Mixins::InstanceMethods
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ module Mixins
24
+
25
+ module ClassMethods
26
+ attr_accessor :db
27
+ def create( assigns ) ; save( new( assigns ) ) ; end
28
+ def all ; db.all.map { |attrs| new( attrs ) } ; end
29
+ def find( key ) ; attrs = db.find( key ); new( attrs.merge( :key => key ) ) if attrs ; end
30
+ def save( object )
31
+ raise( Filebase::Error.new, 'attempted to save an object with nil key' ) if object.key.nil? or object.key.empty?
32
+ db.save( object.key, object.to_h )
33
+ end
34
+ def delete( object )
35
+ raise( Filebase::Error.new, 'attempted to delete an object with nil key' ) if object.key.nil? or object.key.empty?
36
+ db.delete( object.key )
37
+ end
38
+ def has_one( name, options = {} )
39
+ module_eval do
40
+ define_method name do
41
+ @has_one ||= {}
42
+ options[:class] ||= Object.module_eval( name.to_s.camel_case )
43
+ @has_one[name] ||= options[:class].find( get( name ) )
44
+ end
45
+ define_method( name.to_s + '=' ) do | val |
46
+ @has_one ||= {}; @has_one[name] = nil
47
+ set( name, String === val ? val : val.key )
48
+ end
49
+ end
50
+ end
51
+ def has_many( name, options = {} )
52
+ module_eval do
53
+ define_method( name ) do
54
+ @has_many ||= {}
55
+ options[:class] ||= Object.module_eval( name.to_s.camel_case )
56
+ @has_many[name] ||= ( get( name ) || [] ).uniq.map { |key| options[:class].find( key ) }
57
+ end
58
+ # when we save, make sure to pick up any changes to the array
59
+ (class<<self;self;end).module_eval do
60
+ old_save = instance_method(:save)
61
+ define_method :save do |object|
62
+ object.set( name, object.send( name ).map{ |x| x.key }.uniq )
63
+ old_save.bind(self).call(object)
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+
70
+ module InstanceMethods
71
+ def initialize( assigns ) ; super ; assign( assigns ) ; end
72
+ def assign( assigns ) ; assigns.each { |k,v| self.send( "#{k}=", v ) }; self ; end
73
+ def save ; self.class.save( self ) ; self; end
74
+ def delete ; self.class.delete( self ) ; self ; end
75
+ def ==(object) ; key == object.key ; end
76
+ end
77
+
78
+ end
79
+
80
+ end
81
+
82
+ end
data/lib/string.rb ADDED
@@ -0,0 +1,47 @@
1
+ # Waves extends String with a variety of methods for changing from singular to plural and back, and switching to different types of case and word separators. These methods are similar to those found in Rails and other frameworks, but some (all?) of the names are different. The names here were chosen for increased clarity and are hopefully easy to adjust to ...
2
+
3
+ class String
4
+
5
+ # Does a File.join on the two arguments joined by the /. Very handy
6
+ # for doing platform-safe paths without having to use File.join.
7
+ #
8
+ # I unfortunately don't recall where i first saw this ... see
9
+ # Symbol extension as well, allowing for :files / 'afilename.txt'
10
+
11
+ def / ( string )
12
+ File.join(self,string.to_s)
13
+ end
14
+
15
+ def singular
16
+ Inflect::English.singular(self)
17
+ end
18
+
19
+ alias_method(:singularize, :singular)
20
+
21
+ def plural
22
+ Inflect::English.plural(self)
23
+ end
24
+
25
+ alias_method(:pluralize, :plural)
26
+
27
+ def lower_camel_case
28
+ gsub(/(_)(\w)/) { $2.upcase }
29
+ end
30
+
31
+ def camel_case
32
+ lower_camel_case.gsub(/^([a-z])/) { $1.upcase }
33
+ end
34
+
35
+ def snake_case
36
+ gsub(/([a-z\d])([A-Z])/){ "#{$1}_#{$2}"}.tr("-", "_").downcase
37
+ end
38
+
39
+ def title_case
40
+ gsub(/(^|\s)\s*([a-z])/) { $1 + $2.upcase }
41
+ end
42
+
43
+ def text
44
+ gsub(/[\_\-\.\:]/,' ')
45
+ end
46
+
47
+ end
data/lib/symbol.rb ADDED
@@ -0,0 +1,7 @@
1
+ class Symbol
2
+ # Does File.join on self and string, converting self to string before invocation.
3
+ # See String#/ for more.
4
+ def / ( string )
5
+ self.to_s / string
6
+ end
7
+ end
data/lib/yaml.rb ADDED
@@ -0,0 +1,33 @@
1
+ require 'yaml'
2
+ require 'extensions/io'
3
+ class Filebase
4
+
5
+ class YAML
6
+
7
+ def initialize( root )
8
+ @root = root
9
+ end
10
+
11
+ def path( key )
12
+ @root / key + '.yml'
13
+ end
14
+
15
+ def all
16
+ Dir[ path('*') ].map { |file| YAML.load( File.read( file ) ) }
17
+ end
18
+
19
+ def find( key )
20
+ ( ::YAML.load( File.read( path( key ) ) ) if File.exists?( path( key ) ) ) || nil
21
+ end
22
+
23
+ def save( key, object )
24
+ File.write( path( key ), object.to_yaml )
25
+ end
26
+
27
+ def delete( key )
28
+ FileUtils.remove( path( key ) )
29
+ end
30
+
31
+ end
32
+
33
+ end
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dyoder-filebase
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Dan Yoder, Matthew King, Lawrence Pit
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-04-30 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: extensions
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: "0"
23
+ version:
24
+ description:
25
+ email: dan@zeraweb.com
26
+ executables: []
27
+
28
+ extensions: []
29
+
30
+ extra_rdoc_files: []
31
+
32
+ files:
33
+ - lib/attributes.rb
34
+ - lib/filebase.rb
35
+ - lib/model.rb
36
+ - lib/string.rb
37
+ - lib/symbol.rb
38
+ - lib/yaml.rb
39
+ has_rdoc: true
40
+ homepage: http://dev.zeraweb.com/waves
41
+ post_install_message:
42
+ rdoc_options: []
43
+
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: 1.8.6
51
+ version:
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ version:
58
+ requirements: []
59
+
60
+ rubyforge_project:
61
+ rubygems_version: 1.0.1
62
+ signing_key:
63
+ specification_version: 2
64
+ summary: Simple file-based database with model support.
65
+ test_files: []
66
+