nitro 0.10.0 → 0.11.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/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
|