og 0.8.0 → 0.9.3

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.
@@ -4,7 +4,7 @@
4
4
  # * Elias Karakoulakis <ekarak@ktismata.com>
5
5
  #
6
6
  # (c) 2004 Navel, all rights reserved.
7
- # $Id: string.rb 165 2004-11-18 12:04:04Z gmosx $
7
+ # $Id: string.rb 202 2005-01-17 10:44:13Z gmosx $
8
8
 
9
9
  require "uri"
10
10
 
@@ -2,7 +2,7 @@
2
2
  # * George Moschovitis <gm@navel.gr>
3
3
  #
4
4
  # (c) 2004 Navel, all rights reserved.
5
- # $Id: time.rb 167 2004-11-23 14:03:10Z gmosx $
5
+ # $Id: time.rb 202 2005-01-17 10:44:13Z gmosx $
6
6
 
7
7
  require "time.rb"
8
8
 
@@ -216,7 +216,7 @@ module Validation
216
216
 
217
217
  for name in params
218
218
  confirm_name = "#{name}#{c[:postfix]}"
219
- attr_accessor :"#{confirm_name}"
219
+ eval "attr_accessor :#{confirm_name}"
220
220
 
221
221
  code = %{
222
222
  if obj.#{confirm_name}.nil? or (obj.#{confirm_name} != obj.#{name})
data/lib/og.rb CHANGED
@@ -1,18 +1,15 @@
1
- # code:
2
1
  # * George Moschovitis <gm@navel.gr>
3
- #
4
- # (c) 2004 Navel, all rights reserved.
5
- # $Id: og.rb 197 2004-12-21 13:50:17Z gmosx $
2
+ # (c) 2004-2005 Navel, all rights reserved.
3
+ # $Id: og.rb 248 2005-01-31 13:38:34Z gmosx $
6
4
 
7
5
  require 'glue/logger'
6
+ require 'glue/attribute'
8
7
  require 'glue/property'
9
8
  require 'glue/array'
10
9
  require 'glue/hash'
11
10
  require 'glue/time'
12
11
  require 'glue/pool'
13
12
 
14
- # = Og
15
- #
16
13
  # Og (ObjectGraph) is an efficient, yet simple Object-Relational
17
14
  # mapping library.
18
15
  #
@@ -36,7 +33,7 @@ require 'glue/pool'
36
33
  # + Works safely as part of distributed application.
37
34
  # + Simple implementation.
38
35
  #
39
- # === Meta language
36
+ # == Meta language
40
37
  #
41
38
  # primary_key :pid (NOT IMPLEMENTED)
42
39
  # name_key :name (NOT IMPLEMENTED)
@@ -45,7 +42,7 @@ require 'glue/pool'
45
42
  # many_to_many Role, :roles
46
43
  # sql_index :pid
47
44
  #
48
- # === Design
45
+ # == Design
49
46
  #
50
47
  # Keep the main classes backend agnostic.
51
48
  #--
@@ -69,7 +66,7 @@ require 'glue/pool'
69
66
  # The og.xxx methods are more flexible and allow you to use
70
67
  # multiple databases for example.
71
68
  #
72
- # === Managed Objects Lifecycle Callbacks
69
+ # == Managed Objects Lifecycle Callbacks
73
70
  #
74
71
  # * og_pre_insert
75
72
  # * og_post_insert
@@ -82,53 +79,58 @@ require 'glue/pool'
82
79
  # A class level callback is used for delete because typically you call
83
80
  # delete with an oid and not an object to avoid a deserialization.
84
81
  #
85
- # === Future
82
+ # == Future
86
83
  #
87
84
  # * Support prepared statements (pgsql)
88
85
  # * Support stored procedures (pgsql)
89
86
  # * Support caching.
90
87
  # * Deserialize to OpenStruct.
91
88
  # * Better documentation.
92
- #
89
+
93
90
  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
107
91
 
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
92
+ # If true, only allow reading from the database. Usefull
93
+ # for maintainance.
94
+
95
+ cattr_accessor :read_only_mode, false
96
+
97
+ # If true, the library automatically 'enchants' managed classes.
98
+ # In enchant mode, special db aware methods are added to
99
+ # managed classes and instances.
100
+
101
+ cattr_accessor :enchant_managed_classes, true
102
+
103
+ # If true, use Ruby's advanced introspection capabilities to
104
+ # automatically manage classes tha define properties.
105
+
106
+ cattr_accessor :auto_manage_classes, true
107
+
108
+ # If true, automatically include the Og meta-language into Module.
109
+ #
110
+ # By default this is FALSE, to avoid polution of the Module object.
111
+ # However if you include a prop_accessor or a managed Mixin in your
112
+ # object MetaLanguage gets automatically extended in the class.
113
+
114
+ cattr_accessor :include_meta_language, true
115
+
116
+ # Attach the following prefix to all generated SQL table names.
117
+ # Usefull on hosting scenarios where you have to run multiple
118
+ # web applications/sites on a single database.
125
119
 
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
120
+ cattr_accessor :table_prefix, nil
121
+
122
+ # The active database. Og allows you to access multiple
123
+ # databases from a single application.
124
+
125
+ cattr_accessor :db
126
+
127
+ # Set the active database.
128
+
129
+ def self.use(db)
130
+ @@db = db
131
+ @@db.get_connection
132
+ end
133
+
132
134
  end
133
135
 
134
136
  # gmosx: leave this here.
@@ -137,22 +139,18 @@ require 'og/meta'
137
139
 
138
140
  class Og
139
141
 
140
- # = Unmanageable
141
- #
142
142
  # Marker module. If included this in a class, the Og automanager
143
143
  # ignores this class.
144
- #
144
+
145
145
  module Unmanageable; end
146
146
 
147
- # = Database
148
- #
149
147
  # Encapsulates an Og Database.
150
- #
148
+
151
149
  class Database
152
150
  include Og::Enchant
153
151
 
154
152
  # Managed class metadata
155
- #
153
+
156
154
  class ManagedClassMeta
157
155
  # The managed class.
158
156
  attr_accessor :klass
@@ -167,16 +165,19 @@ class Database
167
165
  end
168
166
 
169
167
  # hash of configuration options.
168
+
170
169
  attr_accessor :config
171
170
 
172
171
  # Pool of connections to the backend.
172
+
173
173
  attr_accessor :connection_pool
174
174
 
175
175
  # Managed classes.
176
+
176
177
  attr_accessor :managed_classes
177
178
 
178
179
  # Initialize the database interface.
179
- #
180
+
180
181
  def initialize(config)
181
182
  @config = config
182
183
 
@@ -199,7 +200,7 @@ class Database
199
200
 
200
201
  # gmosx, FIXME: this automanage code is not elegant and slow
201
202
  # should probably recode this, along with glue/property.rb
202
- #
203
+
203
204
  if Og.auto_manage_classes
204
205
  # automatically manage classes with properties and metadata.
205
206
  # gmosx: Any idea how to optimize this?
@@ -219,7 +220,7 @@ class Database
219
220
  end
220
221
 
221
222
  # Shutdown the database interface.
222
- #
223
+
223
224
  def shutdown
224
225
  for con in @connection_pool
225
226
  con.close()
@@ -229,7 +230,7 @@ class Database
229
230
 
230
231
  # Get a connection from the pool to access the database.
231
232
  # Stores the connection in a thread-local variable.
232
- #
233
+
233
234
  def get_connection
234
235
  thread = Thread.current
235
236
 
@@ -243,7 +244,7 @@ class Database
243
244
  alias_method :connection, :get_connection
244
245
 
245
246
  # Restore an unused connection to the pool.
246
- #
247
+
247
248
  def put_connection
248
249
  thread = Thread.current
249
250
 
@@ -254,7 +255,7 @@ class Database
254
255
  end
255
256
 
256
257
  # Utility method, automatically restores a connection to the pool.
257
- #
258
+
258
259
  def connect(deserialize = nil, &block)
259
260
  result = nil
260
261
 
@@ -275,7 +276,7 @@ class Database
275
276
 
276
277
 
277
278
  # Register a standard Ruby class as managed.
278
- #
279
+
279
280
  def manage(klass)
280
281
  return if managed?(klass) or klass.ancestors.include?(Og::Unmanageable)
281
282
 
@@ -289,7 +290,7 @@ class Database
289
290
  end
290
291
 
291
292
  # Helper method to set multiple managed classes.
292
- #
293
+
293
294
  def manage_classes(*klasses)
294
295
  for klass in klasses
295
296
  manage(klass)
@@ -297,7 +298,7 @@ class Database
297
298
  end
298
299
 
299
300
  # Stop managing a Ruby class
300
- #
301
+
301
302
  def unmanage(klass)
302
303
  @managed_classes.delete(klass)
303
304
  end
@@ -309,7 +310,7 @@ class Database
309
310
  end
310
311
 
311
312
  # Add standard og functionality to the class
312
- #
313
+
313
314
  def convert(klass)
314
315
  # Grab backend class
315
316
  backend = @config[:backend]
@@ -393,4 +394,4 @@ class Database
393
394
  end
394
395
  end
395
396
 
396
- end # namespace
397
+ end
@@ -2,7 +2,7 @@
2
2
  # * George Moschovitis <gm@navel.gr>
3
3
  #
4
4
  # (c) 2004 Navel, all rights reserved.
5
- # $Id: backend.rb 197 2004-12-21 13:50:17Z gmosx $
5
+ # $Id: backend.rb 202 2005-01-17 10:44:13Z gmosx $
6
6
 
7
7
  require "yaml"
8
8
 
@@ -1,39 +1,35 @@
1
- # code:
2
1
  # * George Moschovitis <gm@navel.gr>
3
2
  # * Elias Athanasopoulos <elathan@navel.gr>
4
- #
5
- # (c) 2004 Navel, all rights reserved.
6
- # $Id: mysql.rb 194 2004-12-20 20:23:57Z gmosx $
3
+ # (c) 2004-2005 Navel, all rights reserved.
4
+ # $Id: mysql.rb 248 2005-01-31 13:38:34Z gmosx $
7
5
 
8
- require "mysql"
6
+ require 'mysql'
9
7
 
10
- require "og/backend"
8
+ require 'og/backend'
11
9
 
12
10
  class Og
13
11
 
14
- # = MysqlBackend
15
- #
16
12
  # Implements a MySQL powered backend.
17
- #
13
+
18
14
  class MysqlBackend < Og::Backend
19
15
 
20
16
  # A mapping between Ruby and SQL types.
21
- #
17
+
22
18
  TYPEMAP = {
23
- Integer => "integer",
24
- Fixnum => "integer",
25
- Float => "float",
26
- String => "text",
27
- Time => "timestamp",
28
- Date => "date",
29
- TrueClass => "boolean",
30
- Object => "text",
31
- Array => "text",
32
- Hash => "text"
19
+ Integer => 'integer',
20
+ Fixnum => 'integer',
21
+ Float => 'float',
22
+ String => 'text',
23
+ Time => 'timestamp',
24
+ Date => 'date',
25
+ TrueClass => 'tinyint',
26
+ Object => 'text',
27
+ Array => 'text',
28
+ Hash => 'text'
33
29
  }
34
30
 
35
31
  # Intitialize the connection to the RDBMS.
36
- #
32
+
37
33
  def initialize(config)
38
34
  begin
39
35
  @conn = Mysql.connect(config[:address], config[:user],
@@ -53,7 +49,7 @@ class MysqlBackend < Og::Backend
53
49
  # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
54
50
 
55
51
  # Escape an SQL string
56
- #
52
+
57
53
  def self.escape(str)
58
54
  return nil unless str
59
55
  return Mysql.quote(str)
@@ -61,7 +57,7 @@ class MysqlBackend < Og::Backend
61
57
 
62
58
  # Convert a ruby time to an sql timestamp.
63
59
  # TODO: Optimize this
64
- #
60
+
65
61
  def self.timestamp(time = Time.now)
66
62
  return nil unless time
67
63
  return time.strftime("%Y%m%d%H%M%S")
@@ -69,7 +65,7 @@ class MysqlBackend < Og::Backend
69
65
 
70
66
  # Output YYY-mm-dd
71
67
  # TODO: Optimize this
72
- #
68
+
73
69
  def self.date(date)
74
70
  return nil unless date
75
71
  return "#{date.year}-#{date.month}-#{date.mday}"
@@ -77,14 +73,14 @@ class MysqlBackend < Og::Backend
77
73
 
78
74
  # Parse sql datetime
79
75
  # TODO: Optimize this
80
- #
76
+
81
77
  def self.parse_timestamp(str)
82
78
  return Time.parse(str)
83
79
  end
84
80
 
85
81
  # Input YYYY-mm-dd
86
82
  # TODO: Optimize this
87
- #
83
+
88
84
  def self.parse_date(str)
89
85
  return nil unless str
90
86
  return Date.strptime(str)
@@ -96,7 +92,7 @@ class MysqlBackend < Og::Backend
96
92
  # portable.
97
93
  #
98
94
  # FIXME: add extra handling for float.
99
- #
95
+
100
96
  def self.write_prop(p)
101
97
  if p.klass.ancestors.include?(Integer)
102
98
  return "#\{@#{p.symbol} || 'NULL'\}"
@@ -109,7 +105,7 @@ class MysqlBackend < Og::Backend
109
105
  elsif p.klass.ancestors.include?(Date)
110
106
  return %|#\{@#{p.symbol} ? "'#\{Og::MysqlBackend.date(@#{p.symbol})\}'" : 'NULL'\}|
111
107
  elsif p.klass.ancestors.include?(TrueClass)
112
- return "#\{@#{p.symbol} || 'NULL'\}"
108
+ return "#\{@#{p.symbol} ? 1 : 0 \}"
113
109
  else
114
110
  return %|#\{@#{p.symbol} ? "'#\{Og::MysqlBackend.escape(@#{p.symbol}.to_yaml)\}'" : "''"\}|
115
111
  end
@@ -117,7 +113,7 @@ class MysqlBackend < Og::Backend
117
113
 
118
114
  # Return an evaluator for reading the property.
119
115
  # No need to optimize this, used only to precalculate code.
120
- #
116
+
121
117
  def self.read_prop(p, idx)
122
118
  if p.klass.ancestors.include?(Integer)
123
119
  return "res[#{idx}].to_i()"
@@ -130,7 +126,7 @@ class MysqlBackend < Og::Backend
130
126
  elsif p.klass.ancestors.include?(Date)
131
127
  return "Og::MysqlBackend.parse_date(res[#{idx}])"
132
128
  elsif p.klass.ancestors.include?(TrueClass)
133
- return "('true' == res[#{idx}])"
129
+ return "('0' != res[#{idx}])"
134
130
  else
135
131
  return "YAML::load(res[#{idx}])"
136
132
  end
@@ -139,14 +135,14 @@ class MysqlBackend < Og::Backend
139
135
  # Returns the props that will be included in the insert query.
140
136
  # The oid property is rejected because it is mapped to an
141
137
  # AUTO_INCREMENT column.
142
- #
138
+
143
139
  def self.props_for_insert(klass)
144
140
  klass.__props.reject { |p| :oid == p.symbol }
145
141
  end
146
142
 
147
- # Returns the code that actually inserts the object into the
143
+ # Returns the code that actually inserts the object into the
148
144
  # database. Returns the code as String.
149
- #
145
+
150
146
  def self.insert_code(klass, sql, pre_cb, post_cb)
151
147
  %{
152
148
  #{pre_cb}
@@ -158,7 +154,7 @@ class MysqlBackend < Og::Backend
158
154
 
159
155
  # generate the mapping of the database fields to the
160
156
  # object properties.
161
- #
157
+
162
158
  def self.calc_field_index(klass, og)
163
159
  res = og.query "SELECT * FROM #{klass::DBTABLE} LIMIT 1"
164
160
  meta = og.managed_classes[klass]
@@ -168,8 +164,8 @@ class MysqlBackend < Og::Backend
168
164
  end
169
165
  end
170
166
 
171
- # Generate the property for oid
172
- #
167
+ # Generate the property for oid.
168
+
173
169
  def self.eval_og_oid(klass)
174
170
  klass.class_eval %{
175
171
  prop_accessor :oid, Fixnum, :sql => "integer AUTO_INCREMENT PRIMARY KEY"
@@ -181,28 +177,28 @@ class MysqlBackend < Og::Backend
181
177
  # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
182
178
 
183
179
  # Create the database.
184
- #
180
+
185
181
  def self.create_db(database, user = nil, password = nil)
186
182
  Logger.info "Creating database '#{database}'."
187
183
  `mysqladmin -f --user=#{user} --password=#{password} create #{database}`
188
184
  end
189
185
 
190
186
  # Drop the database.
191
- #
187
+
192
188
  def self.drop_db(database, user = nil, password = nil)
193
189
  Logger.info "Dropping database '#{database}'."
194
190
  `mysqladmin -f --user=#{user} --password=#{password} drop #{database}`
195
191
  end
196
192
 
197
193
  # Execute an SQL query and return the result
198
- #
194
+
199
195
  def query(sql)
200
196
  Logger.debug sql if $DBG
201
197
  return @conn.query(sql)
202
198
  end
203
199
 
204
200
  # Execute an SQL query, no result returned.
205
- #
201
+
206
202
  def exec(sql)
207
203
  Logger.debug sql if $DBG
208
204
  @conn.query(sql)
@@ -210,7 +206,7 @@ class MysqlBackend < Og::Backend
210
206
 
211
207
  # Execute an SQL query and return the result. Wrapped in a rescue
212
208
  # block.
213
- #
209
+
214
210
  def safe_query(sql)
215
211
  Logger.debug sql if $DBG
216
212
  begin
@@ -224,7 +220,7 @@ class MysqlBackend < Og::Backend
224
220
 
225
221
  # Execute an SQL query, no result returned. Wrapped in a rescue
226
222
  # block.
227
- #
223
+
228
224
  def safe_exec(sql)
229
225
  Logger.debug sql if $DBG
230
226
  begin
@@ -236,25 +232,25 @@ class MysqlBackend < Og::Backend
236
232
  end
237
233
 
238
234
  # Check if it is a valid resultset.
239
- #
235
+
240
236
  def valid?(res)
241
237
  return !(res.nil? or 0 == res.num_rows)
242
238
  end
243
239
 
244
240
  # Start a new transaction.
245
- #
241
+
246
242
  def start
247
243
  # no transaction support
248
244
  end
249
245
 
250
246
  # Commit a transaction.
251
- #
247
+
252
248
  def commit
253
249
  # no transaction support
254
250
  end
255
251
 
256
252
  # Rollback transaction.
257
- #
253
+
258
254
  def rollback
259
255
  # no transaction support
260
256
  end
@@ -262,7 +258,7 @@ class MysqlBackend < Og::Backend
262
258
  # Create the managed object table. The properties of the
263
259
  # object are mapped to the table columns. Additional sql relations
264
260
  # and constrains are created (indicices, sequences, etc).
265
- #
261
+
266
262
  def create_table(klass)
267
263
  fields = create_fields(klass, TYPEMAP)
268
264
 
@@ -328,7 +324,7 @@ class MysqlBackend < Og::Backend
328
324
  end
329
325
 
330
326
  # Deserialize one row of the resultset.
331
- #
327
+
332
328
  def deserialize_one(res, klass)
333
329
  return nil unless valid?(res)
334
330
 
@@ -343,9 +339,9 @@ class MysqlBackend < Og::Backend
343
339
  end
344
340
 
345
341
  # Deserialize all rows of the resultset.
346
- #
342
+
347
343
  def deserialize_all(res, klass)
348
- return nil unless valid?(res)
344
+ return [] unless valid?(res)
349
345
 
350
346
  entities = []
351
347
 
@@ -364,11 +360,11 @@ class MysqlBackend < Og::Backend
364
360
  end
365
361
 
366
362
  # Return a single integer value from the resultset.
367
- #
363
+
368
364
  def get_int(res, idx = 0)
369
365
  return res.fetch_row[idx].to_i
370
366
  end
371
367
 
372
368
  end
373
369
 
374
- end # module
370
+ end