nitro 0.9.5 → 0.10.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.
Files changed (104) hide show
  1. data/ChangeLog +260 -0
  2. data/INSTALL +60 -0
  3. data/LICENSE +1 -0
  4. data/README +19 -20
  5. data/RELEASES +48 -0
  6. data/Rakefile +102 -92
  7. data/benchmark/og/bench.rb +74 -0
  8. data/benchmark/og/sqlite-no-prepare.1.txt +13 -0
  9. data/benchmark/og/sqlite-no-prepare.2.txt +13 -0
  10. data/benchmark/og/sqlite-prepare.1.txt +13 -0
  11. data/benchmark/og/sqlite-prepare.2.txt +13 -0
  12. data/bin/cluster +1 -1
  13. data/bin/nitro +3 -0
  14. data/bin/proto/conf/app.conf.rb +2 -10
  15. data/examples/README.windows +9 -0
  16. data/examples/blog/README +16 -4
  17. data/examples/blog/lib/blog.rb +3 -3
  18. data/examples/blog/lib/blog/controller.rb +7 -9
  19. data/examples/blog/root/fcgi.rb +2 -4
  20. data/examples/blog/root/style.xsl +4 -6
  21. data/examples/blog/run.rb +41 -0
  22. data/examples/flash/run.rb +9 -0
  23. data/examples/no_xsl_blog/README +0 -1
  24. data/examples/no_xsl_blog/conf/app.conf.rb +6 -13
  25. data/examples/no_xsl_blog/lib/blog.rb +2 -2
  26. data/examples/no_xsl_blog/lib/blog/controller.rb +6 -6
  27. data/examples/no_xsl_blog/root/fcgi.rb +2 -4
  28. data/examples/no_xsl_blog/run.rb +38 -0
  29. data/examples/og/mock_example.rb +0 -2
  30. data/examples/og/mysql_to_psql.rb +0 -2
  31. data/examples/og/run.rb +23 -22
  32. data/examples/tiny/root/fcgi.rb +2 -4
  33. data/examples/tiny/root/index.xhtml +21 -5
  34. data/examples/tiny/root/upload.xhtml +23 -0
  35. data/examples/tiny/run.rb +9 -0
  36. data/examples/wee_style/{wee.rb → run.rb} +13 -13
  37. data/install.rb +44 -0
  38. data/lib/glue/array.rb +6 -10
  39. data/lib/glue/attribute.rb +0 -3
  40. data/lib/glue/cache.rb +1 -1
  41. data/lib/glue/inflector.rb +5 -5
  42. data/lib/glue/mixins.rb +3 -12
  43. data/lib/glue/number.rb +1 -1
  44. data/lib/glue/object.rb +7 -1
  45. data/lib/glue/property.rb +32 -22
  46. data/lib/glue/string.rb +13 -75
  47. data/lib/glue/time.rb +2 -2
  48. data/lib/glue/validation.rb +7 -11
  49. data/lib/nitro.rb +16 -1
  50. data/lib/nitro/{adaptors → adapters}/cgi.rb +101 -20
  51. data/lib/nitro/{adaptors → adapters}/fastcgi.rb +3 -2
  52. data/lib/nitro/{adaptors → adapters}/webrick.rb +4 -4
  53. data/lib/nitro/builders/rss.rb +1 -1
  54. data/lib/nitro/builders/xml.rb +8 -10
  55. data/lib/nitro/cluster.rb +1 -1
  56. data/lib/nitro/conf.rb +34 -0
  57. data/lib/nitro/controller.rb +8 -9
  58. data/lib/nitro/dispatcher.rb +38 -11
  59. data/lib/nitro/filters.rb +1 -1
  60. data/lib/nitro/markup.rb +14 -1
  61. data/lib/nitro/render.rb +7 -10
  62. data/lib/nitro/runner.rb +232 -0
  63. data/lib/nitro/ui/pager.rb +2 -6
  64. data/lib/nitro/uri.rb +7 -11
  65. data/lib/og.rb +27 -261
  66. data/lib/og/adapter.rb +352 -0
  67. data/lib/og/adapters/mysql.rb +304 -0
  68. data/lib/og/adapters/psql.rb +286 -0
  69. data/lib/og/adapters/sqlite.rb +262 -0
  70. data/lib/og/backend.rb +1 -1
  71. data/lib/og/connection.rb +123 -87
  72. data/lib/og/database.rb +268 -0
  73. data/lib/og/meta.rb +23 -22
  74. data/lib/og/mock.rb +2 -3
  75. data/lib/xsl/base.xsl +1 -55
  76. data/test/glue/tc_property.rb +2 -0
  77. data/test/glue/tc_property_type_checking.rb +32 -0
  78. data/test/glue/tc_strings.rb +2 -2
  79. data/test/glue/tc_validation.rb +2 -0
  80. data/test/nitro/adapters/raw_post1.bin +0 -0
  81. data/test/nitro/{adaptors → adapters}/tc_cgi.rb +11 -2
  82. data/test/nitro/{adaptors → adapters}/tc_webrick.rb +3 -3
  83. data/test/nitro/builders/tc_xml.rb +14 -5
  84. data/test/nitro/tc_dispatcher.rb +3 -3
  85. data/test/nitro/tc_uri.rb +2 -4
  86. data/test/og/tc_lifecycle.rb +22 -25
  87. data/test/og/tc_sqlite.rb +87 -0
  88. data/test/tc_og.rb +61 -42
  89. metadata +67 -33
  90. data/examples/blog/conf/app.conf.rb +0 -52
  91. data/examples/blog/ctl +0 -4
  92. data/examples/flash/conf/app.conf.rb +0 -21
  93. data/examples/flash/ctl +0 -4
  94. data/examples/no_xsl_blog/conf/apache.conf +0 -0
  95. data/examples/no_xsl_blog/ctl +0 -4
  96. data/examples/tiny/conf/app.conf.rb +0 -17
  97. data/examples/tiny/ctl +0 -4
  98. data/lib/glue/macro.rb +0 -56
  99. data/lib/nitro/adaptors/runner.rb +0 -123
  100. data/lib/nitro/version.rb +0 -15
  101. data/lib/og/backends/mysql.rb +0 -370
  102. data/lib/og/backends/psql.rb +0 -386
  103. data/lib/og/backends/sqlite.rb +0 -383
  104. data/lib/og/version.rb +0 -9
@@ -1,383 +0,0 @@
1
- # * George Moschovitis <gm@navel.gr>
2
- # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id$
4
-
5
- require 'sqlite'
6
-
7
- require 'og/backend'
8
-
9
- class Og
10
-
11
- # Implements an SQLite powered backend.
12
-
13
- class SqliteBackend < Backend
14
-
15
- # A mapping between Ruby and SQL types.
16
-
17
- TYPEMAP = {
18
- Integer => 'integer',
19
- Fixnum => 'integer',
20
- Float => 'float',
21
- String => 'text',
22
- Time => 'timestamp',
23
- Date => 'date',
24
- TrueClass => 'boolean',
25
- Object => 'text',
26
- Array => 'text',
27
- Hash => 'text'
28
- }
29
-
30
- # Intitialize the connection to the RDBMS.
31
-
32
- def initialize(config)
33
- begin
34
- @conn = SQLite::Database.new(config[:database])
35
- rescue => ex
36
- # gmosx: any idea how to better test this?
37
- if ex.to_s =~ /database .* does not exist/i
38
- Logger.info "Database '#{config[:database]}' not found!"
39
- SqliteBackend.create_db(config[:database], config[:user])
40
- retry
41
- end
42
- raise
43
- end
44
- end
45
-
46
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
47
- # Utilities
48
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
49
-
50
- # Escape an SQL string
51
-
52
- def self.escape(str)
53
- return nil unless str
54
- return str.gsub( /'/, "''" )
55
- end
56
-
57
- # Convert a ruby time to an sql timestamp.
58
- # TODO: Optimize this
59
-
60
- def self.timestamp(time = Time.now)
61
- return nil unless time
62
- return time.strftime("%Y-%m-%d %H:%M:%S")
63
- end
64
-
65
- # Output YYY-mm-dd
66
- # TODO: Optimize this
67
-
68
- def self.date(date)
69
- return nil unless date
70
- return "#{date.year}-#{date.month}-#{date.mday}"
71
- end
72
-
73
- # Parse sql datetime
74
- # TODO: Optimize this
75
-
76
- def self.parse_timestamp(str)
77
- return Time.parse(str)
78
- end
79
-
80
- # Input YYYY-mm-dd
81
- # TODO: Optimize this
82
-
83
- def self.parse_date(str)
84
- return nil unless str
85
- return Date.strptime(str)
86
- end
87
-
88
- # Return an sql string evaluator for the property.
89
- # No need to optimize this, used only to precalculate code.
90
- # YAML is used to store general Ruby objects to be more
91
- # portable.
92
- #
93
- # FIXME: add extra handling for float.
94
-
95
- def self.write_prop(p)
96
- if p.klass.ancestors.include?(Integer)
97
- return "#\{@#{p.symbol} || 'NULL'\}"
98
- elsif p.klass.ancestors.include?(Float)
99
- return "#\{@#{p.symbol} || 'NULL'\}"
100
- elsif p.klass.ancestors.include?(String)
101
- return "'#\{SqliteBackend.escape(@#{p.symbol})\}'"
102
- elsif p.klass.ancestors.include?(Time)
103
- return %|#\{@#{p.symbol} ? "'#\{SqliteBackend.timestamp(@#{p.symbol})\}'" : 'NULL'\}|
104
- elsif p.klass.ancestors.include?(Date)
105
- return %|#\{@#{p.symbol} ? "'#\{SqliteBackend.date(@#{p.symbol})\}'" : 'NULL'\}|
106
- elsif p.klass.ancestors.include?(TrueClass)
107
- return "#\{@#{p.symbol} ? \"'t'\" : 'NULL' \}"
108
- else
109
- return %|#\{@#{p.symbol} ? "'#\{SqliteBackend.escape(@#{p.symbol}.to_yaml)\}'" : "''"\}|
110
- end
111
- end
112
-
113
- # Return an evaluator for reading the property.
114
- # No need to optimize this, used only to precalculate code.
115
-
116
- def self.read_prop(p, idx)
117
- if p.klass.ancestors.include?(Integer)
118
- return "res.getvalue(tuple, #{idx}).to_i()"
119
- elsif p.klass.ancestors.include?(Float)
120
- return "res.getvalue(tuple, #{idx}).to_f()"
121
- elsif p.klass.ancestors.include?(String)
122
- return "res.getvalue(tuple, #{idx})"
123
- elsif p.klass.ancestors.include?(Time)
124
- return "PsqlBackend.parse_timestamp(res.getvalue(tuple, #{idx}))"
125
- elsif p.klass.ancestors.include?(Date)
126
- return "PsqlBackend.parse_date(res.getvalue(tuple, #{idx}))"
127
- elsif p.klass.ancestors.include?(TrueClass)
128
- return %|('t' == res.getvalue(tuple, #{idx}))|
129
- else
130
- return "YAML::load(res.getvalue(tuple, #{idx}))"
131
- end
132
- end
133
-
134
- # Returns the code that actually inserts the object into the
135
- # database. Returns the code as String.
136
-
137
- def self.insert_code(klass, sql, pre_cb, post_cb)
138
- %{
139
- #{pre_cb}
140
- res = conn.db.query("SELECT nextval('#{klass::DBSEQ}')")
141
- @oid = res.getvalue(0, 0).to_i
142
- conn.exec "#{sql}"
143
- #{post_cb}
144
- }
145
- end
146
-
147
- # generate the mapping of the database fields to the
148
- # object properties.
149
-
150
- def self.calc_field_index(klass, og)
151
- res = og.query "SELECT * FROM #{klass::DBTABLE} LIMIT 1"
152
- meta = og.managed_classes[klass]
153
-
154
- for field in res.fields
155
- meta.field_index[field] = res.fieldnum(field)
156
- end
157
- end
158
-
159
- # Generate the property for oid
160
-
161
- def self.eval_og_oid(klass)
162
- klass.class_eval %{
163
- prop_accessor :oid, Fixnum, :sql => "integer PRIMARY KEY"
164
- }
165
- end
166
-
167
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
168
- # Connection methods.
169
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
170
-
171
- # Create the database.
172
-
173
- def self.create_db(database, user = nil, password = nil)
174
- Logger.info "Creating database '#{database}'."
175
- `createdb #{database} -U #{user}`
176
- end
177
-
178
- # Drop the database.
179
-
180
- def self.drop_db(database, user = nil, password = nil)
181
- Logger.info "Dropping database '#{database}'."
182
- `dropdb #{database} -U #{user}`
183
- end
184
-
185
- # Execute an SQL query and return the result.
186
-
187
- def query(sql)
188
- Logger.debug sql if $DBG
189
- return @conn.exec(sql)
190
- end
191
-
192
- # Execute an SQL query, no result returned.
193
-
194
- def exec(sql)
195
- Logger.debug sql if $DBG
196
- res = @conn.exec(sql)
197
- res.clear()
198
- end
199
-
200
- # Execute an SQL query and return the result. Wrapped in a rescue
201
- # block.
202
-
203
- def safe_query(sql)
204
- Logger.debug sql if $DBG
205
- begin
206
- return @conn.exec(sql)
207
- rescue => ex
208
- Logger.error "DB error #{ex}, [#{sql}]"
209
- Logger.error ex.backtrace
210
- return nil
211
- end
212
- end
213
-
214
- # Execute an SQL query, no result returned. Wrapped in a rescue
215
- # block.
216
-
217
- def safe_exec(sql)
218
- Logger.debug sql if $DBG
219
- begin
220
- res = @conn.exec(sql)
221
- res.clear()
222
- rescue => ex
223
- Logger.error "DB error #{ex}, [#{sql}]"
224
- Logger.error ex.backtrace
225
- end
226
- end
227
-
228
- # Check if it is a valid resultset.
229
-
230
- def valid?(res)
231
- return !(res.nil? or 0 == res.num_tuples)
232
- end
233
-
234
- # Create the managed object table. The properties of the
235
- # object are mapped to the table columns. Additional sql relations
236
- # and constrains are created (indicices, sequences, etc).
237
-
238
- def create_table(klass)
239
- fields = create_fields(klass, TYPEMAP)
240
-
241
- sql = "CREATE TABLE #{klass::DBTABLE} (#{fields.join(', ')}"
242
-
243
- # Create table constrains
244
-
245
- if klass.__meta and constrains = klass.__meta[:sql_constrain]
246
- sql << ", #{constrains.join(', ')}"
247
- end
248
-
249
- sql << ") WITHOUT OIDS;"
250
-
251
- # Create indices
252
-
253
- if klass.__meta and indices = klass.__meta[:sql_index]
254
- for data in indices
255
- idx, options = *data
256
- idx = idx.to_s
257
- pre_sql, post_sql = options[:pre], options[:post]
258
- idxname = idx.gsub(/ /, "").gsub(/,/, "_").gsub(/\(.*\)/, "")
259
- sql << " CREATE #{pre_sql} INDEX #{klass::DBTABLE}_#{idxname}_idx #{post_sql} ON #{klass::DBTABLE} (#{idx});"
260
- end
261
- end
262
-
263
- begin
264
- exec(sql)
265
- Logger.info "Created table '#{klass::DBTABLE}'."
266
- rescue => ex
267
- # gmosx: any idea how to better test this?
268
- if ex.to_s =~ /relation .* already exists/i
269
- Logger.debug "Table already exists" if $DBG
270
- else
271
- raise
272
- end
273
- end
274
-
275
- # create the sequence for this table. Even if the table
276
- # uses the oids_seq, attempt to create it. This makes
277
- # the system more fault tolerant.
278
-
279
- begin
280
- exec "CREATE SEQUENCE #{klass::DBSEQ}"
281
- Logger.info "Created sequence '#{klass::DBSEQ}'."
282
- rescue => ex
283
- # gmosx: any idea how to better test this?
284
- if ex.to_s =~ /relation .* already exists/i
285
- Logger.debug "Sequence already exists" if $DBG
286
- else
287
- raise
288
- end
289
- end
290
-
291
- # Create join tables if needed. Join tables are used in
292
- # 'many_to_many' relations.
293
-
294
- if klass.__meta and joins = klass.__meta[:sql_join]
295
- for data in joins
296
- # the class to join to and some options.
297
- join_class, options = *data
298
-
299
- # gmosx: dont use DBTABLE here, perhaps the join class
300
- # is not managed yet.
301
- join_table = "#{self.class.join_table(klass, join_class)}"
302
- join_src = "#{self.class.encode(klass)}_oid"
303
- join_dst = "#{self.class.encode(join_class)}_oid"
304
- begin
305
- exec "CREATE TABLE #{join_table} ( key1 integer NOT NULL, key2 integer NOT NULL )"
306
- exec "CREATE INDEX #{join_table}_key1_idx ON #{join_table} (key1)"
307
- exec "CREATE INDEX #{join_table}_key2_idx ON #{join_table} (key2)"
308
- rescue => ex
309
- # gmosx: any idea how to better test this?
310
- if ex.to_s =~ /relation .* already exists/i
311
- Logger.debug "Join table already exists" if $DBG
312
- else
313
- raise
314
- end
315
- end
316
- end
317
- end
318
-
319
- begin
320
- exec(sql)
321
- Logger.info "Created join table '#{join_table}'."
322
- rescue => ex
323
- # gmosx: any idea how to better test this?
324
- if ex.to_s =~ /relation .* already exists/i
325
- Logger.debug "Join table already exists" if $DBG
326
- else
327
- raise
328
- end
329
- end
330
-
331
- end
332
-
333
- # Drop the managed object table.
334
-
335
- def drop_table(klass)
336
- super
337
- exec "DROP SEQUENCE #{klass::DBSEQ}"
338
- end
339
-
340
- # Deserialize one row of the resultset.
341
-
342
- def deserialize_one(res, klass)
343
- return nil unless valid?(res)
344
-
345
- # gmosx: Managed objects should have no params constructor.
346
- entity = klass.new()
347
- entity.og_deserialize(res, 0)
348
-
349
- # get_join_fields(res, 0, entity, join_fields) if join_fields
350
-
351
- res.clear()
352
- return entity
353
- end
354
-
355
- # Deserialize all rows of the resultset.
356
-
357
- def deserialize_all(res, klass)
358
- return [] unless valid?(res)
359
-
360
- entities = []
361
-
362
- for tuple in (0...res.num_tuples)
363
- entity = klass.new()
364
- entity.og_deserialize(res, tuple)
365
-
366
- # get_join_fields(res, tuple, entity, join_fields) if join_fields
367
-
368
- entities << entity
369
- end
370
-
371
- res.clear()
372
- return entities
373
- end
374
-
375
- # Return a single integer value from the resultset.
376
-
377
- def get_int(res, idx = 0)
378
- return res.getvalue(0, idx).to_i
379
- end
380
-
381
- end
382
-
383
- end
data/lib/og/version.rb DELETED
@@ -1,9 +0,0 @@
1
- # * George Moschovitis <gm@navel.gr>
2
- # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id: version.rb 248 2005-01-31 13:38:34Z gmosx $
4
-
5
- class Og
6
- # The version of Og.
7
-
8
- Version = '0.9.5'
9
- end