og 0.10.0 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS +4 -1
- data/ChangeLog +290 -7
- data/README.og +3 -4
- data/RELEASES.og +50 -0
- data/Rakefile +7 -7
- data/examples/og/run.rb +1 -1
- data/lib/glue/array.rb +14 -33
- data/lib/glue/hash.rb +32 -53
- data/lib/glue/pool.rb +9 -12
- data/lib/glue/property.rb +31 -9
- data/lib/og.rb +20 -12
- data/lib/og/adapter.rb +40 -13
- data/lib/og/adapters/filesys.rb +121 -0
- data/lib/og/adapters/mysql.rb +10 -5
- data/lib/og/adapters/oracle.rb +374 -0
- data/lib/og/adapters/psql.rb +10 -23
- data/lib/og/adapters/sqlite.rb +3 -3
- data/lib/og/backend.rb +2 -2
- data/lib/og/connection.rb +6 -6
- data/lib/og/database.rb +5 -5
- data/lib/og/enchant.rb +6 -2
- data/lib/og/meta.rb +56 -26
- data/lib/og/mock.rb +1 -1
- data/lib/og/typemacros.rb +23 -0
- data/test/og/tc_filesys.rb +83 -0
- data/test/og/tc_meta.rb +55 -0
- data/test/tc_og.rb +115 -36
- metadata +8 -4
- data/ChangeLog.1 +0 -2344
data/Rakefile
CHANGED
@@ -6,7 +6,7 @@ require 'rake/rdoctask'
|
|
6
6
|
require 'rake/testtask'
|
7
7
|
require 'rake/gempackagetask'
|
8
8
|
|
9
|
-
og = true
|
9
|
+
og = true
|
10
10
|
|
11
11
|
task :default => :package
|
12
12
|
|
@@ -14,7 +14,7 @@ task :default => :package
|
|
14
14
|
|
15
15
|
Rake::TestTask.new do |t|
|
16
16
|
t.libs << 'test'
|
17
|
-
t.test_files = FileList['test/**/tc*.rb'].exclude('**/tc*og*.rb')
|
17
|
+
t.test_files = FileList['test/**/tc*.rb'].exclude('**/tc*og*.rb').exclude('test/og/**/*')
|
18
18
|
t.verbose = true
|
19
19
|
end
|
20
20
|
|
@@ -30,8 +30,8 @@ end
|
|
30
30
|
|
31
31
|
Rake::RDocTask.new do |rd|
|
32
32
|
rd.main = 'README'
|
33
|
-
rd.rdoc_dir = 'rdoc'
|
34
|
-
rd.rdoc_files.include('README', 'INSTALL', 'lib/**/*.rb')
|
33
|
+
rd.rdoc_dir = 'doc/rdoc'
|
34
|
+
rd.rdoc_files.include('README', 'INSTALL', 'doc/og_config.txt', 'doc/og_tutorial.txt', 'lib/**/*.rb')
|
35
35
|
rd.options << '--all --inline-source'
|
36
36
|
end
|
37
37
|
|
@@ -91,11 +91,11 @@ spec = Gem::Specification.new do |s|
|
|
91
91
|
s.summary = 'Nitro Web Engine'
|
92
92
|
s.description =
|
93
93
|
'An efficient, multiparadigm and flexible platform for rapid ' +
|
94
|
-
'web application development. Implements a full development stack
|
95
|
-
|
96
|
-
|
94
|
+
'web application development. Implements a full development stack.'
|
95
|
+
|
97
96
|
# s.add_dependency 'postgres-pr', '>= 0.3.0'
|
98
97
|
# s.add_dependency 'postgres', '>= 0.7.1'
|
98
|
+
# s.add_dependency 'ParseTree', '>= 1.3.3'
|
99
99
|
s.add_dependency 'extensions', '>= 0.5'
|
100
100
|
# s.add_dependency 'sqlite3-ruby', '>= 1.0.0'
|
101
101
|
# s.add_dependency 'mysql', '>= 2.5.1'
|
data/examples/og/run.rb
CHANGED
data/lib/glue/array.rb
CHANGED
@@ -1,15 +1,14 @@
|
|
1
1
|
# * George Moschovitis <gm@navel.gr>
|
2
2
|
# (c) 2002-2005 Navel, all rights reserved.
|
3
|
-
# $Id: array.rb
|
3
|
+
# $Id: array.rb 266 2005-02-28 14:50:48Z gmosx $
|
4
4
|
|
5
5
|
require 'sync'
|
6
6
|
|
7
7
|
module N
|
8
8
|
|
9
|
-
# A thread-safe array. We use a sync object instead of a
|
10
|
-
# because it is re-entrant.
|
11
|
-
#
|
12
|
-
# when reading
|
9
|
+
# A thread-safe array. We use a sync object instead of a
|
10
|
+
# mutex, because it is re-entrant. An exclusive lock is
|
11
|
+
# needed when writing, a shared lock IS NEEDED when reading.
|
13
12
|
|
14
13
|
class SafeArray < Array
|
15
14
|
|
@@ -18,61 +17,43 @@ class SafeArray < Array
|
|
18
17
|
# gmosx: delegator is not used.
|
19
18
|
|
20
19
|
def initialize(delegator = nil)
|
21
|
-
@sync =
|
20
|
+
@sync = Sync.new()
|
22
21
|
end
|
23
22
|
|
24
23
|
def << (value)
|
25
|
-
return @sync.synchronize(
|
26
|
-
super
|
27
|
-
}
|
24
|
+
return @sync.synchronize(Sync::SH) { super }
|
28
25
|
end
|
29
26
|
|
30
27
|
def delete_if(&block)
|
31
|
-
return @sync.synchronize(
|
32
|
-
super
|
33
|
-
}
|
28
|
+
return @sync.synchronize(Sync::SH) { super }
|
34
29
|
end
|
35
30
|
|
36
31
|
def [](key)
|
37
|
-
return @sync.synchronize(
|
38
|
-
super
|
39
|
-
}
|
32
|
+
return @sync.synchronize(Sync::SH) { super }
|
40
33
|
end
|
41
34
|
|
42
35
|
def []=(key, value)
|
43
|
-
return @sync.synchronize(
|
44
|
-
super
|
45
|
-
}
|
36
|
+
return @sync.synchronize(Sync::EX) { super }
|
46
37
|
end
|
47
38
|
|
48
39
|
def delete(key)
|
49
|
-
return @sync.synchronize(
|
50
|
-
super
|
51
|
-
}
|
40
|
+
return @sync.synchronize(Sync::EX) { super }
|
52
41
|
end
|
53
42
|
|
54
43
|
def clear
|
55
|
-
@sync.synchronize(
|
56
|
-
super
|
57
|
-
}
|
44
|
+
@sync.synchronize(Sync::EX) { super }
|
58
45
|
end
|
59
46
|
|
60
47
|
def size
|
61
|
-
return @sync.synchronize(
|
62
|
-
super
|
63
|
-
}
|
48
|
+
return @sync.synchronize(Sync::SH) { super }
|
64
49
|
end
|
65
50
|
|
66
51
|
def shift
|
67
|
-
return @sync.synchronize(::Sync::EX) {
|
68
|
-
super
|
69
|
-
}
|
52
|
+
return @sync.synchronize(::Sync::EX) { super }
|
70
53
|
end
|
71
54
|
|
72
55
|
def unshift(el)
|
73
|
-
return @sync.synchronize(::Sync::EX) {
|
74
|
-
super
|
75
|
-
}
|
56
|
+
return @sync.synchronize(::Sync::EX) { super }
|
76
57
|
end
|
77
58
|
|
78
59
|
end
|
data/lib/glue/hash.rb
CHANGED
@@ -1,22 +1,17 @@
|
|
1
|
-
# code:
|
2
1
|
# * George Moschovitis <gm@navel.gr>
|
3
|
-
#
|
4
|
-
#
|
5
|
-
# $Id: hash.rb 202 2005-01-17 10:44:13Z gmosx $
|
2
|
+
# (c) 2004-2005 Navel, all rights reserved.
|
3
|
+
# $Id: hash.rb 263 2005-02-23 13:45:08Z gmosx $
|
6
4
|
|
7
|
-
require
|
5
|
+
require 'sync'
|
8
6
|
|
9
|
-
module N
|
7
|
+
module N
|
10
8
|
|
11
|
-
# == SafeHash
|
12
|
-
#
|
13
9
|
# A thread-safe hash. We use a sync object instead of a mutex,
|
14
|
-
# because it is re-entrant.
|
15
|
-
#
|
16
|
-
# when reading
|
10
|
+
# because it is re-entrant. An exclusive lock is needed when
|
11
|
+
# writing, a shared lock IS NEEDED when reading
|
17
12
|
# uses the delegator pattern to allow for multiple
|
18
13
|
# implementations!
|
19
|
-
|
14
|
+
|
20
15
|
class SafeHash < Hash
|
21
16
|
attr :sync
|
22
17
|
|
@@ -27,63 +22,47 @@ class SafeHash < Hash
|
|
27
22
|
end
|
28
23
|
|
29
24
|
def [](key)
|
30
|
-
|
31
|
-
super
|
32
|
-
}
|
25
|
+
@sync.synchronize(::Sync::SH) { super }
|
33
26
|
end
|
34
27
|
|
35
28
|
def []=(key, value)
|
36
|
-
|
37
|
-
super
|
38
|
-
}
|
29
|
+
@sync.synchronize(::Sync::EX) { super }
|
39
30
|
end
|
40
31
|
|
41
32
|
def delete(key)
|
42
|
-
|
43
|
-
super
|
44
|
-
}
|
33
|
+
@sync.synchronize(::Sync::EX) { super }
|
45
34
|
end
|
46
35
|
|
47
36
|
def clear
|
48
|
-
@sync.synchronize(::Sync::EX) {
|
49
|
-
super
|
50
|
-
}
|
37
|
+
@sync.synchronize(::Sync::EX) { super }
|
51
38
|
end
|
52
39
|
|
53
40
|
def size
|
54
|
-
|
55
|
-
super
|
56
|
-
}
|
41
|
+
@sync.synchronize(::Sync::SH) { super }
|
57
42
|
end
|
58
43
|
|
59
44
|
def values
|
60
|
-
|
61
|
-
super
|
62
|
-
}
|
45
|
+
@sync.synchronize(::Sync::SH) { super }
|
63
46
|
end
|
64
47
|
|
65
48
|
def keys
|
66
|
-
|
67
|
-
super
|
68
|
-
}
|
49
|
+
@sync.synchronize(::Sync::SH) { super }
|
69
50
|
end
|
70
51
|
|
71
|
-
end
|
52
|
+
end
|
72
53
|
|
73
|
-
# == SafeHashDelegator
|
74
|
-
#
|
75
54
|
# A thread-safe hash. We use a sync object instead of a mutex,
|
76
|
-
# because it is re-entrant.
|
77
|
-
#
|
78
|
-
#
|
55
|
+
# because it is re-entrant. An exclusive lock is needed when
|
56
|
+
# writing, a shared lock IS NEEDED when reading.
|
57
|
+
#
|
58
|
+
# === Design
|
79
59
|
#
|
80
|
-
# Design:
|
81
60
|
# This class uses the delegator pattern. However we dont use rubys
|
82
61
|
# delegation facilities, they are more general and powerfull than we
|
83
62
|
# need here (and slower). Instead a custom (but simple) solution is
|
84
63
|
# used.
|
85
64
|
#
|
86
|
-
# Example
|
65
|
+
# === Example
|
87
66
|
#
|
88
67
|
# hash = SafeHashDelegator.new(Hash.new)
|
89
68
|
# hash = SafeHashDelegator.new(Hash.new)
|
@@ -96,20 +75,20 @@ class SafeHashDelegator < Hash
|
|
96
75
|
@sync = ::Sync.new
|
97
76
|
end
|
98
77
|
|
99
|
-
|
100
|
-
|
78
|
+
def [](key)
|
79
|
+
@sync.synchronize(::Sync::SH) {
|
101
80
|
@delegate[key]
|
102
81
|
}
|
103
|
-
|
82
|
+
end
|
104
83
|
|
105
|
-
|
106
|
-
|
84
|
+
def []=(key, value)
|
85
|
+
@sync.synchronize(::Sync::EX) {
|
107
86
|
@delegate[key] = value
|
108
87
|
}
|
109
|
-
|
88
|
+
end
|
110
89
|
|
111
90
|
def delete(key)
|
112
|
-
|
91
|
+
@sync.synchronize(::Sync::EX) {
|
113
92
|
@delegate.delete(key)
|
114
93
|
}
|
115
94
|
end
|
@@ -121,23 +100,23 @@ class SafeHashDelegator < Hash
|
|
121
100
|
end
|
122
101
|
|
123
102
|
def size
|
124
|
-
|
103
|
+
@sync.synchronize(::Sync::SH) {
|
125
104
|
@delegate.size()
|
126
105
|
}
|
127
106
|
end
|
128
107
|
|
129
108
|
def values
|
130
|
-
|
109
|
+
@sync.synchronize(::Sync::SH) {
|
131
110
|
@delegate.values()
|
132
111
|
}
|
133
112
|
end
|
134
113
|
|
135
114
|
def keys
|
136
|
-
|
115
|
+
@sync.synchronize(::Sync::SH) {
|
137
116
|
@delegate.keys()
|
138
117
|
}
|
139
118
|
end
|
140
119
|
|
141
|
-
end
|
120
|
+
end
|
142
121
|
|
143
|
-
end
|
122
|
+
end
|
data/lib/glue/pool.rb
CHANGED
@@ -1,21 +1,17 @@
|
|
1
|
-
# code:
|
2
1
|
# * George Moschovitis <gm@navel.gr>
|
3
|
-
#
|
4
|
-
#
|
5
|
-
# $Id: pool.rb 202 2005-01-17 10:44:13Z gmosx $
|
2
|
+
# (c) 2004-2005 Navel, all rights reserved.
|
3
|
+
# $Id: pool.rb 266 2005-02-28 14:50:48Z gmosx $
|
6
4
|
|
7
|
-
require
|
8
|
-
require
|
5
|
+
require 'thread'
|
6
|
+
require 'monitor'
|
9
7
|
|
10
8
|
module N
|
11
9
|
|
12
|
-
# = Pool
|
13
|
-
#
|
14
10
|
# Generalized object pool implementation. Implemented as a thread
|
15
11
|
# safe stack. Exclusive locking is needed both for push and pop.
|
16
12
|
#
|
17
13
|
# INVESTIGATE: Could use the SizedQueue/Queue.
|
18
|
-
|
14
|
+
|
19
15
|
class Pool < Array
|
20
16
|
include MonitorMixin
|
21
17
|
|
@@ -25,7 +21,7 @@ class Pool < Array
|
|
25
21
|
end
|
26
22
|
|
27
23
|
# Add, restore an object to the pool.
|
28
|
-
|
24
|
+
|
29
25
|
def push(obj)
|
30
26
|
synchronize do
|
31
27
|
super
|
@@ -34,7 +30,7 @@ class Pool < Array
|
|
34
30
|
end
|
35
31
|
|
36
32
|
# Obtain an object from the pool.
|
37
|
-
|
33
|
+
|
38
34
|
def pop
|
39
35
|
synchronize do
|
40
36
|
@cv.wait_while { empty? }
|
@@ -44,6 +40,7 @@ class Pool < Array
|
|
44
40
|
|
45
41
|
# Obtains an object, passes it to a block for processing
|
46
42
|
# and restores it to the pool.
|
43
|
+
|
47
44
|
def obtain
|
48
45
|
result = nil
|
49
46
|
|
@@ -60,4 +57,4 @@ class Pool < Array
|
|
60
57
|
|
61
58
|
end
|
62
59
|
|
63
|
-
end
|
60
|
+
end
|
data/lib/glue/property.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# * George Moschovitis <gm@navel.gr>
|
2
2
|
# * Michael Neumann <mneumann@ntecs.de>
|
3
3
|
# (c) 2004-2005 Navel, all rights reserved.
|
4
|
-
# $Id: property.rb
|
4
|
+
# $Id: property.rb 266 2005-02-28 14:50:48Z gmosx $
|
5
5
|
|
6
6
|
require 'glue/attribute'
|
7
7
|
require 'glue/array'
|
@@ -30,22 +30,35 @@ class Property
|
|
30
30
|
|
31
31
|
cattr_accessor :type_checking, false
|
32
32
|
|
33
|
-
#
|
33
|
+
# The symbol of the property.
|
34
34
|
|
35
35
|
attr_accessor :symbol
|
36
36
|
|
37
|
-
#
|
37
|
+
# The string representation of the symbol.
|
38
38
|
|
39
39
|
attr_accessor :name
|
40
40
|
|
41
|
-
#
|
41
|
+
# The class of the property.
|
42
42
|
|
43
43
|
attr_accessor :klass
|
44
|
-
|
45
|
-
#
|
44
|
+
|
45
|
+
# Additional metadata (like sql declaration, sql index, etc)
|
46
|
+
# Here is a list of predefined metadata:
|
47
|
+
#
|
48
|
+
# [+:reader+]
|
49
|
+
# create reader?
|
50
|
+
#
|
51
|
+
# [+:writer+]
|
52
|
+
# create writer?
|
53
|
+
#
|
54
|
+
# [+:sql_index+]
|
55
|
+
# create an sql index for the column this poperty maps to?
|
56
|
+
#
|
57
|
+
# You can use this mechanism to add your own, custom,
|
58
|
+
# metadata.
|
46
59
|
|
47
60
|
attr_accessor :meta
|
48
|
-
|
61
|
+
|
49
62
|
def initialize(symbol, klass, meta = {})
|
50
63
|
@symbol, @klass = symbol, klass
|
51
64
|
@meta = meta
|
@@ -124,6 +137,11 @@ module PropertyUtils
|
|
124
137
|
else
|
125
138
|
target.__props << prop
|
126
139
|
end
|
140
|
+
|
141
|
+
# Store the property in the :props_and_relations
|
142
|
+
# metadata array.
|
143
|
+
|
144
|
+
target.meta :props_and_relations, prop
|
127
145
|
|
128
146
|
# Precompile the property read/write methods
|
129
147
|
|
@@ -366,7 +384,7 @@ class Module
|
|
366
384
|
prop(klass, symbol, meta)
|
367
385
|
end
|
368
386
|
end
|
369
|
-
|
387
|
+
alias_method :property, :prop_accessor
|
370
388
|
|
371
389
|
# Attach metadata.
|
372
390
|
# Guard against duplicates, no need to keep order.
|
@@ -375,7 +393,11 @@ class Module
|
|
375
393
|
# gmosx: crappy implementation, recode.
|
376
394
|
#++
|
377
395
|
|
378
|
-
def meta(key, val)
|
396
|
+
def meta(key, *val)
|
397
|
+
val = val.first if val.size == 1
|
398
|
+
|
399
|
+
N::PropertyUtils.enchant(self)
|
400
|
+
|
379
401
|
self.module_eval %{
|
380
402
|
@@__meta[key] ||= []
|
381
403
|
@@__meta[key].delete_if { |v| val == v }
|
data/lib/og.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# * George Moschovitis <gm@navel.gr>
|
2
2
|
# (c) 2004-2005 Navel, all rights reserved.
|
3
|
-
# $Id: og.rb
|
3
|
+
# $Id: og.rb 266 2005-02-28 14:50:48Z gmosx $
|
4
4
|
|
5
5
|
require 'glue'
|
6
6
|
require 'glue/logger'
|
@@ -89,7 +89,7 @@ require 'glue/validation'
|
|
89
89
|
# * Deserialize to OpenStruct.
|
90
90
|
# * Better documentation.
|
91
91
|
|
92
|
-
|
92
|
+
module Og
|
93
93
|
|
94
94
|
# The name.
|
95
95
|
|
@@ -97,7 +97,7 @@ class Og
|
|
97
97
|
|
98
98
|
# The version.
|
99
99
|
|
100
|
-
Version = '0.
|
100
|
+
Version = '0.11.0'
|
101
101
|
|
102
102
|
# Library path.
|
103
103
|
|
@@ -106,37 +106,45 @@ class Og
|
|
106
106
|
# If true, only allow reading from the database. Usefull
|
107
107
|
# for maintainance.
|
108
108
|
|
109
|
-
|
109
|
+
mattr_accessor :read_only_mode, false
|
110
110
|
|
111
111
|
# If true, the library automatically 'enchants' managed classes.
|
112
112
|
# In enchant mode, special db aware methods are added to
|
113
113
|
# managed classes and instances.
|
114
|
+
# If false, Og enchants only classes that define properties.
|
114
115
|
|
115
|
-
|
116
|
+
mattr_accessor :enchant_managed_classes, true
|
116
117
|
|
117
118
|
# If true, use Ruby's advanced introspection capabilities to
|
118
119
|
# automatically manage classes tha define properties.
|
119
120
|
|
120
|
-
|
121
|
+
mattr_accessor :auto_manage_classes, true
|
121
122
|
|
122
123
|
# If true, automatically include the Og meta-language into Module.
|
123
|
-
#
|
124
|
-
#
|
125
|
-
# However if you include a prop_accessor or a managed Mixin in your
|
124
|
+
# If false, the polution of the Module object is avoided. However
|
125
|
+
# if you include a prop_accessor or a managed Mixin in your
|
126
126
|
# object MetaLanguage gets automatically extended in the class.
|
127
127
|
|
128
|
-
|
128
|
+
mattr_accessor :include_meta_language, true
|
129
129
|
|
130
130
|
# Attach the following prefix to all generated SQL table names.
|
131
131
|
# Usefull on hosting scenarios where you have to run multiple
|
132
132
|
# web applications/sites on a single database.
|
133
133
|
|
134
|
-
|
134
|
+
mattr_accessor :table_prefix, nil
|
135
135
|
|
136
|
+
# If true, Og tries to create/update the schema in the
|
137
|
+
# data store. For production/live environments set this to false
|
138
|
+
# and only set to true when the object model is upadated.
|
139
|
+
# For debug/development environments this should stay true
|
140
|
+
# for convienience.
|
141
|
+
|
142
|
+
mattr_accessor :create_schema, true
|
143
|
+
|
136
144
|
# The active database. Og allows you to access multiple
|
137
145
|
# databases from a single application.
|
138
146
|
|
139
|
-
|
147
|
+
mattr_accessor :db
|
140
148
|
|
141
149
|
# Set the active database.
|
142
150
|
|