nitro 0.12.0 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (193) hide show
  1. data/{ChangeLog → CHANGELOG} +137 -0
  2. data/INSTALL +1 -2
  3. data/README +1 -1
  4. data/Rakefile +10 -61
  5. data/benchmark/{nitro/bench.rb → bench.rb} +1 -1
  6. data/benchmark/{nitro/simple-webrick-n-200.txt → simple-webrick-n-200.txt} +0 -0
  7. data/benchmark/{nitro/static-webrick-n-200.txt → static-webrick-n-200.txt} +0 -0
  8. data/benchmark/{nitro/tiny-lhttpd-n-200-c-5.txt → tiny-lhttpd-n-200-c-5.txt} +0 -0
  9. data/benchmark/{nitro/tiny-webrick-n-200-c-5.txt → tiny-webrick-n-200-c-5.txt} +0 -0
  10. data/benchmark/{nitro/tiny-webrick-n-200.txt → tiny-webrick-n-200.txt} +0 -0
  11. data/benchmark/{nitro/tiny2-webrick-n-200.txt → tiny2-webrick-n-200.txt} +0 -0
  12. data/doc/{ChangeLog.1 → CHANGELOG.1} +0 -0
  13. data/{RELEASES → doc/RELEASES} +46 -0
  14. data/doc/faq.txt +7 -0
  15. data/examples/README.windows +1 -1
  16. data/examples/ajax/controller.rb +21 -0
  17. data/examples/ajax/public/index.xhtml +70 -0
  18. data/examples/ajax/public/js/ajax.js +64 -0
  19. data/examples/ajax/run.rb +16 -0
  20. data/examples/blog/README +6 -3
  21. data/examples/blog/conf/apache.conf +2 -2
  22. data/examples/blog/conf/lhttpd.conf +2 -2
  23. data/examples/blog/log/apache.error_log +777 -0
  24. data/examples/blog/{root → public}/base.xsl +0 -0
  25. data/examples/blog/{root → public}/fcgi.rb +0 -0
  26. data/examples/blog/{root → public}/m/bubbles.gif +0 -0
  27. data/examples/blog/{root → public}/m/comments_curve.gif +0 -0
  28. data/examples/blog/{root → public}/m/down.gif +0 -0
  29. data/examples/blog/{root → public}/m/footer_bg.gif +0 -0
  30. data/examples/blog/{root → public}/m/garrow.gif +0 -0
  31. data/examples/blog/{root → public}/m/gbull.gif +0 -0
  32. data/examples/blog/{root → public}/m/grbull.gif +0 -0
  33. data/examples/blog/{root → public}/m/h1_bg.gif +0 -0
  34. data/examples/blog/{root → public}/m/header_bg.gif +0 -0
  35. data/examples/blog/{root → public}/m/nitro.gif +0 -0
  36. data/examples/blog/{root → public}/m/obull.gif +0 -0
  37. data/examples/blog/{root → public}/m/page_bg.gif +0 -0
  38. data/examples/blog/{root → public}/m/rss.gif +0 -0
  39. data/examples/blog/{root → public}/m/side_title_bg.gif +0 -0
  40. data/examples/blog/{root → public}/m/sidebar_bg.gif +0 -0
  41. data/examples/{no_xsl_blog/root → blog/public}/style.css +6 -0
  42. data/examples/blog/run.rb +10 -12
  43. data/examples/blog/{lib → src}/blog.rb +3 -3
  44. data/examples/blog/{lib/blog → src}/controller.rb +13 -2
  45. data/examples/blog/src/mailer.rb +23 -0
  46. data/examples/blog/{lib/blog/model.rb → src/models/blog.rb} +4 -7
  47. data/examples/blog/src/models/content.rb +52 -0
  48. data/examples/blog/src/views/blog_entry_email.xhtml +16 -0
  49. data/examples/blog/{root → src/views}/comments.xhtml +0 -0
  50. data/examples/blog/{root → src/views}/entry_form.xhtml +0 -0
  51. data/examples/blog/{root → src/views}/error.xhtml +0 -0
  52. data/examples/blog/{root → src/views}/index.xhtml +0 -0
  53. data/examples/blog/{root → src/views}/login.xhtml +0 -0
  54. data/examples/blog/{root → src/views}/recent_posts.xhtml +0 -0
  55. data/examples/blog/{root → src/views}/view_entry.xhtml +8 -0
  56. data/examples/blog/{root → src/views}/view_entry.xml +0 -0
  57. data/examples/blog/src/xsl/base.xsl +153 -0
  58. data/examples/blog/{root → src/xsl}/style.xsl +2 -2
  59. data/examples/no_xsl_blog/README +5 -1
  60. data/examples/no_xsl_blog/conf/apache.conf +2 -2
  61. data/examples/no_xsl_blog/conf/lhttpd.conf +2 -2
  62. data/examples/no_xsl_blog/lib/blog/model.rb +1 -1
  63. data/{lib/parts → examples/no_xsl_blog/lib}/content.rb +1 -11
  64. data/examples/no_xsl_blog/log/apache.error_log +405 -0
  65. data/examples/no_xsl_blog/{root → public}/comments.xhtml +0 -0
  66. data/examples/no_xsl_blog/{root → public}/entry_form.xhtml +0 -0
  67. data/examples/no_xsl_blog/{root → public}/fcgi.rb +0 -0
  68. data/examples/no_xsl_blog/{root → public}/index.xhtml +0 -0
  69. data/examples/no_xsl_blog/{root → public}/login.xhtml +0 -0
  70. data/examples/no_xsl_blog/{root → public}/m/bubbles.gif +0 -0
  71. data/examples/no_xsl_blog/{root → public}/m/comments_curve.gif +0 -0
  72. data/examples/no_xsl_blog/{root → public}/m/down.gif +0 -0
  73. data/examples/no_xsl_blog/{root → public}/m/footer_bg.gif +0 -0
  74. data/examples/no_xsl_blog/{root → public}/m/garrow.gif +0 -0
  75. data/examples/no_xsl_blog/{root → public}/m/gbull.gif +0 -0
  76. data/examples/no_xsl_blog/{root → public}/m/grbull.gif +0 -0
  77. data/examples/no_xsl_blog/{root → public}/m/h1_bg.gif +0 -0
  78. data/examples/no_xsl_blog/{root → public}/m/header_bg.gif +0 -0
  79. data/examples/no_xsl_blog/{root → public}/m/nitro.gif +0 -0
  80. data/examples/no_xsl_blog/{root → public}/m/obull.gif +0 -0
  81. data/examples/no_xsl_blog/{root → public}/m/page_bg.gif +0 -0
  82. data/examples/no_xsl_blog/{root → public}/m/rss.gif +0 -0
  83. data/examples/no_xsl_blog/{root → public}/m/side_title_bg.gif +0 -0
  84. data/examples/no_xsl_blog/{root → public}/m/sidebar_bg.gif +0 -0
  85. data/examples/no_xsl_blog/{root → public}/recent_posts.xhtml +0 -0
  86. data/examples/{blog/root → no_xsl_blog/public}/style.css +0 -0
  87. data/examples/no_xsl_blog/{root → public}/view_entry.xhtml +0 -0
  88. data/examples/no_xsl_blog/{root → public}/view_entry.xml +0 -0
  89. data/examples/tiny/conf/apache.conf +2 -2
  90. data/examples/tiny/log/apache.error_log +100 -0
  91. data/examples/tiny/{root → public}/fcgi.rb +0 -0
  92. data/examples/tiny/{root → public}/include.xhtml +0 -0
  93. data/examples/tiny/{root → public}/index.xhtml +0 -0
  94. data/{bin/proto/root/m → examples/tiny/public}/nitro.png +0 -0
  95. data/examples/tiny/{root → public}/upload.xhtml +0 -0
  96. data/examples/tiny/run.rb +1 -2
  97. data/examples/why_wiki/wiki.yml +1 -0
  98. data/install.rb +5 -2
  99. data/lib/nitro.rb +2 -6
  100. data/lib/nitro/adapters/fastcgi.rb +2 -2
  101. data/lib/nitro/adapters/webrick.rb +4 -4
  102. data/lib/nitro/conf.rb +5 -2
  103. data/lib/nitro/controller.rb +2 -2
  104. data/lib/nitro/dispatcher.rb +19 -8
  105. data/lib/nitro/mail.rb +252 -8
  106. data/lib/nitro/render.rb +24 -21
  107. data/lib/nitro/runner.rb +1 -1
  108. data/lib/nitro/scaffold.rb +2 -5
  109. data/lib/nitro/simple.rb +2 -1
  110. data/lib/nitro/template.rb +42 -2
  111. data/test/nitro/tc_controller.rb +9 -4
  112. data/test/nitro/tc_dispatcher.rb +4 -6
  113. data/test/nitro/tc_mail.rb +95 -0
  114. data/test/{root → public}/blog/list.xhtml +0 -0
  115. data/test/public/dummy_mailer/registration.xhtml +5 -0
  116. data/vendor/README +0 -1
  117. metadata +136 -181
  118. data/benchmark/og/bench.rb +0 -75
  119. data/benchmark/og/sqlite-no-prepare.1.txt +0 -13
  120. data/benchmark/og/sqlite-no-prepare.2.txt +0 -13
  121. data/benchmark/og/sqlite-prepare.1.txt +0 -13
  122. data/benchmark/og/sqlite-prepare.2.txt +0 -13
  123. data/bin/proto/README +0 -34
  124. data/bin/proto/conf/apache.conf +0 -1
  125. data/bin/proto/conf/app.conf.rb +0 -14
  126. data/bin/proto/conf/lhttpd.conf +0 -236
  127. data/bin/proto/ctl +0 -4
  128. data/bin/proto/lib/README +0 -5
  129. data/bin/proto/log/README +0 -3
  130. data/bin/proto/root/fcgi.rb +0 -6
  131. data/bin/proto/root/index.xhtml +0 -69
  132. data/bin/proto/root/style.css +0 -152
  133. data/bin/proto/root/style.xsl +0 -99
  134. data/doc/og_config.txt +0 -35
  135. data/doc/og_tutorial.txt +0 -595
  136. data/examples/og/README +0 -11
  137. data/examples/og/mock_example.rb +0 -50
  138. data/examples/og/mysql_to_psql.rb +0 -96
  139. data/examples/og/run.rb +0 -286
  140. data/examples/tiny/root/nitro.png +0 -0
  141. data/lib/glue.rb +0 -55
  142. data/lib/glue/array.rb +0 -61
  143. data/lib/glue/attribute.rb +0 -83
  144. data/lib/glue/cache.rb +0 -138
  145. data/lib/glue/flexob.rb +0 -12
  146. data/lib/glue/hash.rb +0 -122
  147. data/lib/glue/inflector.rb +0 -91
  148. data/lib/glue/logger.rb +0 -147
  149. data/lib/glue/misc.rb +0 -14
  150. data/lib/glue/mixins.rb +0 -36
  151. data/lib/glue/number.rb +0 -24
  152. data/lib/glue/object.rb +0 -32
  153. data/lib/glue/pool.rb +0 -60
  154. data/lib/glue/property.rb +0 -408
  155. data/lib/glue/string.rb +0 -162
  156. data/lib/glue/time.rb +0 -85
  157. data/lib/glue/validation.rb +0 -394
  158. data/lib/og.rb +0 -185
  159. data/lib/og/adapter.rb +0 -513
  160. data/lib/og/adapters/filesys.rb +0 -121
  161. data/lib/og/adapters/mysql.rb +0 -347
  162. data/lib/og/adapters/oracle.rb +0 -375
  163. data/lib/og/adapters/psql.rb +0 -273
  164. data/lib/og/adapters/sqlite.rb +0 -262
  165. data/lib/og/backend.rb +0 -297
  166. data/lib/og/connection.rb +0 -304
  167. data/lib/og/database.rb +0 -282
  168. data/lib/og/enchant.rb +0 -125
  169. data/lib/og/meta.rb +0 -373
  170. data/lib/og/mock.rb +0 -165
  171. data/lib/og/observer.rb +0 -53
  172. data/lib/og/typemacros.rb +0 -23
  173. data/lib/parts/README +0 -9
  174. data/test/glue/tc_attribute.rb +0 -22
  175. data/test/glue/tc_cache.rb +0 -45
  176. data/test/glue/tc_hash.rb +0 -38
  177. data/test/glue/tc_logger.rb +0 -39
  178. data/test/glue/tc_numbers.rb +0 -20
  179. data/test/glue/tc_property.rb +0 -89
  180. data/test/glue/tc_property_mixins.rb +0 -93
  181. data/test/glue/tc_property_type_checking.rb +0 -35
  182. data/test/glue/tc_strings.rb +0 -103
  183. data/test/glue/tc_validation.rb +0 -188
  184. data/test/og/tc_filesys.rb +0 -83
  185. data/test/og/tc_lifecycle.rb +0 -104
  186. data/test/og/tc_many_to_many.rb +0 -62
  187. data/test/og/tc_meta.rb +0 -55
  188. data/test/og/tc_observer.rb +0 -85
  189. data/test/og/tc_sqlite.rb +0 -87
  190. data/test/tc_og.rb +0 -355
  191. data/vendor/composite_sexp_processor.rb +0 -43
  192. data/vendor/parse_tree.rb +0 -745
  193. data/vendor/sexp_processor.rb +0 -453
data/lib/og.rb DELETED
@@ -1,185 +0,0 @@
1
- # * George Moschovitis <gm@navel.gr>
2
- # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id: og.rb 270 2005-03-07 17:52:16Z gmosx $
4
-
5
- require 'glue'
6
- require 'glue/logger'
7
- require 'glue/attribute'
8
- require 'glue/property'
9
- require 'glue/array'
10
- require 'glue/hash'
11
- require 'glue/time'
12
- require 'glue/pool'
13
- require 'glue/validation'
14
-
15
- # Og (ObjectGraph) is an efficient, yet simple Object-Relational
16
- # mapping library.
17
- #
18
- # === Features
19
- #
20
- # The library provides the following features:
21
- #
22
- # + Object-Relational mapping.
23
- # + Absolutely no configuration files.
24
- # + Multiple backends (PostgreSQL, MySQL, SQLite).
25
- # + ActiveRecord-style meta language and db aware methods.
26
- # + Deserialize to Ruby Objects.
27
- # + Deserialize sql join queries to Ruby Objects (temporarily dissabled).
28
- # + Serialize arbitrary ruby object graphs through YAML.
29
- # + Connection pooling.
30
- # + Thread safety.
31
- # + SQL transactions.
32
- # + Lifecycle callbacks.
33
- # + Lifecycle observers.
34
- # + Transparent support for cascading deletes for all backends.
35
- # + Hierarchical structures (preorder traversal, materialized paths)
36
- # + Works safely as part of distributed application.
37
- # + Simple implementation.
38
- #
39
- # === Meta language
40
- #
41
- # primary_key :pid (NOT IMPLEMENTED)
42
- # name_key :name (NOT IMPLEMENTED)
43
- # prop_accessor Fixnum, :pid, :sql => "smallint DEFAULT 1"
44
- # has_many Child, :children
45
- # many_to_many Role, :roles
46
- # sql_index :pid
47
- #
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
63
- #
64
- # Keep the main classes backend agnostic.
65
- #
66
- # For class ids we use the name instead of a hash. Class ids are
67
- # typically not used in querys, they are stored for completeness.
68
- # If we store a hash we cannot reclaim the class thus invalidating
69
- # the point. Instead of .name(), to_s() is used so the methods
70
- # are more flexible (they accept class names too!!)
71
- #
72
- # Og allows the serialization of arbitrary Ruby objects. Just
73
- # mark them as Object (or Array or Hash) in the prop_accessor
74
- # and the engine will serialize a YAML dump of the object.
75
- # Arbitrary object graphs are supported too.
76
- #
77
- # This is NOT a singleton, an application may access multiple
78
- # databases.
79
- #
80
- # The og.xxx methods are more flexible and allow you to use
81
- # multiple databases for example.
82
- #
83
- # === Managed Objects Lifecycle Callbacks
84
- #
85
- # * og_pre_read
86
- # * og_post_read
87
- # * og_pre_insert
88
- # * og_post_insert
89
- # * og_pre_update
90
- # * og_post_update
91
- # * og_pre_insert_update
92
- # * og_post_insert_update
93
- # * self.og_pre_delete
94
- #
95
- # A class level callback is used for delete because typically you call
96
- # delete with an oid and not an object to avoid a deserialization.
97
- #
98
- # === Future
99
- #
100
- # * Support prepared statements (pgsql)
101
- # * Support stored procedures (pgsql)
102
- # * Support caching.
103
- # * Deserialize to OpenStruct.
104
- # * Better documentation.
105
-
106
- module Og
107
-
108
- # The name.
109
-
110
- Name = 'ObjectGraph'
111
-
112
- # The version.
113
-
114
- Version = '0.12.0'
115
-
116
- # Library path.
117
-
118
- LibPath = File.dirname(__FILE__)
119
-
120
- # If true, only allow reading from the database. Usefull
121
- # for maintainance.
122
-
123
- mattr_accessor :read_only_mode, false
124
-
125
- # If true, the library automatically 'enchants' managed classes.
126
- # In enchant mode, special db aware methods are added to
127
- # managed classes and instances.
128
- # If false, Og enchants only classes that define properties.
129
-
130
- mattr_accessor :enchant_managed_classes, true
131
-
132
- # If true, use Ruby's advanced introspection capabilities to
133
- # automatically manage classes tha define properties.
134
-
135
- mattr_accessor :auto_manage_classes, true
136
-
137
- # If true, automatically include the Og meta-language into Module.
138
- # If false, the polution of the Module object is avoided. However
139
- # if you include a prop_accessor or a managed Mixin in your
140
- # object MetaLanguage gets automatically extended in the class.
141
-
142
- mattr_accessor :include_meta_language, true
143
-
144
- # Attach the following prefix to all generated SQL table names.
145
- # Usefull on hosting scenarios where you have to run multiple
146
- # web applications/sites on a single database.
147
-
148
- mattr_accessor :table_prefix, nil
149
-
150
- # If true, Og tries to create/update the schema in the
151
- # data store. For production/live environments set this to false
152
- # and only set to true when the object model is upadated.
153
- # For debug/development environments this should stay true
154
- # for convienience.
155
-
156
- mattr_accessor :create_schema, true
157
-
158
- # The active database. Og allows you to access multiple
159
- # databases from a single application.
160
-
161
- mattr_accessor :db
162
-
163
- # Set the active database.
164
-
165
- def self.use(db)
166
- @@db = db
167
- @@db.get_connection
168
- end
169
-
170
- # The adapter of the active database.
171
-
172
- def self.adapter
173
- @@db.adapter
174
- end
175
-
176
- # Marker module. If included this in a class, the Og automanager
177
- # ignores this class.
178
-
179
- module Unmanageable; end
180
-
181
- end
182
-
183
- # gmosx: leave this here.
184
-
185
- require 'og/database'
data/lib/og/adapter.rb DELETED
@@ -1,513 +0,0 @@
1
- # * George Moschovitis <gm@navel.gr>
2
- # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id: adapter.rb 270 2005-03-07 17:52:16Z gmosx $
4
-
5
- require 'yaml'
6
- require 'singleton'
7
-
8
- require 'og/connection'
9
-
10
- module Og
11
-
12
- # An adapter communicates with the backend datastore.
13
- # The adapters for all supported datastores extend this
14
- # class. Typically, an RDBMS is used to implement a
15
- # datastore.
16
-
17
- class Adapter
18
- include Singleton
19
-
20
- # A mapping between Ruby and backend Datastore types.
21
-
22
- attr_accessor :typemap
23
-
24
- # A map for casting Ruby types to SQL safe textual
25
- # representations.
26
-
27
- attr_accessor :typecast
28
-
29
- # Lookup the adapter instance from the adapter name.
30
-
31
- def self.for_name(name)
32
- require "og/adapters/#{name}"
33
- eval %{ return #{name.capitalize}Adapter.instance }
34
- end
35
-
36
- def initialize
37
- # The default mappings, should be valid for most
38
- # RDBMS.
39
-
40
- @typemap = {
41
- Integer => 'integer',
42
- Fixnum => 'integer',
43
- Float => 'float',
44
- String => 'text',
45
- Time => 'timestamp',
46
- Date => 'date',
47
- TrueClass => 'boolean',
48
- Object => 'text',
49
- Array => 'text',
50
- Hash => 'text'
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
- )
65
- end
66
-
67
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
68
- # :section: Utilities
69
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
70
-
71
- # Escape an SQL string
72
-
73
- def self.escape(str)
74
- return nil unless str
75
- return str.gsub( /'/, "''" )
76
- end
77
-
78
- # Convert a ruby time to an sql timestamp.
79
- # TODO: Optimize this
80
-
81
- def self.timestamp(time = Time.now)
82
- return nil unless time
83
- return time.strftime("%Y-%m-%d %H:%M:%S")
84
- end
85
-
86
- # Output YYY-mm-dd
87
- # TODO: Optimize this
88
-
89
- def self.date(date)
90
- return nil unless date
91
- return "#{date.year}-#{date.month}-#{date.mday}"
92
- end
93
-
94
- # Parse sql datetime
95
- # TODO: Optimize this
96
-
97
- def self.parse_timestamp(str)
98
- return nil unless str
99
- return Time.parse(str)
100
- end
101
-
102
- # Input YYYY-mm-dd
103
- # TODO: Optimize this
104
-
105
- def self.parse_date(str)
106
- return nil unless str
107
- return Date.strptime(str)
108
- end
109
-
110
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
111
- # :section: Database methods
112
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
113
-
114
- # Create the database.
115
-
116
- def create_db(database, user = nil, password = nil)
117
- Logger.info "Creating database '#{database}'."
118
- end
119
-
120
- # Drop the database.
121
-
122
- def drop_db(database, user = nil, password = nil)
123
- Logger.info "Dropping database '#{database}'."
124
- end
125
-
126
- # Create a new connection to the backend.
127
-
128
- def new_connection(db)
129
- return Connection.new(db)
130
- end
131
-
132
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
133
- # :section: O->R mapping methods and utilities.
134
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
135
-
136
- # Encode the name of the klass as an sql safe string.
137
- # The Module separators are replaced with _ and NOT stripped
138
- # out so that we can convert back to the original notation if
139
- # needed. The leading module if available is removed.
140
-
141
- def self.encode(klass)
142
- "#{klass.name.gsub(/^.*::/, "")}".gsub(/::/, "_").downcase
143
- end
144
-
145
- # The name of the SQL table where objects of this class
146
- # are stored. A prefix is needed to avoid colision with
147
- # reserved prefices (for example User maps to user which
148
- # is reserved in postgresql). The prefix should start
149
- # with an alphanumeric character to be compatible with
150
- # all RDBMS (most notable Oracle).
151
- #
152
- # You may want to override this method to map an existing
153
- # database schema using Og.
154
-
155
- def self.table(klass)
156
- "og_#{Og.table_prefix}#{encode(klass)}"
157
- end
158
-
159
- # The name of the join table for the two given classes.
160
- # A prefix is needed to avoid colision with reserved
161
- # prefices (for example User maps to user which
162
- # is reserved in postgresql). The prefix should start
163
- # with an alphanumeric character to be compatible with
164
- # all RDBMS (most notable Oracle).
165
- #
166
- # You may want to override this method to map an existing
167
- # database schema using Og.
168
-
169
- def self.join_table(klass1, klass2, field)
170
- "og_#{Og.table_prefix}j_#{encode(klass1)}_#{encode(klass2)}_#{field}"
171
- end
172
-
173
- # Return an sql string evaluator for the property.
174
- # No need to optimize this, used only to precalculate code.
175
- # YAML is used to store general Ruby objects to be more
176
- # portable.
177
- #--
178
- # FIXME: add extra handling for float.
179
- #++
180
-
181
- def write_prop(p)
182
- if p.klass.ancestors.include?(Integer)
183
- return "#\{@#{p.symbol} || 'NULL'\}"
184
- elsif p.klass.ancestors.include?(Float)
185
- return "#\{@#{p.symbol} || 'NULL'\}"
186
- elsif p.klass.ancestors.include?(String)
187
- return %|#\{@#{p.symbol} ? "'#\{#{self.class}.escape(@#{p.symbol})\}'" : 'NULL'\}|
188
- elsif p.klass.ancestors.include?(Time)
189
- return %|#\{@#{p.symbol} ? "'#\{#{self.class}.timestamp(@#{p.symbol})\}'" : 'NULL'\}|
190
- elsif p.klass.ancestors.include?(Date)
191
- return %|#\{@#{p.symbol} ? "'#\{#{self.class}.date(@#{p.symbol})\}'" : 'NULL'\}|
192
- elsif p.klass.ancestors.include?(TrueClass)
193
- return "#\{@#{p.symbol} ? \"'t'\" : 'NULL' \}"
194
- else
195
- # gmosx: keep the '' for nil symbols.
196
- return %|#\{@#{p.symbol} ? "'#\{#{self.class}.escape(@#{p.symbol}.to_yaml)\}'" : "''"\}|
197
- end
198
- end
199
-
200
- # Return an evaluator for reading the property.
201
- # No need to optimize this, used only to precalculate code.
202
-
203
- def read_prop(p, idx)
204
- if p.klass.ancestors.include?(Integer)
205
- return "res[#{idx}].to_i"
206
- elsif p.klass.ancestors.include?(Float)
207
- return "res[#{idx}].to_f"
208
- elsif p.klass.ancestors.include?(String)
209
- return "res[#{idx}]"
210
- elsif p.klass.ancestors.include?(Time)
211
- return "#{self.class}.parse_timestamp(res[#{idx}])"
212
- elsif p.klass.ancestors.include?(Date)
213
- return "#{self.class}.parse_date(res[#{idx}])"
214
- elsif p.klass.ancestors.include?(TrueClass)
215
- return "('0' != res[#{idx}])"
216
- else
217
- return "YAML::load(res[#{idx}])"
218
- end
219
- end
220
-
221
- # Create the fields that correpsond to the klass properties.
222
- # The generated fields array is used in create_table.
223
- # If the property has an :sql metadata this overrides the
224
- # default mapping. If the property has an :extra_sql metadata
225
- # the extra sql is appended after the default mapping.
226
-
227
- def create_fields(klass)
228
- fields = []
229
-
230
- klass.__props.each do |p|
231
- klass.sql_index(p.symbol) if p.meta[:sql_index]
232
-
233
- field = "#{p.symbol}"
234
-
235
- if p.meta and p.meta[:sql]
236
- field << " #{p.meta[:sql]}"
237
- else
238
- field << " #{@typemap[p.klass]}"
239
-
240
- if p.meta
241
- # set default value (gmosx: not that useful in the
242
- # current implementation).
243
- if default = p.meta[:default]
244
- field << " DEFAULT #{default.inspect} NOT NULL"
245
- end
246
-
247
- # set unique
248
- field << " UNIQUE" if p.meta[:unique]
249
-
250
- # attach extra sql
251
- if extra_sql = p.meta[:extra_sql]
252
- field << " #{extra_sql}"
253
- end
254
- end
255
- end
256
-
257
- fields << field
258
- end
259
-
260
- return fields
261
- end
262
-
263
- # Create the managed object table. The properties of the
264
- # object are mapped to the table columns. Additional sql relations
265
- # and constrains are created (indicices, sequences, etc).
266
-
267
- def create_table(klass)
268
- raise 'Not implemented!'
269
- end
270
-
271
- # Returns the props that will be included in the insert query.
272
- # For some backends the oid should be stripped.
273
-
274
- def props_for_insert(klass)
275
- klass.__props
276
- end
277
-
278
- # Returns the code that actually inserts the object into the
279
- # database. Returns the code as String.
280
-
281
- def insert_code(klass, sql, pre_cb, post_cb)
282
- raise 'Not implemented!'
283
- end
284
-
285
- # Generate the mapping of the database fields to the
286
- # object properties.
287
-
288
- def calc_field_index(klass, og)
289
- # Implement if needed.
290
- end
291
-
292
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
293
- # :section: Precompile lifecycle methods.
294
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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
-
306
- # Generate the property for oid.
307
-
308
- def eval_og_oid(klass)
309
- klass.class_eval %{
310
- prop_accessor :oid, Fixnum, :sql => "integer PRIMARY KEY"
311
- }
312
- end
313
-
314
- # Precompile the insert code for the given class.
315
- # The generated code sets the oid when inserting!
316
-
317
- def eval_og_insert(klass, db)
318
-
319
- # Attach object callbacks.
320
-
321
- if klass.instance_methods.include?('og_pre_insert')
322
- pre_cb = 'og_pre_insert(conn);'
323
- else
324
- pre_cb = ''
325
- end
326
-
327
- if klass.instance_methods.include?('og_post_insert')
328
- post_cb = 'og_post_insert(conn);'
329
- else
330
- post_cb = ''
331
- end
332
-
333
- if klass.instance_methods.include?('og_pre_insert_update')
334
- pre_cb << 'og_pre_insert_update(conn);'
335
- end
336
-
337
- if klass.instance_methods.include?('og_post_insert_update')
338
- post_cb << 'og_post_insert_update(conn);'
339
- end
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
-
370
- klass.class_eval %{
371
- def og_insert(conn)
372
- #{insert_code(klass, db, pre_cb, post_cb)}
373
- end
374
- }
375
- end
376
-
377
- # Precompile the update code for the given class.
378
- # Ignore the oid when updating!
379
-
380
- def eval_og_update(klass, db)
381
- props = klass.__props.reject { |p| :oid == p.symbol }
382
-
383
- updates = props.collect { |p|
384
- "#{p.name}=#{write_prop(p)}"
385
- }
386
-
387
- sql = "UPDATE #{klass::DBTABLE} SET #{updates.join(', ')} WHERE oid=#\{@oid\}"
388
-
389
- # Attach object callbacks.
390
-
391
- if klass.instance_methods.include?('og_pre_update')
392
- pre_cb = 'og_pre_update(conn);'
393
- else
394
- pre_cb = ''
395
- end
396
-
397
- if klass.instance_methods.include?('og_post_update')
398
- post_cb = 'og_post_update(conn);'
399
- else
400
- post_cb = ''
401
- end
402
-
403
- if klass.instance_methods.include?('og_pre_insert_update')
404
- pre_cb << 'og_pre_insert_update(conn);'
405
- end
406
-
407
- if klass.instance_methods.include?('og_post_insert_update')
408
- post_cb << 'og_post_insert_update(conn);'
409
- end
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
-
440
- klass.class_eval %{
441
- def og_update(conn)
442
- #{pre_cb}
443
- conn.exec "#{sql}"
444
- #{post_cb}
445
- end
446
- }
447
- end
448
-
449
- # Precompile the code to read (deserialize) objects of the
450
- # given class from the backend. In order to allow for changing
451
- # field/attribute orders we have to use a field mapping hash.
452
-
453
- def eval_og_read(klass, db)
454
- calc_field_index(klass, db)
455
-
456
- props = klass.__props
457
- code = []
458
-
459
- props.each do |p|
460
- if idx = db.managed_classes[klass].field_index[p.name]
461
- # more fault tolerant if a new field is added and it
462
- # doesnt exist in the database.
463
- code << "@#{p.name} = #{read_prop(p, idx)}"
464
- end
465
- end
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
-
502
- klass.class_eval %{
503
- def og_read(res, tuple = nil)
504
- #{pre_cb}
505
- #{code.join('; ')}
506
- #{post_cb}
507
- end
508
- }
509
- end
510
-
511
- end
512
-
513
- end