og 0.5.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.
- data/AUTHORS +19 -0
- data/LICENSE +32 -0
- data/README.og +104 -0
- data/RELEASES.og +23 -0
- data/examples/og/README +4 -0
- data/examples/og/run.rb +251 -0
- data/lib/glue.rb +52 -0
- data/lib/glue/array.rb +84 -0
- data/lib/glue/cache.rb +140 -0
- data/lib/glue/hash.rb +143 -0
- data/lib/glue/inflector.rb +91 -0
- data/lib/glue/logger.rb +51 -0
- data/lib/glue/macro.rb +56 -0
- data/lib/glue/mixins.rb +45 -0
- data/lib/glue/number.rb +30 -0
- data/lib/glue/pool.rb +63 -0
- data/lib/glue/property.rb +301 -0
- data/lib/glue/string.rb +224 -0
- data/lib/glue/time.rb +93 -0
- data/lib/og.rb +411 -0
- data/lib/og/backend.rb +258 -0
- data/lib/og/backends/mysql.rb +360 -0
- data/lib/og/backends/psql.rb +359 -0
- data/lib/og/connection.rb +265 -0
- data/lib/og/meta.rb +139 -0
- data/lib/og/version.rb +8 -0
- data/test/tc_og.rb +179 -0
- metadata +71 -0
data/lib/glue/array.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
# code:
|
2
|
+
# * George Moschovitis <gm@navel.gr>
|
3
|
+
#
|
4
|
+
# (c) 2002-2003 Navel, all rights reserved.
|
5
|
+
# $Id: array.rb 165 2004-11-18 12:04:04Z gmosx $
|
6
|
+
|
7
|
+
require "sync"
|
8
|
+
|
9
|
+
module G
|
10
|
+
|
11
|
+
# == SafeArray
|
12
|
+
#
|
13
|
+
# A thread-safe array. We use a sync object instead of a mutex,
|
14
|
+
# because it is re-entrant.
|
15
|
+
# An exclusive lock is needed when writing, a shared lock IS NEEDED
|
16
|
+
# when reading
|
17
|
+
#
|
18
|
+
class SafeArray < Array
|
19
|
+
|
20
|
+
attr :sync
|
21
|
+
|
22
|
+
# gmosx: delegator is not used.
|
23
|
+
#
|
24
|
+
def initialize(delegator = nil)
|
25
|
+
@sync = ::Sync.new()
|
26
|
+
end
|
27
|
+
|
28
|
+
def << (value)
|
29
|
+
return @sync.synchronize(::Sync::SH) {
|
30
|
+
super
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
def delete_if(&block)
|
35
|
+
return @sync.synchronize(::Sync::SH) {
|
36
|
+
super
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
def [](key)
|
41
|
+
return @sync.synchronize(::Sync::SH) {
|
42
|
+
super
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
def []=(key, value)
|
47
|
+
return @sync.synchronize(::Sync::EX) {
|
48
|
+
super
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
def delete(key)
|
53
|
+
return @sync.synchronize(::Sync::EX) {
|
54
|
+
super
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
def clear
|
59
|
+
@sync.synchronize(::Sync::EX) {
|
60
|
+
super
|
61
|
+
}
|
62
|
+
end
|
63
|
+
|
64
|
+
def size
|
65
|
+
return @sync.synchronize(::Sync::SH) {
|
66
|
+
super
|
67
|
+
}
|
68
|
+
end
|
69
|
+
|
70
|
+
def shift
|
71
|
+
return @sync.synchronize(::Sync::EX) {
|
72
|
+
super
|
73
|
+
}
|
74
|
+
end
|
75
|
+
|
76
|
+
def unshift(el)
|
77
|
+
return @sync.synchronize(::Sync::EX) {
|
78
|
+
super
|
79
|
+
}
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end # module
|
data/lib/glue/cache.rb
ADDED
@@ -0,0 +1,140 @@
|
|
1
|
+
# code:
|
2
|
+
# * George Moschovitis <gm@navel.gr>
|
3
|
+
# * Anastasios Koutoumanos <ak@navel.gr>
|
4
|
+
#
|
5
|
+
# (c) 2004 Navel, all rights reserved.
|
6
|
+
# $Id: cache.rb 167 2004-11-23 14:03:10Z gmosx $
|
7
|
+
|
8
|
+
module G;
|
9
|
+
|
10
|
+
# = LRUCache
|
11
|
+
#
|
12
|
+
# A cache utilizing a simple LRU (Least Recently Used) policy.
|
13
|
+
# The items managed by this cache must respond to the #key method.
|
14
|
+
# Attempts to optimize reads rather than inserts!
|
15
|
+
#
|
16
|
+
# LRU semantics are enforced by inserting the items in a queue.
|
17
|
+
# The lru item is always at the tail. Two special sentinels
|
18
|
+
# (head, tail) are used to simplify (?) the code.
|
19
|
+
#
|
20
|
+
class LRUCache < Hash
|
21
|
+
|
22
|
+
# Mix this in your class to make LRU-managable.
|
23
|
+
#
|
24
|
+
module Item
|
25
|
+
attr_accessor :lru_key, :lru_prev, :lru_next
|
26
|
+
end
|
27
|
+
|
28
|
+
# head-tail sentinels
|
29
|
+
#
|
30
|
+
class Sentinel; include Item; end
|
31
|
+
|
32
|
+
# the maximum number of items in the cache
|
33
|
+
attr_accessor :max_items
|
34
|
+
|
35
|
+
# the head sentinel
|
36
|
+
attr :head
|
37
|
+
# the tail sentinel, tail.prev points to the lru item.
|
38
|
+
attr :tail
|
39
|
+
|
40
|
+
#
|
41
|
+
#
|
42
|
+
def initialize(max_items)
|
43
|
+
@max_items = max_items
|
44
|
+
lru_clear()
|
45
|
+
end
|
46
|
+
|
47
|
+
# Lookup an item in the cache
|
48
|
+
#
|
49
|
+
def [](key)
|
50
|
+
if item = super
|
51
|
+
return lru_touch(item)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# The inserted item is considered mru!
|
56
|
+
#
|
57
|
+
def []=(key, item)
|
58
|
+
item = super
|
59
|
+
item.lru_key = key
|
60
|
+
lru_insert(item)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Delete an item from the cache
|
64
|
+
#
|
65
|
+
def delete(key)
|
66
|
+
if item = super
|
67
|
+
lru_delete(item)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Clear the cache
|
72
|
+
#
|
73
|
+
def clear
|
74
|
+
super
|
75
|
+
lru_clear()
|
76
|
+
end
|
77
|
+
|
78
|
+
# The first (mru) element in the cache
|
79
|
+
#
|
80
|
+
def first
|
81
|
+
@head.lru_next
|
82
|
+
end
|
83
|
+
|
84
|
+
# The last (lru) element in the cache
|
85
|
+
#
|
86
|
+
def last
|
87
|
+
@tail.lru_prev
|
88
|
+
end
|
89
|
+
alias_method :lru, :last
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
# Delete an item from the lru list.
|
94
|
+
#
|
95
|
+
def lru_delete(item)
|
96
|
+
lru_join(item.lru_prev, item.lru_next)
|
97
|
+
return item
|
98
|
+
end
|
99
|
+
|
100
|
+
# Join two items in the lru list
|
101
|
+
# Return y to allow for chaining
|
102
|
+
#
|
103
|
+
def lru_join(x, y)
|
104
|
+
x.lru_next = y
|
105
|
+
y.lru_prev = x
|
106
|
+
return y
|
107
|
+
end
|
108
|
+
|
109
|
+
# Append a child item to a parent item in the lru list
|
110
|
+
# (Re)inserts the child in the list.
|
111
|
+
#
|
112
|
+
def lru_append(parent, child)
|
113
|
+
lru_join(child, parent.lru_next)
|
114
|
+
lru_join(parent, child)
|
115
|
+
end
|
116
|
+
|
117
|
+
# Insert an item
|
118
|
+
#
|
119
|
+
def lru_insert(item)
|
120
|
+
delete(last.lru_key) if size() > @max_items
|
121
|
+
lru_append(@head, item)
|
122
|
+
end
|
123
|
+
|
124
|
+
# Touch an item, make mru!
|
125
|
+
# Returns the item
|
126
|
+
#
|
127
|
+
def lru_touch(item)
|
128
|
+
lru_append(@head, lru_delete(item))
|
129
|
+
end
|
130
|
+
|
131
|
+
# Clear the lru
|
132
|
+
#
|
133
|
+
def lru_clear
|
134
|
+
@head = Sentinel.new
|
135
|
+
@tail = Sentinel.new
|
136
|
+
lru_join(@head, @tail)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
end # module
|
data/lib/glue/hash.rb
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
# code:
|
2
|
+
# * George Moschovitis <gm@navel.gr>
|
3
|
+
#
|
4
|
+
# (c) 2004 Navel, all rights reserved.
|
5
|
+
# $Id: hash.rb 167 2004-11-23 14:03:10Z gmosx $
|
6
|
+
|
7
|
+
require "sync"
|
8
|
+
|
9
|
+
module G;
|
10
|
+
|
11
|
+
# == SafeHash
|
12
|
+
#
|
13
|
+
# A thread-safe hash. We use a sync object instead of a mutex,
|
14
|
+
# because it is re-entrant.
|
15
|
+
# An exclusive lock is needed when writing, a shared lock IS NEEDED
|
16
|
+
# when reading
|
17
|
+
# uses the delegator pattern to allow for multiple
|
18
|
+
# implementations!
|
19
|
+
#
|
20
|
+
class SafeHash < Hash
|
21
|
+
attr :sync
|
22
|
+
|
23
|
+
# gmosx: delegator is not used.
|
24
|
+
#
|
25
|
+
def initialize(delegator = nil)
|
26
|
+
@sync = ::Sync.new
|
27
|
+
end
|
28
|
+
|
29
|
+
def [](key)
|
30
|
+
return @sync.synchronize(::Sync::SH) {
|
31
|
+
super
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
def []=(key, value)
|
36
|
+
return @sync.synchronize(::Sync::EX) {
|
37
|
+
super
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
def delete(key)
|
42
|
+
return @sync.synchronize(::Sync::EX) {
|
43
|
+
super
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
def clear
|
48
|
+
@sync.synchronize(::Sync::EX) {
|
49
|
+
super
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
def size
|
54
|
+
return @sync.synchronize(::Sync::SH) {
|
55
|
+
super
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
def values
|
60
|
+
return @sync.synchronize(::Sync::SH) {
|
61
|
+
super
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
def keys
|
66
|
+
return @sync.synchronize(::Sync::SH) {
|
67
|
+
super
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
end # SafeHash
|
72
|
+
|
73
|
+
# == SafeHashDelegator
|
74
|
+
#
|
75
|
+
# A thread-safe hash. We use a sync object instead of a mutex,
|
76
|
+
# because it is re-entrant.
|
77
|
+
# An exclusive lock is needed when writing, a shared lock IS NEEDED
|
78
|
+
# when reading
|
79
|
+
#
|
80
|
+
# Design:
|
81
|
+
# This class uses the delegator pattern. However we dont use rubys
|
82
|
+
# delegation facilities, they are more general and powerfull than we
|
83
|
+
# need here (and slower). Instead a custom (but simple) solution is
|
84
|
+
# used.
|
85
|
+
#
|
86
|
+
# Example:
|
87
|
+
#
|
88
|
+
# hash = SafeHashDelegator.new(Hash.new)
|
89
|
+
# hash = SafeHashDelegator.new(Hash.new)
|
90
|
+
|
91
|
+
class SafeHashDelegator < Hash
|
92
|
+
attr :delegate, :sync
|
93
|
+
|
94
|
+
def initialize(delegate)
|
95
|
+
@delegate = delegate
|
96
|
+
@sync = ::Sync.new
|
97
|
+
end
|
98
|
+
|
99
|
+
def [](key)
|
100
|
+
return @sync.synchronize(::Sync::SH) {
|
101
|
+
@delegate[key]
|
102
|
+
}
|
103
|
+
end
|
104
|
+
|
105
|
+
def []=(key, value)
|
106
|
+
return @sync.synchronize(::Sync::EX) {
|
107
|
+
@delegate[key] = value
|
108
|
+
}
|
109
|
+
end
|
110
|
+
|
111
|
+
def delete(key)
|
112
|
+
return @sync.synchronize(::Sync::EX) {
|
113
|
+
@delegate.delete(key)
|
114
|
+
}
|
115
|
+
end
|
116
|
+
|
117
|
+
def clear
|
118
|
+
@sync.synchronize(::Sync::EX) {
|
119
|
+
@delegate.clear
|
120
|
+
}
|
121
|
+
end
|
122
|
+
|
123
|
+
def size
|
124
|
+
return @sync.synchronize(::Sync::SH) {
|
125
|
+
@delegate.size()
|
126
|
+
}
|
127
|
+
end
|
128
|
+
|
129
|
+
def values
|
130
|
+
return @sync.synchronize(::Sync::SH) {
|
131
|
+
@delegate.values()
|
132
|
+
}
|
133
|
+
end
|
134
|
+
|
135
|
+
def keys
|
136
|
+
return @sync.synchronize(::Sync::SH) {
|
137
|
+
@delegate.keys()
|
138
|
+
}
|
139
|
+
end
|
140
|
+
|
141
|
+
end # SafeHashDelegator
|
142
|
+
|
143
|
+
end # module
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# Code from RubyOnRailes (http://www.rubyonrails.com)
|
2
|
+
# Copyright (c) 2004 David Heinemeier Hansson.
|
3
|
+
#
|
4
|
+
|
5
|
+
module G
|
6
|
+
|
7
|
+
# The Inflector transforms words from singular to plural, class names to table names, modulized class names to ones without,
|
8
|
+
# and class names to foreign keys.
|
9
|
+
#
|
10
|
+
module Inflector
|
11
|
+
extend self
|
12
|
+
|
13
|
+
def pluralize(word)
|
14
|
+
result = word.dup
|
15
|
+
plural_rules.each do |(rule, replacement)|
|
16
|
+
break if result.gsub!(rule, replacement)
|
17
|
+
end
|
18
|
+
return result
|
19
|
+
end
|
20
|
+
|
21
|
+
def singularize(word)
|
22
|
+
result = word.dup
|
23
|
+
singular_rules.each do |(rule, replacement)|
|
24
|
+
break if result.gsub!(rule, replacement)
|
25
|
+
end
|
26
|
+
return result
|
27
|
+
end
|
28
|
+
|
29
|
+
def camelize(lower_case_and_underscored_word)
|
30
|
+
lower_case_and_underscored_word.gsub(/(^|_)(.)/){$2.upcase}
|
31
|
+
end
|
32
|
+
|
33
|
+
def underscore(camel_cased_word)
|
34
|
+
camel_cased_word.gsub(/([A-Z]+)([A-Z])/,'\1_\2').gsub(/([a-z])([A-Z])/,'\1_\2').downcase
|
35
|
+
end
|
36
|
+
|
37
|
+
def demodulize(class_name_in_module)
|
38
|
+
class_name_in_module.gsub(/^.*::/, '')
|
39
|
+
end
|
40
|
+
|
41
|
+
def foreign_key(class_name, separate_class_name_and_id_with_underscore = true)
|
42
|
+
Inflector.underscore(Inflector.demodulize(class_name)) +
|
43
|
+
(separate_class_name_and_id_with_underscore ? "_id" : "id")
|
44
|
+
end
|
45
|
+
|
46
|
+
# Convert a class to a name.
|
47
|
+
#
|
48
|
+
def name(klass)
|
49
|
+
Inflector.underscore(Inflector.demodulize(klass.to_s))
|
50
|
+
end
|
51
|
+
|
52
|
+
# Convert a class to a name in plural
|
53
|
+
#
|
54
|
+
def plural_name(klass)
|
55
|
+
Inflector.pluralize(Inflector.underscore(Inflector.demodulize(klass.to_s)))
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
def plural_rules #:doc:
|
60
|
+
[
|
61
|
+
[/(x|ch|ss)$/, '\1es'], # search, switch, fix, box, process, address
|
62
|
+
[/([^aeiouy]|qu)y$/, '\1ies'], # query, ability, agency
|
63
|
+
[/(?:([^f])fe|([lr])f)$/, '\1\2ves'], # half, safe, wife
|
64
|
+
[/sis$/, 'ses'], # basis, diagnosis
|
65
|
+
[/([ti])um$/, '\1a'], # datum, medium
|
66
|
+
[/person$/, 'people'], # person, salesperson
|
67
|
+
[/man$/, 'men'], # man, woman, spokesman
|
68
|
+
[/child$/, 'children'], # child
|
69
|
+
[/s$/, 's'], # no change (compatibility)
|
70
|
+
[/$/, 's']
|
71
|
+
]
|
72
|
+
end
|
73
|
+
|
74
|
+
def singular_rules #:doc:
|
75
|
+
[
|
76
|
+
[/(x|ch|ss)es$/, '\1'],
|
77
|
+
[/([^aeiouy]|qu)ies$/, '\1y'],
|
78
|
+
[/([lr])ves$/, '\1f'],
|
79
|
+
[/([^f])ves$/, '\1fe'],
|
80
|
+
[/(analy|ba|diagno|parenthe|progno|synop|the)ses$/, '\1sis'],
|
81
|
+
[/([ti])a$/, '\1um'],
|
82
|
+
[/people$/, 'person'],
|
83
|
+
[/men$/, 'man'],
|
84
|
+
[/status$/, 'status'],
|
85
|
+
[/children$/, 'child'],
|
86
|
+
[/s$/, '']
|
87
|
+
]
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end # module
|