og 0.7.0 → 0.8.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 +14 -4
- data/ChangeLog +192 -1
- data/README.og +2 -1
- data/RELEASES.og +35 -0
- data/Rakefile +1 -1
- data/examples/og/mock_example.rb +6 -9
- data/examples/og/mysql_to_psql.rb +100 -0
- data/examples/og/run.rb +8 -17
- data/lib/glue/array.rb +1 -1
- data/lib/glue/attribute.rb +86 -0
- data/lib/glue/cache.rb +1 -1
- data/lib/glue/hash.rb +1 -1
- data/lib/glue/inflector.rb +1 -1
- data/lib/glue/logger.rb +118 -18
- data/lib/glue/mixins.rb +1 -1
- data/lib/glue/number.rb +1 -1
- data/lib/glue/pool.rb +1 -1
- data/lib/glue/property.rb +48 -31
- data/lib/glue/string.rb +1 -1
- data/lib/glue/time.rb +2 -2
- data/lib/glue/validation.rb +400 -0
- data/lib/glue.rb +7 -8
- data/lib/og/backend.rb +47 -46
- data/lib/og/backends/mysql.rb +64 -63
- data/lib/og/backends/psql.rb +73 -72
- data/lib/og/connection.rb +7 -8
- data/lib/og/enchant.rb +80 -0
- data/lib/og/meta.rb +21 -21
- data/lib/og/mock.rb +31 -88
- data/lib/og/version.rb +6 -5
- data/lib/og.rb +95 -129
- data/test/tc_og.rb +3 -3
- data/vendor/extensions/_base.rb +153 -0
- data/vendor/extensions/_template.rb +36 -0
- data/vendor/extensions/all.rb +21 -0
- data/vendor/extensions/array.rb +68 -0
- data/vendor/extensions/binding.rb +224 -0
- data/vendor/extensions/class.rb +50 -0
- data/vendor/extensions/continuation.rb +71 -0
- data/vendor/extensions/enumerable.rb +250 -0
- data/vendor/extensions/hash.rb +23 -0
- data/vendor/extensions/io.rb +58 -0
- data/vendor/extensions/kernel.rb +42 -0
- data/vendor/extensions/module.rb +114 -0
- data/vendor/extensions/numeric.rb +230 -0
- data/vendor/extensions/object.rb +164 -0
- data/vendor/extensions/ostruct.rb +41 -0
- data/vendor/extensions/string.rb +316 -0
- data/vendor/extensions/symbol.rb +28 -0
- metadata +24 -4
- data/lib/glue/property.rb.old +0 -307
data/lib/og/meta.rb
CHANGED
@@ -7,7 +7,7 @@
|
|
7
7
|
require 'og/backend'
|
8
8
|
require 'glue/inflector'
|
9
9
|
|
10
|
-
|
10
|
+
class Og
|
11
11
|
|
12
12
|
# = MetaUtils
|
13
13
|
#
|
@@ -66,7 +66,7 @@ module MetaLanguage
|
|
66
66
|
#{prop_eval}
|
67
67
|
|
68
68
|
def #{name}
|
69
|
-
|
69
|
+
Og.db.load_by_oid(@#{name}_oid, #{klass})
|
70
70
|
end
|
71
71
|
|
72
72
|
def #{name}=(obj_or_oid)
|
@@ -104,7 +104,7 @@ module MetaLanguage
|
|
104
104
|
end
|
105
105
|
|
106
106
|
def #{name}(extrasql = nil)
|
107
|
-
|
107
|
+
Og.db.select_one("SELECT * FROM #{Og::Backend.table(klass)} WHERE #{linkback}=\#\@oid \#\{extrasql\}", #{klass})
|
108
108
|
end
|
109
109
|
}
|
110
110
|
end
|
@@ -123,7 +123,7 @@ module MetaLanguage
|
|
123
123
|
# def children; ... end
|
124
124
|
#
|
125
125
|
def has_many(name, klass, options = {})
|
126
|
-
name_s =
|
126
|
+
name_s = N::Inflector.singularize(name.to_s)
|
127
127
|
|
128
128
|
# linkback is the property of the child object that 'links back'
|
129
129
|
# to this object.
|
@@ -140,11 +140,11 @@ module MetaLanguage
|
|
140
140
|
end
|
141
141
|
|
142
142
|
def #{name}(extrasql = nil)
|
143
|
-
|
143
|
+
Og.db.select("SELECT * FROM #{Og::Backend.table(klass)} WHERE #{linkback}=\#\@oid \#\{extrasql\}", #{klass})
|
144
144
|
end
|
145
145
|
|
146
146
|
def #{name}_count(extrasql = nil)
|
147
|
-
|
147
|
+
Og.db.count("SELECT COUNT(*) FROM #{Og::Backend.table(klass)} WHERE #{linkback}=\#\@oid \#\{extrasql\}")
|
148
148
|
end
|
149
149
|
|
150
150
|
def add_#{name_s}(obj, extra = nil)
|
@@ -179,9 +179,9 @@ module MetaLanguage
|
|
179
179
|
#++
|
180
180
|
def many_to_many(name, klass, options = {})
|
181
181
|
list_o = name.to_s
|
182
|
-
prop_o =
|
183
|
-
list_m = options[:linkback] ||
|
184
|
-
prop_m =
|
182
|
+
prop_o = N::Inflector.singularize(list_o)
|
183
|
+
list_m = options[:linkback] || N::Inflector.plural_name(self)
|
184
|
+
prop_m = N::Inflector.singularize(list_m)
|
185
185
|
|
186
186
|
# exit if the class is allready indirectly 'enchanted' from the
|
187
187
|
# other class of the many_to_many relation.
|
@@ -197,24 +197,24 @@ module MetaLanguage
|
|
197
197
|
|
198
198
|
module_eval %{
|
199
199
|
def #{list_o}(extrasql = nil)
|
200
|
-
|
200
|
+
Og.db.select("SELECT d.* FROM #{Og::Backend.table(klass)} AS d, #{Og::Backend.join_table(self, klass)} AS j WHERE j.key1=\#\@oid AND j.key2=d.oid \#\{extrasql\}", #{klass})
|
201
201
|
end
|
202
202
|
|
203
203
|
def #{list_o}_count(extrasql = nil)
|
204
|
-
|
204
|
+
Og.db.select("SELECT COUNT(*) FROM #{Og::Backend.table(klass)} AS d, #{Og::Backend.join_table(self, klass)} AS j WHERE j.key1=\#\@oid AND j.key2=d.oid \#\{extrasql\}", #{klass})
|
205
205
|
end
|
206
206
|
|
207
207
|
def add_#{prop_o}(obj, extra = nil)
|
208
|
-
|
208
|
+
Og.db.exec("INSERT INTO #{Og::Backend.join_table(self, klass)} (key1, key2) VALUES (\#\@oid, \#\{obj.oid\})")
|
209
209
|
end
|
210
210
|
|
211
211
|
def del_#{prop_o}(obj_or_oid, extra = nil)
|
212
|
-
|
212
|
+
Og.db.exec("DELETE FROM #{Og::Backend.join_table(self, klass)} WHERE key2=\#\{obj_or_oid.to_i\}")
|
213
213
|
end
|
214
214
|
alias_method :delete_#{prop_o}, :del_#{prop_o}
|
215
215
|
|
216
216
|
def clear_#{list_o}
|
217
|
-
|
217
|
+
Og.db.exec("DELETE FROM #{Og::Backend.join_table(self, klass)} WHERE key1=\#\@oid")
|
218
218
|
end
|
219
219
|
}
|
220
220
|
|
@@ -222,24 +222,24 @@ module MetaLanguage
|
|
222
222
|
|
223
223
|
klass.module_eval %{
|
224
224
|
def #{list_m}(extrasql = nil)
|
225
|
-
|
225
|
+
Og.db.select("SELECT s.* FROM #{Og::Backend.table(self)} AS s, #{Og::Backend.join_table(self, klass)} AS j WHERE j.key2=\#\@oid AND j.key1=s.oid \#\{extrasql\}", #{self})
|
226
226
|
end
|
227
227
|
|
228
228
|
def #{list_m}_count(extrasql = nil)
|
229
|
-
|
229
|
+
Og.db.select("SELECT COUNT(*) FROM #{Og::Backend.table(self)} AS s, #{Og::Backend.join_table(self, klass)} AS j WHERE j.key2=\#\@oid AND j.key1=s.oid \#\{extrasql\}", #{self})
|
230
230
|
end
|
231
231
|
|
232
232
|
def add_#{prop_m}(obj, extra = nil)
|
233
|
-
|
233
|
+
Og.db.exec("INSERT INTO #{Og::Backend.join_table(self, klass)} (key1, key2) VALUES (\#\{obj.oid\}, \#\@oid)")
|
234
234
|
end
|
235
235
|
|
236
236
|
def del_#{prop_m}(obj_or_oid, extra = nil)
|
237
|
-
|
237
|
+
Og.db.exec("DELETE FROM #{Og::Backend.join_table(self, klass)} WHERE key1=\#\{obj_or_oid.to_i\}")
|
238
238
|
end
|
239
239
|
alias_method :delete_#{prop_m}, :del_#{prop_m}
|
240
240
|
|
241
241
|
def clear_#{list_m}
|
242
|
-
|
242
|
+
Og.db.exec("DELETE FROM #{Og::Backend.join_table(self, klass)} WHERE key2=\#\@oid")
|
243
243
|
end
|
244
244
|
}
|
245
245
|
end
|
@@ -247,13 +247,13 @@ module MetaLanguage
|
|
247
247
|
|
248
248
|
end
|
249
249
|
|
250
|
-
end #
|
250
|
+
end # namespace
|
251
251
|
|
252
252
|
# Include the meta-language extensions into Module. If the flag is
|
253
253
|
# false the developer is responsible for including the MetaLanguage
|
254
254
|
# module where needed.
|
255
255
|
#
|
256
|
-
if
|
256
|
+
if Og.include_meta_language
|
257
257
|
class Module # :nodoc: all
|
258
258
|
include Og::MetaLanguage
|
259
259
|
end
|
data/lib/og/mock.rb
CHANGED
@@ -10,7 +10,7 @@ require 'og'
|
|
10
10
|
require 'rubygems'
|
11
11
|
require_gem 'flexmock'
|
12
12
|
|
13
|
-
|
13
|
+
class Og
|
14
14
|
|
15
15
|
# = MockDatabase
|
16
16
|
#
|
@@ -22,6 +22,7 @@ module Og
|
|
22
22
|
# to avoid code duplication.
|
23
23
|
#++
|
24
24
|
class MockDatabase < ::FlexMock
|
25
|
+
include Og::Enchant
|
25
26
|
|
26
27
|
# Managed class metadata
|
27
28
|
#
|
@@ -53,11 +54,11 @@ class MockDatabase < ::FlexMock
|
|
53
54
|
# Initialize FlexMock
|
54
55
|
super
|
55
56
|
|
56
|
-
@managed_classes =
|
57
|
+
@managed_classes = N::SafeHash.new
|
57
58
|
|
58
|
-
|
59
|
+
Logger.info "Using mock database."
|
59
60
|
|
60
|
-
if
|
61
|
+
if Og.auto_manage_classes
|
61
62
|
# automatically manage classes with properties and metadata.
|
62
63
|
# gmosx: Any idea how to optimize this?
|
63
64
|
classes_to_manage = []
|
@@ -66,10 +67,13 @@ class MockDatabase < ::FlexMock
|
|
66
67
|
classes_to_manage << c
|
67
68
|
end
|
68
69
|
end
|
69
|
-
|
70
|
-
|
70
|
+
Logger.info "Og auto manages the following classes:"
|
71
|
+
Logger.info "#{classes_to_manage.inspect}"
|
71
72
|
manage_classes(*classes_to_manage)
|
72
73
|
end
|
74
|
+
|
75
|
+
# use the newly created database.
|
76
|
+
Og.use(self)
|
73
77
|
end
|
74
78
|
|
75
79
|
# Shutdown the database interface.
|
@@ -78,6 +82,20 @@ class MockDatabase < ::FlexMock
|
|
78
82
|
end
|
79
83
|
alias_method :close, :shutdown
|
80
84
|
|
85
|
+
# Get a connection from the pool to access the database.
|
86
|
+
# Stores the connection in a thread-local variable.
|
87
|
+
#
|
88
|
+
def get_connection
|
89
|
+
# nop
|
90
|
+
end
|
91
|
+
alias_method :connection, :get_connection
|
92
|
+
|
93
|
+
# Restore an unused connection to the pool.
|
94
|
+
#
|
95
|
+
def put_connection
|
96
|
+
# nop
|
97
|
+
end
|
98
|
+
|
81
99
|
# Register a standard Ruby class as managed.
|
82
100
|
#
|
83
101
|
def manage(klass)
|
@@ -89,7 +107,7 @@ class MockDatabase < ::FlexMock
|
|
89
107
|
convert(klass)
|
90
108
|
|
91
109
|
# Add helper methods to the class.
|
92
|
-
enchant(klass) if
|
110
|
+
enchant(klass) if Og.enchant_managed_classes
|
93
111
|
end
|
94
112
|
|
95
113
|
# Helper method to set multiple managed classes.
|
@@ -116,72 +134,14 @@ class MockDatabase < ::FlexMock
|
|
116
134
|
#
|
117
135
|
def convert(klass)
|
118
136
|
klass.class_eval %{
|
119
|
-
DBTABLE = "#{Og::
|
120
|
-
DBSEQ = "#{Og::
|
137
|
+
DBTABLE = "#{Og::Backend.table(klass)}"
|
138
|
+
DBSEQ = "#{Og::Backend.table(klass)}_oids_seq"
|
121
139
|
|
122
140
|
def to_i()
|
123
141
|
@oid
|
124
142
|
end
|
125
143
|
}
|
126
144
|
end
|
127
|
-
|
128
|
-
# Enchant a managed class. Add useful DB related methods to the
|
129
|
-
# class and its instances.
|
130
|
-
#
|
131
|
-
def enchant(klass)
|
132
|
-
klass.class_eval %{
|
133
|
-
def self.save(obj)
|
134
|
-
$og << obj
|
135
|
-
end
|
136
|
-
|
137
|
-
def self.load(oid_or_name)
|
138
|
-
$og.load(oid_or_name, #{klass})
|
139
|
-
end
|
140
|
-
|
141
|
-
def self.[](oid_or_name)
|
142
|
-
$og.load(oid_or_name, #{klass})
|
143
|
-
end
|
144
|
-
|
145
|
-
def self.load_all(extra_sql = nil)
|
146
|
-
$og.load_all(#{klass}, extra_sql)
|
147
|
-
end
|
148
|
-
|
149
|
-
def self.all(extra_sql = nil)
|
150
|
-
$og.load_all(#{klass}, extra_sql)
|
151
|
-
end
|
152
|
-
|
153
|
-
def self.count(sql = "SELECT COUNT(*) FROM #{klass::DBTABLE}")
|
154
|
-
$og.count(sql, #{klass})
|
155
|
-
end
|
156
|
-
|
157
|
-
def self.select(sql)
|
158
|
-
$og.select(sql, #{klass})
|
159
|
-
end
|
160
|
-
|
161
|
-
def self.select_one(sql)
|
162
|
-
$og.select_one(sql, #{klass})
|
163
|
-
end
|
164
|
-
|
165
|
-
def self.delete(obj_or_oid)
|
166
|
-
$og.delete(obj_or_oid, #{klass})
|
167
|
-
end
|
168
|
-
|
169
|
-
def save
|
170
|
-
$og << self
|
171
|
-
return self
|
172
|
-
end
|
173
|
-
alias_method :save!, :save
|
174
|
-
|
175
|
-
def update_properties(updatesql)
|
176
|
-
$og.pupdate(updatesql, self.oid, #{klass})
|
177
|
-
end
|
178
|
-
alias_method :pupdate!, :update_properties
|
179
|
-
|
180
|
-
def delete!
|
181
|
-
$og.delete(@oid, #{klass})
|
182
|
-
end
|
183
|
-
}
|
184
|
-
end
|
185
145
|
|
186
146
|
# Automatically wrap connection methods.
|
187
147
|
#
|
@@ -193,31 +153,14 @@ class MockDatabase < ::FlexMock
|
|
193
153
|
end
|
194
154
|
}
|
195
155
|
end
|
196
|
-
|
197
|
-
wrap_method :create_table, "klass"
|
198
|
-
wrap_method :drop_table, "klass"
|
199
|
-
wrap_method :save, "obj"; alias_method :<<, :save; alias_method :put, :save
|
200
|
-
wrap_method :insert, "obj"
|
201
|
-
wrap_method :update, "obj"
|
202
|
-
wrap_method :update_properties, "update_sql, obj_or_oid, klass = nil"
|
203
|
-
wrap_method :pupdate, "update_sql, obj_or_oid, klass = nil"
|
204
|
-
wrap_method :load, "oid, klass"; alias_method :get, :load
|
205
|
-
wrap_method :load_by_oid, "oid, klass"
|
206
|
-
wrap_method :load_by_name, "name, klass"
|
207
|
-
wrap_method :load_all, "klass, extrasql = nil"
|
208
|
-
wrap_method :select, "sql, klass"
|
209
|
-
wrap_method :select_one, "sql, klass"
|
210
|
-
wrap_method :count, "sql, klass = nil"
|
211
|
-
wrap_method :delete, "obj_or_oid, klass = nil"
|
212
|
-
wrap_method :query, "sql"
|
213
|
-
wrap_method :exec, "sql"
|
214
|
-
=end
|
156
|
+
|
215
157
|
def self.create_db!(config)
|
158
|
+
# nop
|
216
159
|
end
|
217
160
|
|
218
161
|
def self.drop_db!(config)
|
162
|
+
# nop
|
219
163
|
end
|
220
164
|
end
|
221
165
|
|
222
|
-
end #
|
223
|
-
|
166
|
+
end # namespace
|
data/lib/og/version.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
-
|
2
|
-
#
|
3
|
-
#
|
4
|
-
# (c) 2004 Navel, all rights reserved.
|
1
|
+
#--
|
2
|
+
# George Moschovitis <gm@navel.gr>
|
3
|
+
# (c) 2004-2005 Navel, all rights reserved.
|
5
4
|
# $Id: version.rb 198 2004-12-22 11:26:59Z gmosx $
|
5
|
+
#++
|
6
6
|
|
7
7
|
# The version of Og.
|
8
|
-
|
8
|
+
|
9
|
+
$og_version = '0.8.0'
|
data/lib/og.rb
CHANGED
@@ -4,36 +4,12 @@
|
|
4
4
|
# (c) 2004 Navel, all rights reserved.
|
5
5
|
# $Id: og.rb 197 2004-12-21 13:50:17Z gmosx $
|
6
6
|
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
11
|
-
require
|
12
|
-
|
13
|
-
# If true, only allow reading from the database. Usefull
|
14
|
-
# for maintainance.
|
15
|
-
#
|
16
|
-
$og_read_only_mode = false
|
17
|
-
|
18
|
-
# If true, the library automatically 'enchants' managed classes.
|
19
|
-
# In enchant mode, special db aware methods are added to
|
20
|
-
# managed classes and instances.
|
21
|
-
#
|
22
|
-
$og_enchant_managed_classes = true
|
23
|
-
|
24
|
-
# If true, use Ruby's advanced introspection capabilities to
|
25
|
-
# automatically manage classes tha define properties.
|
26
|
-
$og_auto_manage_classes = true
|
27
|
-
|
28
|
-
# If true, automatically include the Og meta-language into Module.
|
29
|
-
$og_include_meta_language = true
|
30
|
-
|
31
|
-
# Attach the following prefix to all generated SQL table names.
|
32
|
-
# Usefull on hosting scenarios where you have to run multiple
|
33
|
-
# web applications/sites on a single database.
|
34
|
-
$og_table_prefix = nil
|
35
|
-
|
36
|
-
require "og/meta"
|
7
|
+
require 'glue/logger'
|
8
|
+
require 'glue/property'
|
9
|
+
require 'glue/array'
|
10
|
+
require 'glue/hash'
|
11
|
+
require 'glue/time'
|
12
|
+
require 'glue/pool'
|
37
13
|
|
38
14
|
# = Og
|
39
15
|
#
|
@@ -58,11 +34,12 @@ require "og/meta"
|
|
58
34
|
# + Transparent support for cascading deletes for all backends.
|
59
35
|
# + Hierarchical structures (preorder traversal, materialized paths)
|
60
36
|
# + Works safely as part of distributed application.
|
61
|
-
# + Simple implementation
|
37
|
+
# + Simple implementation.
|
62
38
|
#
|
63
39
|
# === Meta language
|
64
40
|
#
|
65
|
-
# primary_key :pid
|
41
|
+
# primary_key :pid (NOT IMPLEMENTED)
|
42
|
+
# name_key :name (NOT IMPLEMENTED)
|
66
43
|
# prop_accessor Fixnum, :pid, :sql => "smallint DEFAULT 1"
|
67
44
|
# has_many Child, :children
|
68
45
|
# many_to_many Role, :roles
|
@@ -71,10 +48,10 @@ require "og/meta"
|
|
71
48
|
# === Design
|
72
49
|
#
|
73
50
|
# Keep the main classes backend agnostic.
|
74
|
-
|
51
|
+
#--
|
75
52
|
# Try to make the methods work with oids. Do NOT implement descendants
|
76
53
|
# use a root id (rid).
|
77
|
-
|
54
|
+
#++
|
78
55
|
# For class ids we use the name instead of a hash. Class ids are
|
79
56
|
# typically not used in querys, they are stored for completeness.
|
80
57
|
# If we store a hash we cannot reclaim the class thus invalidating
|
@@ -89,7 +66,7 @@ require "og/meta"
|
|
89
66
|
# This is NOT a singleton, an application may access multiple
|
90
67
|
# databases.
|
91
68
|
#
|
92
|
-
# The
|
69
|
+
# The og.xxx methods are more flexible and allow you to use
|
93
70
|
# multiple databases for example.
|
94
71
|
#
|
95
72
|
# === Managed Objects Lifecycle Callbacks
|
@@ -101,7 +78,6 @@ require "og/meta"
|
|
101
78
|
# * og_pre_insert_update
|
102
79
|
# * og_post_insert_update
|
103
80
|
# * self.og_pre_delete
|
104
|
-
# * validate
|
105
81
|
#
|
106
82
|
# A class level callback is used for delete because typically you call
|
107
83
|
# delete with an oid and not an object to avoid a deserialization.
|
@@ -114,8 +90,53 @@ require "og/meta"
|
|
114
90
|
# * Deserialize to OpenStruct.
|
115
91
|
# * Better documentation.
|
116
92
|
#
|
117
|
-
|
93
|
+
class Og
|
94
|
+
class << self
|
95
|
+
# If true, only allow reading from the database. Usefull
|
96
|
+
# for maintainance.
|
97
|
+
attr_accessor :read_only_mode
|
98
|
+
|
99
|
+
# If true, the library automatically 'enchants' managed classes.
|
100
|
+
# In enchant mode, special db aware methods are added to
|
101
|
+
# managed classes and instances.
|
102
|
+
attr_accessor :enchant_managed_classes
|
103
|
+
|
104
|
+
# If true, use Ruby's advanced introspection capabilities to
|
105
|
+
# automatically manage classes tha define properties.
|
106
|
+
attr_accessor :auto_manage_classes
|
118
107
|
|
108
|
+
# If true, automatically include the Og meta-language into Module.
|
109
|
+
attr_accessor :include_meta_language
|
110
|
+
|
111
|
+
# Attach the following prefix to all generated SQL table names.
|
112
|
+
# Usefull on hosting scenarios where you have to run multiple
|
113
|
+
# web applications/sites on a single database.
|
114
|
+
attr_accessor :table_prefix
|
115
|
+
|
116
|
+
# The active database. Og allows you to access multiple
|
117
|
+
# databases from a single application.
|
118
|
+
attr_accessor :db
|
119
|
+
|
120
|
+
def use(db)
|
121
|
+
@db = db
|
122
|
+
@db.get_connection
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# set default options:
|
127
|
+
self.read_only_mode = false
|
128
|
+
self.enchant_managed_classes = true
|
129
|
+
self.auto_manage_classes = true
|
130
|
+
self.include_meta_language = true
|
131
|
+
self.table_prefix = nil
|
132
|
+
end
|
133
|
+
|
134
|
+
# gmosx: leave this here.
|
135
|
+
require 'og/enchant'
|
136
|
+
require 'og/meta'
|
137
|
+
|
138
|
+
class Og
|
139
|
+
|
119
140
|
# = Unmanageable
|
120
141
|
#
|
121
142
|
# Marker module. If included this in a class, the Og automanager
|
@@ -128,6 +149,7 @@ module Unmanageable; end
|
|
128
149
|
# Encapsulates an Og Database.
|
129
150
|
#
|
130
151
|
class Database
|
152
|
+
include Og::Enchant
|
131
153
|
|
132
154
|
# Managed class metadata
|
133
155
|
#
|
@@ -166,10 +188,10 @@ class Database
|
|
166
188
|
require "og/backends/#{backend}"
|
167
189
|
eval %{ @config[:backend] = #{backend.capitalize}Backend }
|
168
190
|
|
169
|
-
@connection_pool =
|
170
|
-
@managed_classes =
|
191
|
+
@connection_pool = N::Pool.new
|
192
|
+
@managed_classes = N::SafeHash.new
|
171
193
|
|
172
|
-
|
194
|
+
Logger.info "Connecting to database '#{@config[:database]}' using backend '#{backend}'."
|
173
195
|
|
174
196
|
@config[:connection_count].times do
|
175
197
|
@connection_pool << Og::Connection.new(self)
|
@@ -178,7 +200,7 @@ class Database
|
|
178
200
|
# gmosx, FIXME: this automanage code is not elegant and slow
|
179
201
|
# should probably recode this, along with glue/property.rb
|
180
202
|
#
|
181
|
-
if
|
203
|
+
if Og.auto_manage_classes
|
182
204
|
# automatically manage classes with properties and metadata.
|
183
205
|
# gmosx: Any idea how to optimize this?
|
184
206
|
classes_to_manage = []
|
@@ -187,10 +209,13 @@ class Database
|
|
187
209
|
classes_to_manage << c
|
188
210
|
end
|
189
211
|
end
|
190
|
-
|
191
|
-
|
212
|
+
Logger.info "Og auto manages the following classes:"
|
213
|
+
Logger.info "#{classes_to_manage.inspect}"
|
192
214
|
manage_classes(*classes_to_manage)
|
193
215
|
end
|
216
|
+
|
217
|
+
# use the newly created database.
|
218
|
+
Og.use(self)
|
194
219
|
end
|
195
220
|
|
196
221
|
# Shutdown the database interface.
|
@@ -206,8 +231,6 @@ class Database
|
|
206
231
|
# Stores the connection in a thread-local variable.
|
207
232
|
#
|
208
233
|
def get_connection
|
209
|
-
$log.debug "Get Og connection" if $DBG
|
210
|
-
|
211
234
|
thread = Thread.current
|
212
235
|
|
213
236
|
unless conn = thread[:og_conn]
|
@@ -217,12 +240,11 @@ class Database
|
|
217
240
|
|
218
241
|
return conn
|
219
242
|
end
|
243
|
+
alias_method :connection, :get_connection
|
220
244
|
|
221
245
|
# Restore an unused connection to the pool.
|
222
246
|
#
|
223
247
|
def put_connection
|
224
|
-
$log.debug "Put Og connection" if $DBG
|
225
|
-
|
226
248
|
thread = Thread.current
|
227
249
|
|
228
250
|
if conn = thread[:og_conn]
|
@@ -263,7 +285,7 @@ class Database
|
|
263
285
|
convert(klass)
|
264
286
|
|
265
287
|
# Add helper methods to the class.
|
266
|
-
enchant(klass) if
|
288
|
+
enchant(klass) if Og.enchant_managed_classes
|
267
289
|
end
|
268
290
|
|
269
291
|
# Helper method to set multiple managed classes.
|
@@ -289,13 +311,16 @@ class Database
|
|
289
311
|
# Add standard og functionality to the class
|
290
312
|
#
|
291
313
|
def convert(klass)
|
314
|
+
# Grab backend class
|
315
|
+
backend = @config[:backend]
|
316
|
+
|
292
317
|
# gmosx: this check is needed to allow the developer to customize
|
293
318
|
# the sql generated for oid
|
294
|
-
|
319
|
+
backend.eval_og_oid(klass) unless klass.instance_methods.include?(:oid)
|
295
320
|
|
296
321
|
klass.class_eval %{
|
297
|
-
DBTABLE = "#{
|
298
|
-
DBSEQ = "#{
|
322
|
+
DBTABLE = "#{backend.table(klass)}"
|
323
|
+
DBSEQ = "#{backend.table(klass)}_oids_seq"
|
299
324
|
|
300
325
|
def to_i()
|
301
326
|
@oid
|
@@ -308,72 +333,9 @@ class Database
|
|
308
333
|
# Precompile some code that gets executed all the time.
|
309
334
|
# Deletion code is not precompiled, because it is not used
|
310
335
|
# as frequently.
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
end
|
315
|
-
|
316
|
-
# Enchant a managed class. Add useful DB related methods to the
|
317
|
-
# class and its instances.
|
318
|
-
#
|
319
|
-
def enchant(klass)
|
320
|
-
klass.module_eval <<-"end_eval", __FILE__, __LINE__
|
321
|
-
def self.create(*params)
|
322
|
-
obj = #{klass}.new(*params)
|
323
|
-
obj.save!
|
324
|
-
end
|
325
|
-
|
326
|
-
def self.save(obj)
|
327
|
-
$og << obj
|
328
|
-
end
|
329
|
-
|
330
|
-
def self.load(oid_or_name)
|
331
|
-
$og.load(oid_or_name, #{klass})
|
332
|
-
end
|
333
|
-
|
334
|
-
def self.[](oid_or_name)
|
335
|
-
$og.load(oid_or_name, #{klass})
|
336
|
-
end
|
337
|
-
|
338
|
-
def self.load_all(extra_sql = nil)
|
339
|
-
$og.load_all(#{klass}, extra_sql)
|
340
|
-
end
|
341
|
-
|
342
|
-
def self.all(extra_sql = nil)
|
343
|
-
$og.load_all(#{klass}, extra_sql)
|
344
|
-
end
|
345
|
-
|
346
|
-
def self.count(sql = "SELECT COUNT(*) FROM #{klass::DBTABLE}")
|
347
|
-
$og.count(sql, #{klass})
|
348
|
-
end
|
349
|
-
|
350
|
-
def self.select(sql)
|
351
|
-
$og.select(sql, #{klass})
|
352
|
-
end
|
353
|
-
|
354
|
-
def self.select_one(sql)
|
355
|
-
$og.select_one(sql, #{klass})
|
356
|
-
end
|
357
|
-
|
358
|
-
def self.delete(obj_or_oid)
|
359
|
-
$og.delete(obj_or_oid, #{klass})
|
360
|
-
end
|
361
|
-
|
362
|
-
def save
|
363
|
-
$og << self
|
364
|
-
return self
|
365
|
-
end
|
366
|
-
alias_method :save!, :save
|
367
|
-
|
368
|
-
def update_properties(updatesql)
|
369
|
-
$og.pupdate(updatesql, self.oid, #{klass})
|
370
|
-
end
|
371
|
-
alias_method :pupdate!, :update_properties
|
372
|
-
|
373
|
-
def delete!
|
374
|
-
$og.delete(@oid, #{klass})
|
375
|
-
end
|
376
|
-
end_eval
|
336
|
+
backend.eval_og_insert(klass)
|
337
|
+
backend.eval_og_update(klass)
|
338
|
+
backend.eval_og_deserialize(klass, self)
|
377
339
|
end
|
378
340
|
|
379
341
|
# Automatically wrap connection methods.
|
@@ -412,19 +374,23 @@ class Database
|
|
412
374
|
wrap_method :query, "sql"
|
413
375
|
wrap_method :exec, "sql"
|
414
376
|
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
end
|
419
|
-
|
420
|
-
def self.drop_db!(config)
|
421
|
-
backend = config[:backend] || "psql"
|
422
|
-
require "og/backends/#{backend}"
|
423
|
-
eval %{
|
424
|
-
#{backend.capitalize}Backend.drop_db(config[:database], config[:user],
|
377
|
+
class << self
|
378
|
+
def create_db!(config)
|
379
|
+
get_connection().db.create_db(config[:database], config[:user],
|
425
380
|
config[:password])
|
426
|
-
|
381
|
+
end
|
382
|
+
alias_method :create!, :create_db!
|
383
|
+
|
384
|
+
def drop_db!(config)
|
385
|
+
backend = config[:backend] || "psql"
|
386
|
+
require "og/backends/#{backend}"
|
387
|
+
eval %{
|
388
|
+
#{backend.capitalize}Backend.drop_db(config[:database], config[:user],
|
389
|
+
config[:password])
|
390
|
+
}
|
391
|
+
end
|
392
|
+
alias_method :drop!, :drop_db!
|
427
393
|
end
|
428
394
|
end
|
429
395
|
|
430
|
-
end #
|
396
|
+
end # namespace
|
data/test/tc_og.rb
CHANGED