og 0.11.0 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
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