yaml-model 1.0.1

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.
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ Gemfile.lock
2
+ pkg/*
3
+ *.gem
4
+ .bundle
5
+ vendor/*
6
+ *.swp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in yaml-model.gemspec
4
+ gemspec
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ task :default => :test
5
+
6
+ desc "unit tests"
7
+ task :test do
8
+ exec 'bundle exec rspec test/*.rb'
9
+ end
data/lib/yaml-model.rb ADDED
@@ -0,0 +1,173 @@
1
+ require 'yaml'
2
+ require 'yaml-model/version'
3
+
4
+ class YAML_Model
5
+
6
+ class Error < Exception
7
+ end
8
+
9
+ def self.reset!
10
+ @@database_filename = nil
11
+
12
+ @@database = {
13
+ :next_oid => 1,
14
+ :data => {}
15
+ }
16
+ end
17
+
18
+ reset!
19
+
20
+ attr_reader :id
21
+
22
+ @@volatile = [ :@volatile ]
23
+
24
+ def self.all
25
+ @@database[ :data ][ self.name ] ||= []
26
+ end
27
+
28
+ def assert( assertion, info )
29
+ raise Error.new( info.inspect ) unless assertion
30
+ end
31
+
32
+ def assert_type( variable, types )
33
+ assert( [types].flatten.inject(false){|result,type|result||=(type===variable)}, "Invalid type: `#{variable.class.name}`" )
34
+ end
35
+
36
+ def self.type attribute, types, &block
37
+ define_method attribute do
38
+ instance_eval "@#{attribute}"
39
+ end
40
+ define_method "#{attribute}=".to_sym do |value|
41
+ assert_type value, types
42
+ instance_exec( value, &block ) if block_given?
43
+ instance_eval "@#{attribute} = value"
44
+ end
45
+ end
46
+
47
+ def self.init *attributes, &block
48
+ define_method :initialize do |*args|
49
+ attributes.each do |attribute|
50
+ self.send( "#{attribute}=".to_sym, args.shift )
51
+ end
52
+ self.instance_eval( &block ) if block_given?
53
+ end
54
+ end
55
+
56
+ def self.[]( id )
57
+ all.select{|n|n.id==id}.first
58
+ end
59
+
60
+ def self.load!
61
+ @@database = YAML.load( File.read( @@database_filename.to_s ) ) if File.exists?( @@database_filename.to_s )
62
+ end
63
+
64
+ def self.filename=( filename )
65
+ @@database_filename = filename
66
+ self.load!
67
+ end
68
+
69
+ def self.to_yaml
70
+ @@database.to_yaml
71
+ end
72
+
73
+ def self.save!
74
+ if @@database_filename
75
+ File.open( @@database_filename, 'w' ) do |file|
76
+ file.write( self.to_yaml )
77
+ end
78
+ end
79
+ end
80
+
81
+ def self.each &block
82
+ all.each &block
83
+ end
84
+
85
+ def self.select &block
86
+ all.select &block
87
+ end
88
+
89
+ def self.filter hash
90
+ select do |this|
91
+ hash.keys.inject( true ) do |result,variable|
92
+ this.instance_eval( "@#{variable}" ) == hash[ variable ]
93
+ end
94
+ end
95
+ end
96
+
97
+ def self.volatile variable
98
+ @@volatile << "@#{variable}".to_sym
99
+ end
100
+
101
+ def to_yaml_properties
102
+ instance_variables - @@volatile
103
+ end
104
+
105
+ def self.create( *args )
106
+ this = self.new( *args )
107
+ this.instance_eval do
108
+ @id = @@database[ :next_oid ]
109
+ @id.freeze
110
+ end
111
+ @@database[ :next_oid ] += 1
112
+ @@database[ :data ][ this.class.name ] ||= []
113
+ @@database[ :data ][ this.class.name ] << this
114
+ this
115
+ end
116
+
117
+ def delete
118
+ @@database[ :data ][ self.class.name ].delete( self )
119
+ end
120
+
121
+ def self.sort_by( *attributes )
122
+ define_method '<=>'.to_sym do |other|
123
+ attributes.map{|a|self.send(a)} <=> attributes.map{|a|other.send(a)}
124
+ end
125
+ end
126
+
127
+ sort_by :id
128
+
129
+ def self.has( that_attribute_plural, that_class, many_to_many = false )
130
+ if many_to_many
131
+ this_class = self
132
+ this_class_name, that_class_name = [this_class,that_class].map{|n|n.name.split(':')[-1]}
133
+ this_attribute_singular = this_class_name.downcase.to_sym
134
+ that_attribute_singular = that_class_name.downcase.to_sym
135
+ via_class_name = [ this_class_name, that_class_name ].sort.map{|n|n.capitalize}.join('')
136
+ via_class = eval( "#{via_class_name}||=Class.new(YAML_Model)" )
137
+ via_attribute_plural = ( via_class_name.downcase + "s" ).to_sym
138
+
139
+ if via_class.instance_variables.empty?
140
+ via_class.type this_attribute_singular, this_class
141
+ via_class.type that_attribute_singular, that_class
142
+ end
143
+
144
+ this_class.has via_attribute_plural, via_class
145
+
146
+ define_method that_attribute_plural do
147
+ send( via_attribute_plural ).map do |via_instance|
148
+ via_instance.send( that_attribute_singular )
149
+ end
150
+ end
151
+
152
+ define_method "add_#{that_attribute_singular}".to_sym do |that_instance|
153
+ via_instance = via_class.create
154
+ via_instance.send( "#{this_attribute_singular}=".to_sym, self )
155
+ via_instance.send( "#{that_attribute_singular}=".to_sym, that_instance )
156
+ end
157
+
158
+ else
159
+
160
+ define_method that_attribute_plural do
161
+ that_class.select do |that_instance|
162
+ that_instance.instance_variables.inject( false ) do |result,variable|
163
+ result ||= that_instance.instance_eval(variable.to_s).class == self.class && that_instance.instance_eval(variable.to_s).id == self.id
164
+ end
165
+ end
166
+ end
167
+
168
+ end
169
+ end
170
+
171
+ at_exit { self.save! }
172
+
173
+ end
@@ -0,0 +1,3 @@
1
+ class YAML_Model
2
+ VERSION = "1.0.1"
3
+ end
data/test/has.rb ADDED
@@ -0,0 +1,77 @@
1
+ require 'yaml-model'
2
+
3
+ describe YAML_Model, "::has" do
4
+
5
+ before( :each ) do
6
+ YAML_Model.reset!
7
+ end
8
+
9
+ it "creates a method of the correct attribute name" do
10
+ User = Class.new( YAML_Model )
11
+ class User < YAML_Model
12
+ has :posts, Class.new( YAML_Model )
13
+ end
14
+ User.instance_methods.index( :posts ).should_not == nil
15
+ end
16
+
17
+ it "correctly references items that belong to it" do
18
+ User = Class.new( YAML_Model )
19
+ Post = Class.new( YAML_Model )
20
+ class Post < YAML_Model
21
+ type :user, User
22
+ init :user
23
+ end
24
+ class User < YAML_Model
25
+ has :posts, Post
26
+ end
27
+
28
+ user_a = User.create
29
+ user_b = User.create
30
+ user_c = User.create
31
+ post_a = Post.create( user_a )
32
+ post_b = Post.create( user_a )
33
+ post_c = Post.create( user_c )
34
+
35
+ user_a.posts.should == [ post_a, post_b ]
36
+ user_b.posts.should == []
37
+ user_c.posts.should == [ post_c ]
38
+ end
39
+
40
+ it "adds an add_ method when the relationship is many_to_many" do
41
+ Tag = Class.new( YAML_Model )
42
+ Post = Class.new( YAML_Model )
43
+ class Post < YAML_Model
44
+ has :tags, Tag, :many_to_many
45
+ end
46
+ Post.instance_methods.index( :add_tag ).should_not == nil
47
+ Tag.instance_methods.index( :add_post ).should == nil
48
+ end
49
+
50
+ it "handles many to many relationships seamlessly" do
51
+ Tag = Class.new( YAML_Model )
52
+ Post = Class.new( YAML_Model )
53
+ Post.has :tags, Tag, :many_to_many
54
+ Tag.has :posts, Post, :many_to_many
55
+
56
+ post_a = Post.create
57
+ post_b = Post.create
58
+ post_c = Post.create
59
+
60
+ tag_a = Tag.create
61
+ tag_b = Tag.create
62
+ tag_c = Tag.create
63
+
64
+ post_a.add_tag( tag_a )
65
+ post_a.add_tag( tag_b )
66
+ tag_b.add_post( post_c )
67
+
68
+ post_a.tags.sort.should == [ tag_a, tag_b ].sort
69
+ post_b.tags.should == []
70
+ post_c.tags.should == [ tag_b ]
71
+
72
+ tag_a.posts.should == [ post_a ]
73
+ tag_b.posts.sort.should == [ post_a, post_c ].sort
74
+ tag_c.posts.should == []
75
+ end
76
+
77
+ end
data/test/init.rb ADDED
@@ -0,0 +1,34 @@
1
+ require 'yaml-model'
2
+
3
+ describe YAML_Model, "::init" do
4
+
5
+ before( :each ) do
6
+ YAML_Model.reset!
7
+ end
8
+
9
+ it "runs the block it's given" do
10
+ $ran_it = false
11
+ Test = Class.new( YAML_Model )
12
+ class Test < YAML_Model
13
+ init do
14
+ $ran_it = true
15
+ end
16
+ end
17
+ $ran_it.should == false
18
+ Test.create
19
+ $ran_it.should == true
20
+ end
21
+
22
+ it "can set instance varibles inside blocks it's given" do
23
+ Test = Class.new( YAML_Model )
24
+ class Test < YAML_Model
25
+ type :name, String
26
+ init :name do
27
+ @name = "Bar"
28
+ end
29
+ end
30
+ test = Test.create( "Foo" )
31
+ test.name.should == "Bar"
32
+ end
33
+
34
+ end
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "yaml-model/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "yaml-model"
7
+ s.version = YAML_Model::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Clive Crous"]
10
+ s.email = ["clive@crous.co.za"]
11
+ s.homepage = "http://www.darkarts.co.za/yaml-model"
12
+ s.summary = %q{A NoSQL data model with data stored as YAML}
13
+ s.description = %q{A NoSQL data model with data stored as YAML}
14
+
15
+ s.add_development_dependency "bundler", ">= 1.0.0"
16
+ s.add_development_dependency "rspec", ">= 1.3.0"
17
+ s.add_development_dependency "rake", ">= 0.8.7"
18
+
19
+ s.files = `git ls-files`.split("\n")
20
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
21
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
22
+ s.require_paths = ["lib"]
23
+ end
metadata ADDED
@@ -0,0 +1,118 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: yaml-model
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 1
7
+ - 0
8
+ - 1
9
+ version: 1.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Clive Crous
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-01-27 00:00:00 +02:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: bundler
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 1
29
+ - 0
30
+ - 0
31
+ version: 1.0.0
32
+ type: :development
33
+ prerelease: false
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: rspec
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ segments:
43
+ - 1
44
+ - 3
45
+ - 0
46
+ version: 1.3.0
47
+ type: :development
48
+ prerelease: false
49
+ version_requirements: *id002
50
+ - !ruby/object:Gem::Dependency
51
+ name: rake
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ segments:
58
+ - 0
59
+ - 8
60
+ - 7
61
+ version: 0.8.7
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: *id003
65
+ description: A NoSQL data model with data stored as YAML
66
+ email:
67
+ - clive@crous.co.za
68
+ executables: []
69
+
70
+ extensions: []
71
+
72
+ extra_rdoc_files: []
73
+
74
+ files:
75
+ - .gitignore
76
+ - Gemfile
77
+ - Rakefile
78
+ - lib/yaml-model.rb
79
+ - lib/yaml-model/version.rb
80
+ - test/has.rb
81
+ - test/init.rb
82
+ - yaml-model.gemspec
83
+ has_rdoc: true
84
+ homepage: http://www.darkarts.co.za/yaml-model
85
+ licenses: []
86
+
87
+ post_install_message:
88
+ rdoc_options: []
89
+
90
+ require_paths:
91
+ - lib
92
+ required_ruby_version: !ruby/object:Gem::Requirement
93
+ none: false
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ hash: -961508909
98
+ segments:
99
+ - 0
100
+ version: "0"
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ none: false
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ hash: -961508909
107
+ segments:
108
+ - 0
109
+ version: "0"
110
+ requirements: []
111
+
112
+ rubyforge_project:
113
+ rubygems_version: 1.3.7
114
+ signing_key:
115
+ specification_version: 3
116
+ summary: A NoSQL data model with data stored as YAML
117
+ test_files: []
118
+