og 0.11.0 → 0.12.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/ChangeLog CHANGED
@@ -1,5 +1,155 @@
1
+ 07-03-2005 George Moschovitis <gm@navel.gr>
2
+
3
+ * lib/og/adapters/mysql.rb: overide create_fields.
4
+
5
+ * examples/why_wiki: updated, added nice urls.
6
+
7
+ * lib/nitro/adapters/webrick.rb: use CgiUtils.parse_params and
8
+ CgiUtils.parse_cookies to be more compatible with FastiCGI, and
9
+ fix some bugs.
10
+
11
+ * examples/blog/roor/base.xsl: moved temporarily here.
12
+
13
+ * lib/xsl: deprecated.
14
+
15
+ * lib/nitro.rb: removed resolve_action_arguments option.
16
+
17
+ * examples/no_xsl_blog/*: updated.
18
+
19
+ * RELEASES.og: updated.
20
+
21
+ * RELEASES: updated.
22
+
23
+ * bin/cluster: deprecated.
24
+
25
+ * doc/LICENCE: moved from root.
26
+
27
+ * doc/AUTHORS: moved from root.
28
+
29
+ * after some fixes, tests pass again.
30
+
31
+ * test/nitro/ui/sitemap.rb: deprecated.
32
+
33
+ * lib/nitro/ui/sitemap.rb: deprecated.
34
+
35
+ * lib/nitro/controller.rb (#action_methods): better removal of pp methods,
36
+ remove Controller methods.
37
+
38
+ * lib/nitro/render.rb: no require of nitro, caused problems.
39
+
40
+ * lib/og/adapters/*: added typcast overrides to the other
41
+ adapters.
42
+
43
+ * test/og/tc_observer.rb: added tests.
44
+
45
+ 06-03-2005 George Moschovitis <gm@navel.gr>
46
+
47
+ * lib/og/meta.rb: fixed linkback to_s bug.
48
+
49
+ * test/og/tc_observer.rb: implemeted, many cases.
50
+
51
+ * lib/og.rb: added og_pre_read / og_post_read callbacks.
52
+
53
+ * lib/og/adapter.rb (#eval_lifecycle_methods): evaluate callbacks,
54
+ (#eval_og_insert): evaluate observer callbacks,
55
+ fix for class observer,
56
+ (#eval_og_update): evaluate observer callbacks,
57
+ (#eval_og_update): evaluate observer callbacks.
58
+
59
+ * lib/og/observer.rb: scrapped the STUPID rails design,
60
+ introduced an ultra cool, efficient, and ruby compatible design.
61
+ (#add_observer): accepts multiple observers.
62
+
63
+ 05-03-2005 George Moschovitis <gm@navel.gr>
64
+
65
+ * examples/blog/root/error.xhtml: click to reload.
66
+
67
+ * lib/nitro/runner.rb: added --crawl option.
68
+ added --render option.
69
+
70
+ * examples/blog/root/shader.xsl: fixed base href bug.
71
+
72
+ * lib/nitro/template.rb: #() alias, useful in xslt stylesheets.
73
+
74
+ * examples/blog/root/*: use scaffolded view_uri.
75
+
76
+ * lib/nitro/scaffold.rb: add support for routes.
77
+ :nosuffix option.
78
+
79
+ * lib/nitro/controller.rb (#action): implemented.
80
+ (#update_routes): implemented.
81
+ (ActionParam): implemented.
82
+ (ActionMeta): implemented.
83
+ (#action_method_arguments): deprecated.
84
+
85
+ 04-03-2005 George Moschovitis <gm@navel.gr>
86
+
87
+ * lib/nitro/controller.rb: introduced the concept of the action
88
+ keyword.
89
+
90
+ * lib/nitro/routing.rb: introduced,
91
+ (Router): introduced.
92
+ (#route): works.
93
+
94
+ * lib/nitro/dispatcher.rb: added routes map,
95
+ experimental rewrite support.
96
+
97
+ * lib/og/adapters/*: added support for multiple many_to_many relations.
98
+
99
+ * test/og/tc_many_to_many.rb: implemented.
100
+
101
+ * lib/og/meta.rb: accept :linkback as symbol,
102
+ added support for multiple many_to_many relations. [mneumann]
103
+
104
+ * lib/og/adapter.rb (join_table): encode a field name
105
+ to allow for multiple many_to_many relations with the same klass. [mneumann]
106
+
107
+ * lib/nitro/markup.rb: markup >, <.
108
+
109
+ * examples/blog/root/error.xhtml: Introduced and made really
110
+ useful.
111
+
112
+ * lib/nitro/render.rb (#log_error): reimplemented
113
+ to be more flexible and allow for much better error reporting.
114
+
115
+ * lib/nitro/context.rb (#out): override, to catch errors.
116
+
117
+ * lib/nitro/shaders.rb (RubyShader): use the TemplateMixin.
118
+
119
+ * RELEASES: updated.
120
+
121
+ * lib/nitro/template.rb: factored out TemplateMixin,
122
+ improved API.
123
+
124
+ 03-03-2005 George Moschovitis <gm@navel.gr>
125
+
126
+ * lib/nitro/template.rb: introduced as standalone template engine,
127
+ pass binding and buffer to store the result.
128
+
129
+ 01-03-2005 George Moschovitis <gm@navel.gr>
130
+
131
+ * lib/og/enchant.rb: COOL: generate finders for all properties,
132
+ take :unique into account when generating finders,
133
+ finders use typecast system.
134
+ find* alias for select* methods.
135
+ converted Og.db -> @@og_db.
136
+
137
+ * lib/og/adapter.rb: use :unique metadata,
138
+ introduced typecast system.
139
+
140
+ * lib/og.rb: better comments.
141
+
142
+ * test/og/tc_observer.rb: introduced.
143
+
144
+ * lib/og/observer.rb: introduced,
145
+ (Observable): implemented.
146
+
147
+ * lib/nitro/ui/select.rb: deprecated.
148
+
1
149
  28-02-2005 George Moschovitis <gm@navel.gr>
2
150
 
151
+ * --- VERSION 0.11.0 ---
152
+
3
153
  * lib/nitro/controller.rb (#action_method_arguments): implemented.
4
154
 
5
155
  * lib/nitro.rb: added resolve_action_arguments,
data/README.og CHANGED
@@ -1,7 +1,7 @@
1
- = Og 0.11.0
1
+ = Og 0.12.0
2
2
 
3
- Nitro integrates the Og (ObjectGraph) object-relational mapping
4
- library. Og provides transparent serialization of object graphs to a RDBMS
3
+ (ObjectGraph) is a powerfull object-relational mapping library. Og provides
4
+ transparent serialization of object graphs to a RDBMS
5
5
  backend. Unlike other similar libraries Og maps standard Ruby
6
6
  objects to SQL tables and not vice versa. Og provides a meta language
7
7
  to describe the relations between objects, a flexible and intuitive api
@@ -36,6 +36,7 @@ The library provides the following features:
36
36
  + Thread safety.
37
37
  + SQL transactions.
38
38
  + Lifecycle callbacks.
39
+ + Lifecycle observers.
39
40
  + Transparent support for cascading deletes for all backends.
40
41
  + Hierarchical structures (preorder traversal, materialized paths)
41
42
  + Works safely as part of a distributed application.
@@ -1,3 +1,43 @@
1
+ == Version 0.12.0 was released on 07/03/2005.
2
+
3
+ A careful blend of new features and subtle improvements
4
+ to the existing infrastructure. Some important bugs where
5
+ fixed aswell.
6
+
7
+ Most notable additions:
8
+
9
+ * Og automatically generates finders for all properties, for
10
+ even easier (and portable) querying:
11
+
12
+ class Article
13
+ property :title, :body, String
14
+ property :hits, Fixnum
15
+ property :create_time, Time
16
+ end
17
+
18
+ you get the finders:
19
+
20
+ Article.find_by_title
21
+ Article.find_by_body
22
+ Article.find_by_hits
23
+ Article.find_by_create_time
24
+
25
+ The finders take into account the unique constrain, to return
26
+ an array or just an object as needed.
27
+
28
+ * Og introduces lifecycle observers to avoid 'poluting' the model
29
+ objects with excess functionality. You can use every object
30
+ as observer (duck typing) or extend from an AR style Observer
31
+ class. The observer callbacks are precompiled in the lifecycle
32
+ methods only if defined, so the perfomance is not affected
33
+ in the general case.
34
+
35
+ * Fixed Og bug: multiple many_to_many relations with the
36
+ same target class.
37
+
38
+ * further code cleanup, improved examples and more.
39
+
40
+
1
41
  == Version 0.11.0 was released on 28/02/2005.
2
42
 
3
43
  The platform continues to evolve and now supports the
data/Rakefile CHANGED
@@ -59,7 +59,7 @@ spec = Gem::Specification.new do |s|
59
59
  s.required_ruby_version = '>= 1.8.0'
60
60
 
61
61
  s.files = FileList[
62
- 'README.og', 'RELEASES.og', 'LICENSE', 'AUTHORS', 'Rakefile', 'ChangeLog*',
62
+ 'README.og', 'RELEASES.og', 'doc/LICENSE', 'doc/AUTHORS', 'Rakefile', 'ChangeLog*',
63
63
  'install.rb',
64
64
  'examples/og/*', 'lib/glue.rb', 'lib/glue/**/*', 'lib/og/**/*', 'lib/og.rb',
65
65
  'test/*og*.rb', 'test/og/*', 'vendor/extensions/**/*'
@@ -69,7 +69,7 @@ spec = Gem::Specification.new do |s|
69
69
  s.autorequire = 'og'
70
70
 
71
71
  s.has_rdoc = true
72
- s.extra_rdoc_files = FileList['README.og', 'RELEASES.og', 'LICENSE', 'AUTHORS'].to_a
72
+ s.extra_rdoc_files = FileList['README.og', 'RELEASES.og', 'doc/LICENSE', 'doc/AUTHORS'].to_a
73
73
  s.rdoc_options << '--main' << 'README.og' << '--title' << 'Og Documentation'
74
74
  s.rdoc_options << '--all' << '--inline-source'
75
75
 
File without changes
File without changes
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 266 2005-02-28 14:50:48Z gmosx $
3
+ # $Id: og.rb 270 2005-03-07 17:52:16Z gmosx $
4
4
 
5
5
  require 'glue'
6
6
  require 'glue/logger'
@@ -15,7 +15,7 @@ require 'glue/validation'
15
15
  # Og (ObjectGraph) is an efficient, yet simple Object-Relational
16
16
  # mapping library.
17
17
  #
18
- # == Features
18
+ # === Features
19
19
  #
20
20
  # The library provides the following features:
21
21
  #
@@ -30,12 +30,13 @@ require 'glue/validation'
30
30
  # + Thread safety.
31
31
  # + SQL transactions.
32
32
  # + Lifecycle callbacks.
33
+ # + Lifecycle observers.
33
34
  # + Transparent support for cascading deletes for all backends.
34
35
  # + Hierarchical structures (preorder traversal, materialized paths)
35
36
  # + Works safely as part of distributed application.
36
37
  # + Simple implementation.
37
38
  #
38
- # == Meta language
39
+ # === Meta language
39
40
  #
40
41
  # primary_key :pid (NOT IMPLEMENTED)
41
42
  # name_key :name (NOT IMPLEMENTED)
@@ -44,13 +45,24 @@ require 'glue/validation'
44
45
  # many_to_many Role, :roles
45
46
  # sql_index :pid
46
47
  #
47
- # == Design
48
+ # === Property Metadata
49
+ #
50
+ # Og defines, reserves and uses the following property
51
+ # metadata types:
52
+ #
53
+ # [+:sql_index+]
54
+ # Create an sql index for this property.
55
+ #
56
+ # [+:unique+]
57
+ # This value of the property must be unique.
58
+ #
59
+ # [+:name_key+]
60
+ # This property is used as name-key.
61
+ #
62
+ # === Design
48
63
  #
49
64
  # Keep the main classes backend agnostic.
50
- #--
51
- # Try to make the methods work with oids. Do NOT implement descendants
52
- # use a root id (rid).
53
- #++
65
+ #
54
66
  # For class ids we use the name instead of a hash. Class ids are
55
67
  # typically not used in querys, they are stored for completeness.
56
68
  # If we store a hash we cannot reclaim the class thus invalidating
@@ -68,8 +80,10 @@ require 'glue/validation'
68
80
  # The og.xxx methods are more flexible and allow you to use
69
81
  # multiple databases for example.
70
82
  #
71
- # == Managed Objects Lifecycle Callbacks
83
+ # === Managed Objects Lifecycle Callbacks
72
84
  #
85
+ # * og_pre_read
86
+ # * og_post_read
73
87
  # * og_pre_insert
74
88
  # * og_post_insert
75
89
  # * og_pre_update
@@ -81,7 +95,7 @@ require 'glue/validation'
81
95
  # A class level callback is used for delete because typically you call
82
96
  # delete with an oid and not an object to avoid a deserialization.
83
97
  #
84
- # == Future
98
+ # === Future
85
99
  #
86
100
  # * Support prepared statements (pgsql)
87
101
  # * Support stored procedures (pgsql)
@@ -97,7 +111,7 @@ module Og
97
111
 
98
112
  # The version.
99
113
 
100
- Version = '0.11.0'
114
+ Version = '0.12.0'
101
115
 
102
116
  # Library path.
103
117
 
@@ -1,6 +1,6 @@
1
1
  # * George Moschovitis <gm@navel.gr>
2
2
  # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id: adapter.rb 266 2005-02-28 14:50:48Z gmosx $
3
+ # $Id: adapter.rb 270 2005-03-07 17:52:16Z gmosx $
4
4
 
5
5
  require 'yaml'
6
6
  require 'singleton'
@@ -20,6 +20,11 @@ class Adapter
20
20
  # A mapping between Ruby and backend Datastore types.
21
21
 
22
22
  attr_accessor :typemap
23
+
24
+ # A map for casting Ruby types to SQL safe textual
25
+ # representations.
26
+
27
+ attr_accessor :typecast
23
28
 
24
29
  # Lookup the adapter instance from the adapter name.
25
30
 
@@ -29,6 +34,9 @@ class Adapter
29
34
  end
30
35
 
31
36
  def initialize
37
+ # The default mappings, should be valid for most
38
+ # RDBMS.
39
+
32
40
  @typemap = {
33
41
  Integer => 'integer',
34
42
  Fixnum => 'integer',
@@ -41,6 +49,19 @@ class Adapter
41
49
  Array => 'text',
42
50
  Hash => 'text'
43
51
  }
52
+
53
+ # The :s: is a marker that will be replaced with the
54
+ # actual value to be casted. The default parameter of
55
+ # the Hash handles all other types (Object, Array, etc)
56
+
57
+ @typecast = Hash.new("'#\{#{self.class}.escape(:s:.to_yaml)\}'").update(
58
+ Integer => "\#\{:s:\}",
59
+ Float => "\#\{:s:\}",
60
+ String => "'#\{#{self.class}.escape(:s:)\}'",
61
+ Time => "'#\{#{self.class}.timestamp(:s:)\}'",
62
+ Date => "'#\{#{self.class}.date(:s:)\}'",
63
+ TrueClass => "#\{:s: ? \"'t'\" : 'NULL' \}"
64
+ )
44
65
  end
45
66
 
46
67
  # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -105,7 +126,7 @@ class Adapter
105
126
  # Create a new connection to the backend.
106
127
 
107
128
  def new_connection(db)
108
- return Og::Connection.new(db)
129
+ return Connection.new(db)
109
130
  end
110
131
 
111
132
  # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -145,8 +166,8 @@ class Adapter
145
166
  # You may want to override this method to map an existing
146
167
  # database schema using Og.
147
168
 
148
- def self.join_table(klass1, klass2)
149
- "og_#{Og.table_prefix}j_#{encode(klass1)}_#{encode(klass2)}"
169
+ def self.join_table(klass1, klass2, field)
170
+ "og_#{Og.table_prefix}j_#{encode(klass1)}_#{encode(klass2)}_#{field}"
150
171
  end
151
172
 
152
173
  # Return an sql string evaluator for the property.
@@ -222,7 +243,10 @@ class Adapter
222
243
  if default = p.meta[:default]
223
244
  field << " DEFAULT #{default.inspect} NOT NULL"
224
245
  end
225
-
246
+
247
+ # set unique
248
+ field << " UNIQUE" if p.meta[:unique]
249
+
226
250
  # attach extra sql
227
251
  if extra_sql = p.meta[:extra_sql]
228
252
  field << " #{extra_sql}"
@@ -266,9 +290,19 @@ class Adapter
266
290
  end
267
291
 
268
292
  # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
269
- # :section: Managed object enchant methods
293
+ # :section: Precompile lifecycle methods.
270
294
  # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
271
295
 
296
+ # Precompile some code that gets executed all the time.
297
+ # Deletion code is not precompiled, because it is not used
298
+ # as frequently.
299
+
300
+ def eval_lifecycle_methods(klass, db)
301
+ eval_og_insert(klass, db)
302
+ eval_og_update(klass, db)
303
+ eval_og_read(klass, db)
304
+ end
305
+
272
306
  # Generate the property for oid.
273
307
 
274
308
  def eval_og_oid(klass)
@@ -281,6 +315,9 @@ class Adapter
281
315
  # The generated code sets the oid when inserting!
282
316
 
283
317
  def eval_og_insert(klass, db)
318
+
319
+ # Attach object callbacks.
320
+
284
321
  if klass.instance_methods.include?('og_pre_insert')
285
322
  pre_cb = 'og_pre_insert(conn);'
286
323
  else
@@ -300,7 +337,36 @@ class Adapter
300
337
  if klass.instance_methods.include?('og_post_insert_update')
301
338
  post_cb << 'og_post_insert_update(conn);'
302
339
  end
303
-
340
+
341
+ # Attach observers.
342
+
343
+ if observers = klass.__meta[:og_observers]
344
+ observers.each_with_index do |o, idx|
345
+ if o.is_a?(Class)
346
+ obs = "#{o}.instance"
347
+ o = o.instance
348
+ else
349
+ obs = "self.class.__meta[:og_observers][#{idx}]"
350
+ end
351
+
352
+ if o.respond_to?(:og_pre_insert)
353
+ pre_cb << "#{obs}.og_pre_insert(conn, self);"
354
+ end
355
+
356
+ if o.respond_to?(:og_post_insert)
357
+ post_cb << "#{obs}.og_post_insert(conn, self);"
358
+ end
359
+
360
+ if o.respond_to?(:og_pre_insert_update)
361
+ pre_cb << "#{obs}.og_pre_insert_update(conn, self);"
362
+ end
363
+
364
+ if o.respond_to?(:og_post_insert_update)
365
+ post_cb << "#{obs}.og_post_insert_update(conn, self);"
366
+ end
367
+ end
368
+ end
369
+
304
370
  klass.class_eval %{
305
371
  def og_insert(conn)
306
372
  #{insert_code(klass, db, pre_cb, post_cb)}
@@ -320,6 +386,8 @@ class Adapter
320
386
 
321
387
  sql = "UPDATE #{klass::DBTABLE} SET #{updates.join(', ')} WHERE oid=#\{@oid\}"
322
388
 
389
+ # Attach object callbacks.
390
+
323
391
  if klass.instance_methods.include?('og_pre_update')
324
392
  pre_cb = 'og_pre_update(conn);'
325
393
  else
@@ -340,6 +408,35 @@ class Adapter
340
408
  post_cb << 'og_post_insert_update(conn);'
341
409
  end
342
410
 
411
+ # Attach observers.
412
+
413
+ if observers = klass.__meta[:og_observers]
414
+ observers.each_with_index do |o, idx|
415
+ if o.is_a?(Class)
416
+ obs = "#{o}.instance"
417
+ o = o.instance
418
+ else
419
+ obs = "self.class.__meta[:og_observers][#{idx}]"
420
+ end
421
+
422
+ if o.respond_to?(:og_pre_update)
423
+ pre_cb << "#{obs}.og_pre_update(conn, self);"
424
+ end
425
+
426
+ if o.respond_to?(:og_post_update)
427
+ post_cb << "#{obs}.og_post_update(conn, self);"
428
+ end
429
+
430
+ if o.respond_to?(:og_pre_insert_update)
431
+ pre_cb << "#{obs}.og_pre_insert_update(conn, self);"
432
+ end
433
+
434
+ if o.respond_to?(:og_post_insert_update)
435
+ post_cb << "#{obs}.og_post_insert_update(conn, self);"
436
+ end
437
+ end
438
+ end
439
+
343
440
  klass.class_eval %{
344
441
  def og_update(conn)
345
442
  #{pre_cb}
@@ -367,9 +464,46 @@ class Adapter
367
464
  end
368
465
  end
369
466
 
467
+ # Attach object callbacks.
468
+
469
+ if klass.instance_methods.include?('og_pre_read')
470
+ pre_cb = 'og_pre_read(conn);'
471
+ else
472
+ pre_cb = ''
473
+ end
474
+
475
+ if klass.instance_methods.include?('og_post_read')
476
+ post_cb = 'og_post_read(conn);'
477
+ else
478
+ post_cb = ''
479
+ end
480
+
481
+ # Attach observers.
482
+
483
+ if observers = klass.__meta[:og_observers]
484
+ observers.each_with_index do |o, idx|
485
+ if o.is_a?(Class)
486
+ obs = "#{o}.instance"
487
+ o = o.instance
488
+ else
489
+ obs = "self.class.__meta[:og_observers][#{idx}]"
490
+ end
491
+
492
+ if o.respond_to?(:og_pre_read)
493
+ pre_cb << "#{obs}.og_pre_read(conn, self);"
494
+ end
495
+
496
+ if o.respond_to?(:og_post_read)
497
+ post_cb << "#{obs}.og_post_read(conn, self);"
498
+ end
499
+ end
500
+ end
501
+
370
502
  klass.class_eval %{
371
503
  def og_read(res, tuple = nil)
504
+ #{pre_cb}
372
505
  #{code.join('; ')}
506
+ #{post_cb}
373
507
  end
374
508
  }
375
509
  end