nitro 0.10.0 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS +4 -1
- data/ChangeLog +290 -7
- data/README +3 -3
- data/RELEASES +94 -0
- data/Rakefile +7 -7
- data/benchmark/og/bench.rb +11 -10
- data/{ChangeLog.1 → doc/ChangeLog.1} +0 -0
- data/doc/apache.txt +9 -0
- data/doc/architecture.txt +1 -27
- data/doc/bugs.txt +11 -4
- data/doc/config.txt +22 -0
- data/doc/og_config.txt +35 -0
- data/doc/og_tutorial.txt +595 -0
- data/doc/tutorial.txt +22 -0
- data/examples/blog/conf/apache.conf +30 -0
- data/examples/blog/conf/lhttpd.conf +2 -2
- data/examples/blog/lib/blog/controller.rb +11 -2
- data/examples/blog/log/apache.error_log +5528 -0
- data/examples/blog/root/fcgi.rb +1 -1
- data/examples/blog/run.rb +9 -3
- data/examples/flash/run.rb +2 -2
- data/examples/no_xsl_blog/conf/apache.conf +30 -0
- data/examples/no_xsl_blog/conf/lhttpd.conf +1 -1
- data/examples/no_xsl_blog/lib/blog/controller.rb +2 -2
- data/examples/no_xsl_blog/log/apache.error_log +68 -0
- data/examples/no_xsl_blog/root/fcgi.rb +2 -2
- data/examples/no_xsl_blog/run.rb +3 -3
- data/examples/og/run.rb +1 -1
- data/examples/tiny/conf/apache.conf +29 -4
- data/examples/tiny/conf/lhttpd.conf +1 -1
- data/examples/tiny/log/apache.error_log +30 -0
- data/examples/tiny/root/fcgi.rb +2 -2
- data/examples/tiny/root/index.xhtml +1 -1
- data/examples/tiny/run.rb +3 -2
- data/examples/wee_style/run.rb +7 -9
- data/examples/why_wiki/README +5 -0
- data/examples/why_wiki/run.rb +57 -0
- data/examples/why_wiki/wiki.yml +6 -0
- data/examples/wiki.yml +1 -0
- data/lib/glue/array.rb +14 -33
- data/lib/glue/hash.rb +32 -53
- data/lib/glue/pool.rb +9 -12
- data/lib/glue/property.rb +31 -9
- data/lib/nitro.rb +30 -8
- data/lib/nitro/adapters/cgi.rb +23 -3
- data/lib/nitro/adapters/webrick.rb +9 -3
- data/lib/nitro/builders/form.rb +21 -13
- data/lib/nitro/builders/rss.rb +20 -9
- data/lib/nitro/builders/table.rb +69 -10
- data/lib/nitro/builders/xhtml.rb +13 -4
- data/lib/nitro/component.rb +15 -0
- data/lib/nitro/conf.rb +4 -3
- data/lib/nitro/context.rb +22 -14
- data/lib/nitro/controller.rb +63 -5
- data/lib/nitro/dispatcher.rb +11 -6
- data/lib/nitro/output.rb +28 -0
- data/lib/nitro/render.rb +78 -59
- data/lib/nitro/request.rb +5 -1
- data/lib/nitro/runner.rb +20 -6
- data/lib/nitro/session.rb +89 -18
- data/lib/nitro/session/drb.rb +31 -0
- data/lib/nitro/session/drbserver.rb +71 -0
- data/lib/nitro/session/memory.rb +13 -0
- data/lib/nitro/simple.rb +7 -0
- data/lib/nitro/ui/date-select.rb +2 -5
- data/lib/nitro/ui/pager.rb +4 -4
- data/lib/nitro/ui/tabs.rb +2 -4
- data/lib/nitro/uri.rb +7 -4
- data/lib/og.rb +20 -12
- data/lib/og/adapter.rb +40 -13
- data/lib/og/adapters/filesys.rb +121 -0
- data/lib/og/adapters/mysql.rb +10 -5
- data/lib/og/adapters/oracle.rb +374 -0
- data/lib/og/adapters/psql.rb +10 -23
- data/lib/og/adapters/sqlite.rb +3 -3
- data/lib/og/backend.rb +2 -2
- data/lib/og/connection.rb +6 -6
- data/lib/og/database.rb +5 -5
- data/lib/og/enchant.rb +6 -2
- data/lib/og/meta.rb +56 -26
- data/lib/og/mock.rb +1 -1
- data/lib/og/typemacros.rb +23 -0
- data/lib/parts/content.rb +4 -10
- data/test/nitro/adapters/tc_cgi.rb +1 -1
- data/test/nitro/builders/tc_rss.rb +1 -1
- data/test/nitro/builders/tc_table.rb +30 -0
- data/test/nitro/tc_context.rb +4 -0
- data/test/nitro/tc_controller.rb +9 -2
- data/test/og/tc_filesys.rb +83 -0
- data/test/og/tc_meta.rb +55 -0
- data/test/tc_og.rb +115 -36
- data/vendor/README +11 -5
- data/vendor/breakpoint.rb +35 -38
- data/vendor/breakpoint_client.rb +119 -80
- data/vendor/composite_sexp_processor.rb +43 -0
- data/vendor/parse_tree.rb +745 -0
- data/vendor/sexp_processor.rb +453 -0
- metadata +34 -7
- data/examples/no_xsl_blog/conf/app.conf.rb +0 -47
@@ -0,0 +1,31 @@
|
|
1
|
+
# * George Moschovitis <gm@navel.gr>
|
2
|
+
# (c) 2004-2005 Navel, all rights reserved.
|
3
|
+
# $Id: drb.rb 264 2005-02-23 13:46:55Z gmosx $
|
4
|
+
|
5
|
+
require 'drb'
|
6
|
+
|
7
|
+
require 'glue/attribute'
|
8
|
+
require 'nitro/session'
|
9
|
+
|
10
|
+
Logger.debug 'Using Drb sessions.'
|
11
|
+
|
12
|
+
module N
|
13
|
+
|
14
|
+
class Session
|
15
|
+
|
16
|
+
# The address of the Session DRb server.
|
17
|
+
|
18
|
+
cattr_accessor :drb_address, '127.0.0.1'
|
19
|
+
|
20
|
+
# The port of the Session DRb server.
|
21
|
+
|
22
|
+
cattr_accessor :drb_port, 9069
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
Session.store = DRbObject.new(
|
27
|
+
nil,
|
28
|
+
"druby://#{Session.drb_address}:#{Session.drb_port}"
|
29
|
+
)
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# * George Moschovitis <gm@navel.gr>
|
4
|
+
# (c) 2004-2005 Navel, all rights reserved.
|
5
|
+
# $Id: drbserver.rb 264 2005-02-23 13:46:55Z gmosx $
|
6
|
+
|
7
|
+
require 'drb'
|
8
|
+
require 'optparse'
|
9
|
+
|
10
|
+
require 'glue/hash'
|
11
|
+
require 'nitro/session'
|
12
|
+
|
13
|
+
# A distributes session store implemented as
|
14
|
+
# a simple DRb server.
|
15
|
+
|
16
|
+
address = '127.0.0.1'
|
17
|
+
port = 9069
|
18
|
+
debug = false
|
19
|
+
|
20
|
+
parser = OptionParser.new do |opts|
|
21
|
+
|
22
|
+
opts.banner = 'Usage: drbserver.rb [options]'
|
23
|
+
opts.separator ''
|
24
|
+
opts.separator 'Specific options:'
|
25
|
+
|
26
|
+
opts.on('-a A', '--address A', 'Listening address.') do |a|
|
27
|
+
address = a
|
28
|
+
end
|
29
|
+
|
30
|
+
opts.on('-p P', '--port P', Integer, 'Listening port.') do |p|
|
31
|
+
port = p
|
32
|
+
end
|
33
|
+
|
34
|
+
opts.on('-D', '--debug', 'Run in debug mode.') do |p|
|
35
|
+
debug = true
|
36
|
+
end
|
37
|
+
|
38
|
+
opts.on_tail('-h', '--help', 'Show this message.') do
|
39
|
+
puts opts
|
40
|
+
exit
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
begin
|
46
|
+
parser.parse!(ARGV)
|
47
|
+
rescue OptionParser::InvalidOption
|
48
|
+
puts 'Invalid option, pass the --help parameter to get help!'
|
49
|
+
exit
|
50
|
+
end
|
51
|
+
|
52
|
+
sessions = N::SafeHash.new
|
53
|
+
|
54
|
+
if debug
|
55
|
+
|
56
|
+
class << sessions
|
57
|
+
def []=(k, v)
|
58
|
+
puts "WRITE: #{k} = #{v}"
|
59
|
+
super
|
60
|
+
end
|
61
|
+
|
62
|
+
def [](k)
|
63
|
+
puts "READ: #{k}"
|
64
|
+
super
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
DRb.start_service("druby://#{address}:#{port}", sessions)
|
71
|
+
DRb.thread.join
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# * George Moschovitis <gm@navel.gr>
|
2
|
+
# (c) 2004-2005 Navel, all rights reserved.
|
3
|
+
# $Id: memory.rb 264 2005-02-23 13:46:55Z gmosx $
|
4
|
+
|
5
|
+
require 'glue/hash'
|
6
|
+
|
7
|
+
Logger.debug 'Using In-Memory sessions.'
|
8
|
+
|
9
|
+
module N
|
10
|
+
|
11
|
+
Session.store = SafeHash.new
|
12
|
+
|
13
|
+
end
|
data/lib/nitro/simple.rb
ADDED
data/lib/nitro/ui/date-select.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
|
-
# code:
|
2
1
|
# * George Moschovitis <gm@navel.gr>
|
3
|
-
#
|
4
|
-
# (c) 2004 Navel, all rights reserved.
|
2
|
+
# (c) 2004-2005 Navel, all rights reserved.
|
5
3
|
# $Id: select.rb 39 2004-09-29 12:40:53Z elathan $
|
6
4
|
|
7
5
|
module N; module UI
|
@@ -68,5 +66,4 @@ module N; module UI
|
|
68
66
|
return str
|
69
67
|
end
|
70
68
|
|
71
|
-
end; end
|
72
|
-
|
69
|
+
end; end
|
data/lib/nitro/ui/pager.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# * George Moschovitis <gm@navel.gr>
|
2
2
|
# (c) 2004-2005 Navel, all rights reserved.
|
3
|
-
# $Id: pager.rb
|
3
|
+
# $Id: pager.rb 266 2005-02-28 14:50:48Z gmosx $
|
4
4
|
|
5
5
|
require 'nitro/uri'
|
6
6
|
|
@@ -17,9 +17,9 @@ module N; module UI
|
|
17
17
|
#
|
18
18
|
# === Example
|
19
19
|
#
|
20
|
-
# @pager =
|
21
|
-
# @entries =
|
22
|
-
# @pager.set(
|
20
|
+
# @pager = UI::Pager.new('entries', @request, 5)
|
21
|
+
# @entries = BlogEntry.all("ORDER BY oid #{@pager.sql_limit}")
|
22
|
+
# @pager.set(BlogEntry.count)
|
23
23
|
#
|
24
24
|
# default navigation (customize with css):
|
25
25
|
# <div class="pager">#{@pager.navigation}</div>
|
data/lib/nitro/ui/tabs.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
|
-
# code:
|
2
1
|
# * George Moschovitis <gm@navel.gr>
|
3
|
-
#
|
4
|
-
#
|
5
|
-
# $Id: tabs.rb 101 2004-10-22 12:35:39Z gmosx $
|
2
|
+
# (c) 2004-2005 Navel, all rights reserved.
|
3
|
+
# $Id: tabs.rb 266 2005-02-28 14:50:48Z gmosx $
|
6
4
|
|
7
5
|
module N; module UI
|
8
6
|
|
data/lib/nitro/uri.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# * George Moschovitis <gm@navel.gr>
|
2
2
|
# (c) 2004-2005 Navel, all rights reserved.
|
3
|
-
# $Id: uri.rb
|
3
|
+
# $Id: uri.rb 263 2005-02-23 13:45:08Z gmosx $
|
4
4
|
|
5
5
|
require "uri"
|
6
6
|
require "cgi"
|
@@ -9,9 +9,9 @@ require "glue/string"
|
|
9
9
|
|
10
10
|
module N
|
11
11
|
|
12
|
-
# URI utilities collection
|
12
|
+
# URI utilities collection.
|
13
13
|
#
|
14
|
-
# === Design
|
14
|
+
# === Design
|
15
15
|
#
|
16
16
|
# Implement as a module to avoid class polution. You can still
|
17
17
|
# use Ruby's advanced features to include the module in your
|
@@ -19,11 +19,14 @@ module N
|
|
19
19
|
# which isn't possible if you use self.
|
20
20
|
#
|
21
21
|
# The uris passed as parameters are typically strings.
|
22
|
+
#--
|
23
|
+
# gmosx, TODO: deprecate this.
|
24
|
+
#++
|
22
25
|
|
23
26
|
module UriUtils
|
24
27
|
|
25
28
|
# Decode the uri components.
|
26
|
-
|
29
|
+
|
27
30
|
def self.decode(uri)
|
28
31
|
# gmosx: hmm is this needed?
|
29
32
|
# guard against invalid filenames for example pictures with
|
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
|
3
|
+
# $Id: og.rb 266 2005-02-28 14:50:48Z gmosx $
|
4
4
|
|
5
5
|
require 'glue'
|
6
6
|
require 'glue/logger'
|
@@ -89,7 +89,7 @@ require 'glue/validation'
|
|
89
89
|
# * Deserialize to OpenStruct.
|
90
90
|
# * Better documentation.
|
91
91
|
|
92
|
-
|
92
|
+
module Og
|
93
93
|
|
94
94
|
# The name.
|
95
95
|
|
@@ -97,7 +97,7 @@ class Og
|
|
97
97
|
|
98
98
|
# The version.
|
99
99
|
|
100
|
-
Version = '0.
|
100
|
+
Version = '0.11.0'
|
101
101
|
|
102
102
|
# Library path.
|
103
103
|
|
@@ -106,37 +106,45 @@ class Og
|
|
106
106
|
# If true, only allow reading from the database. Usefull
|
107
107
|
# for maintainance.
|
108
108
|
|
109
|
-
|
109
|
+
mattr_accessor :read_only_mode, false
|
110
110
|
|
111
111
|
# If true, the library automatically 'enchants' managed classes.
|
112
112
|
# In enchant mode, special db aware methods are added to
|
113
113
|
# managed classes and instances.
|
114
|
+
# If false, Og enchants only classes that define properties.
|
114
115
|
|
115
|
-
|
116
|
+
mattr_accessor :enchant_managed_classes, true
|
116
117
|
|
117
118
|
# If true, use Ruby's advanced introspection capabilities to
|
118
119
|
# automatically manage classes tha define properties.
|
119
120
|
|
120
|
-
|
121
|
+
mattr_accessor :auto_manage_classes, true
|
121
122
|
|
122
123
|
# If true, automatically include the Og meta-language into Module.
|
123
|
-
#
|
124
|
-
#
|
125
|
-
# However if you include a prop_accessor or a managed Mixin in your
|
124
|
+
# If false, the polution of the Module object is avoided. However
|
125
|
+
# if you include a prop_accessor or a managed Mixin in your
|
126
126
|
# object MetaLanguage gets automatically extended in the class.
|
127
127
|
|
128
|
-
|
128
|
+
mattr_accessor :include_meta_language, true
|
129
129
|
|
130
130
|
# Attach the following prefix to all generated SQL table names.
|
131
131
|
# Usefull on hosting scenarios where you have to run multiple
|
132
132
|
# web applications/sites on a single database.
|
133
133
|
|
134
|
-
|
134
|
+
mattr_accessor :table_prefix, nil
|
135
135
|
|
136
|
+
# If true, Og tries to create/update the schema in the
|
137
|
+
# data store. For production/live environments set this to false
|
138
|
+
# and only set to true when the object model is upadated.
|
139
|
+
# For debug/development environments this should stay true
|
140
|
+
# for convienience.
|
141
|
+
|
142
|
+
mattr_accessor :create_schema, true
|
143
|
+
|
136
144
|
# The active database. Og allows you to access multiple
|
137
145
|
# databases from a single application.
|
138
146
|
|
139
|
-
|
147
|
+
mattr_accessor :db
|
140
148
|
|
141
149
|
# Set the active database.
|
142
150
|
|
data/lib/og/adapter.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
# * George Moschovitis <gm@navel.gr>
|
2
2
|
# (c) 2004-2005 Navel, all rights reserved.
|
3
|
-
# $Id: adapter.rb
|
3
|
+
# $Id: adapter.rb 266 2005-02-28 14:50:48Z gmosx $
|
4
4
|
|
5
5
|
require 'yaml'
|
6
6
|
require 'singleton'
|
7
7
|
|
8
8
|
require 'og/connection'
|
9
9
|
|
10
|
-
|
10
|
+
module Og
|
11
11
|
|
12
12
|
# An adapter communicates with the backend datastore.
|
13
13
|
# The adapters for all supported datastores extend this
|
@@ -74,6 +74,7 @@ class Adapter
|
|
74
74
|
# TODO: Optimize this
|
75
75
|
|
76
76
|
def self.parse_timestamp(str)
|
77
|
+
return nil unless str
|
77
78
|
return Time.parse(str)
|
78
79
|
end
|
79
80
|
|
@@ -108,7 +109,7 @@ class Adapter
|
|
108
109
|
end
|
109
110
|
|
110
111
|
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
111
|
-
# :section:
|
112
|
+
# :section: O->R mapping methods and utilities.
|
112
113
|
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
113
114
|
|
114
115
|
# Encode the name of the klass as an sql safe string.
|
@@ -121,24 +122,40 @@ class Adapter
|
|
121
122
|
end
|
122
123
|
|
123
124
|
# The name of the SQL table where objects of this class
|
124
|
-
# are stored.
|
125
|
+
# are stored. A prefix is needed to avoid colision with
|
126
|
+
# reserved prefices (for example User maps to user which
|
127
|
+
# is reserved in postgresql). The prefix should start
|
128
|
+
# with an alphanumeric character to be compatible with
|
129
|
+
# all RDBMS (most notable Oracle).
|
130
|
+
#
|
131
|
+
# You may want to override this method to map an existing
|
132
|
+
# database schema using Og.
|
125
133
|
|
126
134
|
def self.table(klass)
|
127
|
-
"
|
135
|
+
"og_#{Og.table_prefix}#{encode(klass)}"
|
128
136
|
end
|
129
137
|
|
130
138
|
# The name of the join table for the two given classes.
|
139
|
+
# A prefix is needed to avoid colision with reserved
|
140
|
+
# prefices (for example User maps to user which
|
141
|
+
# is reserved in postgresql). The prefix should start
|
142
|
+
# with an alphanumeric character to be compatible with
|
143
|
+
# all RDBMS (most notable Oracle).
|
144
|
+
#
|
145
|
+
# You may want to override this method to map an existing
|
146
|
+
# database schema using Og.
|
131
147
|
|
132
148
|
def self.join_table(klass1, klass2)
|
133
|
-
"
|
149
|
+
"og_#{Og.table_prefix}j_#{encode(klass1)}_#{encode(klass2)}"
|
134
150
|
end
|
135
|
-
|
151
|
+
|
136
152
|
# Return an sql string evaluator for the property.
|
137
153
|
# No need to optimize this, used only to precalculate code.
|
138
154
|
# YAML is used to store general Ruby objects to be more
|
139
155
|
# portable.
|
140
|
-
|
156
|
+
#--
|
141
157
|
# FIXME: add extra handling for float.
|
158
|
+
#++
|
142
159
|
|
143
160
|
def write_prop(p)
|
144
161
|
if p.klass.ancestors.include?(Integer)
|
@@ -146,7 +163,7 @@ class Adapter
|
|
146
163
|
elsif p.klass.ancestors.include?(Float)
|
147
164
|
return "#\{@#{p.symbol} || 'NULL'\}"
|
148
165
|
elsif p.klass.ancestors.include?(String)
|
149
|
-
return "'#\{#{self.class}.escape(@#{p.symbol})\}'"
|
166
|
+
return %|#\{@#{p.symbol} ? "'#\{#{self.class}.escape(@#{p.symbol})\}'" : 'NULL'\}|
|
150
167
|
elsif p.klass.ancestors.include?(Time)
|
151
168
|
return %|#\{@#{p.symbol} ? "'#\{#{self.class}.timestamp(@#{p.symbol})\}'" : 'NULL'\}|
|
152
169
|
elsif p.klass.ancestors.include?(Date)
|
@@ -154,6 +171,7 @@ class Adapter
|
|
154
171
|
elsif p.klass.ancestors.include?(TrueClass)
|
155
172
|
return "#\{@#{p.symbol} ? \"'t'\" : 'NULL' \}"
|
156
173
|
else
|
174
|
+
# gmosx: keep the '' for nil symbols.
|
157
175
|
return %|#\{@#{p.symbol} ? "'#\{#{self.class}.escape(@#{p.symbol}.to_yaml)\}'" : "''"\}|
|
158
176
|
end
|
159
177
|
end
|
@@ -197,9 +215,18 @@ class Adapter
|
|
197
215
|
field << " #{p.meta[:sql]}"
|
198
216
|
else
|
199
217
|
field << " #{@typemap[p.klass]}"
|
200
|
-
|
201
|
-
if p.meta
|
202
|
-
|
218
|
+
|
219
|
+
if p.meta
|
220
|
+
# set default value (gmosx: not that useful in the
|
221
|
+
# current implementation).
|
222
|
+
if default = p.meta[:default]
|
223
|
+
field << " DEFAULT #{default.inspect} NOT NULL"
|
224
|
+
end
|
225
|
+
|
226
|
+
# attach extra sql
|
227
|
+
if extra_sql = p.meta[:extra_sql]
|
228
|
+
field << " #{extra_sql}"
|
229
|
+
end
|
203
230
|
end
|
204
231
|
end
|
205
232
|
|
@@ -235,7 +262,7 @@ class Adapter
|
|
235
262
|
# object properties.
|
236
263
|
|
237
264
|
def calc_field_index(klass, og)
|
238
|
-
|
265
|
+
# Implement if needed.
|
239
266
|
end
|
240
267
|
|
241
268
|
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# * George Moschovitis <gm@navel.gr>
|
2
|
+
# (c) 2004-2005 Navel, all rights reserved.
|
3
|
+
# $Id: filesys.rb 264 2005-02-23 13:46:55Z gmosx $
|
4
|
+
|
5
|
+
require 'fileutils'
|
6
|
+
|
7
|
+
require 'og/adapter'
|
8
|
+
require 'og/connection'
|
9
|
+
require 'glue/attribute'
|
10
|
+
|
11
|
+
module Og
|
12
|
+
|
13
|
+
# The Filesys adapter. This adapter stores Og objectes in
|
14
|
+
# the filesystem. This adapter is a proof of concept and
|
15
|
+
# at the moment severely limited. For extra documentation
|
16
|
+
# see lib/og/adapter.rb
|
17
|
+
|
18
|
+
class FilesysAdapter < Adapter
|
19
|
+
|
20
|
+
# Creates the name of the database root dir.
|
21
|
+
|
22
|
+
def self.dir(database)
|
23
|
+
"#{database}_db"
|
24
|
+
end
|
25
|
+
|
26
|
+
def create_db(database, user = nil, password = nil)
|
27
|
+
begin
|
28
|
+
FileUtils.mkdir_p(self.class.dir(database))
|
29
|
+
rescue
|
30
|
+
Logger.error "Cannot create '#{database}'!"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def drop_db(database, user = nil, password = nil)
|
35
|
+
begin
|
36
|
+
FileUtils.rmdir(self.class.dir(database))
|
37
|
+
super
|
38
|
+
rescue
|
39
|
+
Logger.error "Cannot drop '#{database}'!"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def insert_code(klass, db, pre_cb, post_cb)
|
44
|
+
props = props_for_insert(klass)
|
45
|
+
values = props.collect { |p| write_prop(p) }.join(',')
|
46
|
+
|
47
|
+
sql = "INSERT INTO #{klass::DBTABLE} (#{props.collect {|p| p.name}.join(',')}) VALUES (#{values})"
|
48
|
+
|
49
|
+
%{
|
50
|
+
#{pre_cb}
|
51
|
+
conn.store.query("#{sql}").close
|
52
|
+
@oid = conn.store.last_insert_row_id
|
53
|
+
#{post_cb}
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
def new_connection(db)
|
58
|
+
return FilesysConnection.new(db)
|
59
|
+
end
|
60
|
+
|
61
|
+
# A 'table' is emulated by using a directory to store
|
62
|
+
# one file per table row. Each file contains an object
|
63
|
+
# marshaled in YAML format. A special file called
|
64
|
+
# '_sequence' stores the sequence for this 'table'.
|
65
|
+
|
66
|
+
def create_table(klass, db)
|
67
|
+
class_dir = File.join(self.class.dir(db.config[:database]), klass::DBTABLE)
|
68
|
+
FileUtils.mkdir_p(class_dir)
|
69
|
+
|
70
|
+
seq_file = File.join(class_dir, 'seq')
|
71
|
+
File.open(seq_file, 'w') { |f| f << '1' }
|
72
|
+
rescue => ex
|
73
|
+
Logger.error "Cannot create directory to store '#{klass}' classes!"
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
# The Filesys adapter connection.
|
79
|
+
|
80
|
+
class FilesysConnection < Connection
|
81
|
+
|
82
|
+
def initialize(db)
|
83
|
+
super
|
84
|
+
config = db.config
|
85
|
+
|
86
|
+
begin
|
87
|
+
raise unless File.directory?(FilesysAdapter.dir(config[:database]))
|
88
|
+
rescue => ex
|
89
|
+
if true # ex.to_s =~ /database .* does not exist/i
|
90
|
+
Logger.info "Database '#{config[:database]}' not found!"
|
91
|
+
@db.adapter.create_db(config[:database], config[:user])
|
92
|
+
retry
|
93
|
+
end
|
94
|
+
raise
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def save(obj)
|
99
|
+
seq = nil
|
100
|
+
class_dir = File.join(FilesysAdapter.dir(@db.config[:database]), obj.class::DBTABLE)
|
101
|
+
File.open(File.join(class_dir, 'seq'), 'r') { |f| seq = f.read.to_i }
|
102
|
+
obj.oid = seq
|
103
|
+
File.open(File.join(class_dir, "#{seq}.yml"), 'w') { |f| f << obj.to_yaml }
|
104
|
+
seq += 1
|
105
|
+
File.open(File.join(class_dir, 'seq'), 'w') { |f| f << seq }
|
106
|
+
end
|
107
|
+
|
108
|
+
def load(oid, klass)
|
109
|
+
obj = nil
|
110
|
+
class_dir = File.join(FilesysAdapter.dir(@db.config[:database]), klass::DBTABLE)
|
111
|
+
File.open(File.join(class_dir, "#{oid}.yml"), 'r') { |f| obj = YAML::load(f.read) }
|
112
|
+
return obj
|
113
|
+
end
|
114
|
+
|
115
|
+
def close
|
116
|
+
Logger.debug "Closed DB connection." if $DBG
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|