dyoder-filebase 0.2.2 → 0.3.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.
@@ -0,0 +1,35 @@
1
+ require 'yaml'
2
+ require 'extensions/io'
3
+ class Filebase
4
+
5
+ class YAML
6
+
7
+ def initialize( root )
8
+ @root = root.to_s
9
+ end
10
+
11
+ def path( key )
12
+ File.join( @root, key.to_s ) + '.yml'
13
+ end
14
+
15
+ def all
16
+ Dir[ path('*') ].map { |file| find( File.basename(file,'.yml' ) ) }.compact
17
+ end
18
+
19
+ def find( key )
20
+ obj = ::YAML.load( File.read( path( key ) ) ) rescue nil
21
+ obj['key'] = key if Hash === obj
22
+ obj or nil # convert false to nil
23
+ end
24
+
25
+ def save( key, object )
26
+ File.write( path( key ), object.to_yaml )
27
+ end
28
+
29
+ def delete( key )
30
+ FileUtils.remove( path( key ) )
31
+ end
32
+
33
+ end
34
+
35
+ end
@@ -0,0 +1,48 @@
1
+ module Attributes
2
+
3
+ def initialize(hash = {} )
4
+ attributes = hash
5
+ end
6
+
7
+ def attributes=( hash )
8
+ # copy the hash, converting all keys to strings
9
+ @attrs = hash.inject({}) { |h,p| k,v = p; h[k.to_s] = v; h }
10
+ end
11
+
12
+ def attributes
13
+ @attrs ||= {}
14
+ end
15
+
16
+ def method_missing(name,*args)
17
+ name = name.to_s
18
+ if name =~/=$/ and args.length == 1
19
+ set(name[0..-2], args[0] )
20
+ else
21
+ get(name)
22
+ end
23
+ end
24
+
25
+ def [](name)
26
+ get(name)
27
+ end
28
+
29
+ def []=(name,val)
30
+ set(name,val)
31
+ end
32
+
33
+ def set(name, val)
34
+ attributes[name.to_s] = val
35
+ end
36
+
37
+ def get(name)
38
+ rval = attributes[name.to_s]
39
+ rval.is_a?( Hash ) ? Attributes.new( rval ) : rval
40
+ end
41
+
42
+ def to_h
43
+ @attrs
44
+ end
45
+
46
+ alias_method :to_hash, :to_h
47
+
48
+ end
@@ -0,0 +1,84 @@
1
+ require 'filebase/attributes'
2
+
3
+ class Filebase
4
+
5
+ Error = RuntimeError
6
+
7
+ module Model
8
+
9
+ def self.[]( path )
10
+ Module.new do |mixin|
11
+ ( class << mixin ; self ; end ).module_eval do
12
+ define_method( :included ) do | model |
13
+ model.module_eval do
14
+ @db = Filebase.new( path )
15
+ extend Mixins::ClassMethods ; include Attributes ; include Mixins::InstanceMethods
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ module Mixins
23
+
24
+ module ClassMethods
25
+ attr_accessor :db
26
+ def create( assigns ) ; save( new( assigns ) ) ; end
27
+ def all ; db.all.map { |attrs| new( attrs ) } ; end
28
+ def find( key ) ; attrs = db.find( key ); new( attrs ) if attrs ; end
29
+ def []( key ) ; find( key ) ; 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.gsub(/(_)(\w)/) { $2.upcase }.gsub(/^([a-z])/) { $1.upcase } )
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
+ def eql?(object) ; key == object.key ; end
77
+ def hash ; key.hash ; end
78
+ end
79
+
80
+ end
81
+
82
+ end
83
+
84
+ end
data/lib/filebase.rb ADDED
@@ -0,0 +1,11 @@
1
+ require 'rubygems'
2
+ require 'drivers/yaml'
3
+ class Filebase
4
+ class << self ; attr_accessor :storage ; end
5
+ self.storage = YAML
6
+ def initialize( root = '.', storage = nil )
7
+ @storage = ( storage || Filebase.storage ).new( root )
8
+ end
9
+ # delegate everything to the storage object ...
10
+ def method_missing( name,*args ) ; @storage.send( name, *args ) ; end
11
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dyoder-filebase
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dan Yoder