nitro 0.3.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +284 -0
- data/{LICENCE → LICENSE} +1 -1
- data/README +13 -17
- data/RELEASES +13 -1
- data/Rakefile +1 -9
- data/bin/cluster.rb +5 -5
- data/examples/blog/README +45 -0
- data/examples/blog/apache.conf +0 -0
- data/examples/blog/app.rb +21 -0
- data/examples/blog/config.rb +88 -0
- data/examples/blog/lib/blog.rb +104 -0
- data/examples/blog/log/app.log +117 -0
- data/examples/blog/root/comments.xhtml +38 -0
- data/examples/blog/root/entry_form.xhtml +18 -0
- data/examples/blog/root/index.xhtml +43 -0
- data/examples/blog/root/login.xhtml +24 -0
- data/examples/blog/root/m/bubbles.gif +0 -0
- data/examples/blog/root/m/comments_curve.gif +0 -0
- data/examples/blog/root/m/down.gif +0 -0
- data/examples/blog/root/m/footer_bg.gif +0 -0
- data/examples/blog/root/m/garrow.gif +0 -0
- data/examples/blog/root/m/gbull.gif +0 -0
- data/examples/blog/root/m/grbull.gif +0 -0
- data/examples/blog/root/m/h1_bg.gif +0 -0
- data/examples/blog/root/m/header_bg.gif +0 -0
- data/examples/blog/root/m/obull.gif +0 -0
- data/examples/blog/root/m/page_bg.gif +0 -0
- data/examples/blog/root/m/side_title_bg.gif +0 -0
- data/examples/blog/root/m/sidebar_bg.gif +0 -0
- data/examples/blog/root/recent_posts.xhtml +14 -0
- data/examples/blog/root/style.css +201 -0
- data/examples/blog/root/style.xsl +118 -0
- data/examples/blog/root/view_entry.xhtml +29 -0
- data/examples/og/run.rb +27 -29
- data/examples/tiny/README +3 -4
- data/examples/tiny/app.rb +6 -16
- data/examples/tiny/config.rb +30 -0
- data/examples/tiny/log/app.log +23 -0
- data/examples/tiny/root/{index.sx → index.xhtml} +3 -6
- data/lib/{n/std.rb → nitro.rb} +9 -4
- data/lib/{n → nitro}/application.rb +13 -7
- data/lib/{n → nitro}/config.rb +38 -8
- data/lib/{n → nitro}/events.rb +1 -1
- data/lib/{n → nitro}/l10n.rb +1 -1
- data/lib/{n → nitro}/logger.rb +8 -8
- data/lib/{n → nitro}/macros.rb +3 -3
- data/lib/{n → nitro}/mixins.rb +1 -1
- data/lib/nitro/properties.rb +301 -0
- data/lib/{n → nitro}/server.rb +2 -2
- data/lib/{n → nitro}/server/appserver.rb +14 -5
- data/lib/{n → nitro}/server/cluster.rb +5 -5
- data/lib/{n → nitro}/server/cookie.rb +1 -1
- data/lib/nitro/server/dispatcher.rb +66 -0
- data/lib/{n → nitro}/server/filters.rb +7 -7
- data/lib/{n → nitro}/server/filters/autologin.rb +3 -3
- data/lib/{n → nitro}/server/fragment.rb +3 -3
- data/lib/{n → nitro}/server/handlers.rb +3 -3
- data/lib/nitro/server/render.rb +200 -0
- data/lib/{n → nitro}/server/request.rb +6 -6
- data/lib/{n → nitro}/server/requestpart.rb +5 -5
- data/lib/{n → nitro}/server/script.rb +3 -3
- data/lib/{n → nitro}/server/server.rb +4 -4
- data/lib/{n → nitro}/server/session.rb +3 -3
- data/lib/nitro/server/shaders.rb +165 -0
- data/lib/{n → nitro}/server/user.rb +1 -1
- data/lib/nitro/server/webrick.rb +175 -0
- data/lib/nitro/service.rb +25 -0
- data/lib/{n → nitro}/sitemap.rb +2 -2
- data/lib/{n → nitro}/ui/date-select.rb +0 -0
- data/lib/{n → nitro}/ui/pager.rb +1 -1
- data/lib/{n → nitro}/ui/popup.rb +1 -1
- data/lib/{n → nitro}/ui/select.rb +1 -1
- data/lib/{n → nitro}/ui/tabs.rb +1 -1
- data/lib/{n → nitro}/utils/array.rb +1 -1
- data/lib/{n → nitro}/utils/cache.rb +1 -1
- data/lib/{n → nitro}/utils/gfx.rb +1 -1
- data/lib/{n → nitro}/utils/hash.rb +1 -1
- data/lib/{n → nitro}/utils/html.rb +1 -1
- data/lib/{n → nitro}/utils/http.rb +1 -1
- data/lib/{n → nitro}/utils/mail.rb +1 -1
- data/lib/{n → nitro}/utils/number.rb +1 -1
- data/lib/{n → nitro}/utils/pool.rb +1 -1
- data/lib/{n → nitro}/utils/string.rb +19 -95
- data/lib/{n → nitro}/utils/template.rb +0 -0
- data/lib/{n → nitro}/utils/time.rb +1 -1
- data/lib/{n → nitro}/utils/uri.rb +3 -3
- data/lib/nitro/version.rb +11 -0
- data/lib/{n/og.rb → og.rb} +61 -31
- data/lib/{n/og → og}/backend.rb +13 -7
- data/lib/{n/og → og}/backends/mysql.rb +43 -39
- data/lib/{n/og → og}/backends/psql.rb +42 -38
- data/lib/{n/og → og}/connection.rb +21 -9
- data/lib/{n/og → og}/meta.rb +18 -12
- data/lib/xsl/base.xsl +11 -88
- data/test/n/server/tc_cookie.rb +1 -1
- data/test/n/server/tc_filters.rb +1 -1
- data/test/n/server/tc_request.rb +3 -3
- data/test/n/server/tc_requestpart.rb +2 -2
- data/test/n/server/tc_session.rb +1 -1
- data/test/n/tc_events.rb +1 -1
- data/test/n/tc_og.rb +16 -18
- data/test/n/tc_properties.rb +22 -18
- data/test/n/tc_sitemap.rb +2 -2
- data/test/n/ui/tc_pager.rb +4 -4
- data/test/n/utils/tc_cache.rb +1 -1
- data/test/n/utils/tc_hash.rb +1 -1
- data/test/n/utils/tc_html.rb +1 -1
- data/test/n/utils/tc_http.rb +1 -1
- data/test/n/utils/tc_number.rb +1 -1
- data/test/n/utils/tc_strings.rb +1 -46
- data/test/n/utils/tc_uri.rb +1 -1
- metadata +101 -108
- data/examples/simple/README +0 -42
- data/examples/simple/app.rb +0 -31
- data/examples/simple/conf/apache.conf +0 -100
- data/examples/simple/conf/config.rb +0 -72
- data/examples/simple/conf/debug-config.rb +0 -26
- data/examples/simple/conf/live-config.rb +0 -26
- data/examples/simple/conf/requires.rb +0 -43
- data/examples/simple/ctl +0 -32
- data/examples/simple/env.rb +0 -32
- data/examples/simple/install.rb +0 -12
- data/examples/simple/lib/articles/entities.rb +0 -37
- data/examples/simple/lib/articles/lc-en.rb +0 -36
- data/examples/simple/lib/articles/methods.rb +0 -55
- data/examples/simple/lib/articles/part.rb +0 -57
- data/examples/simple/root/add-article.sx +0 -15
- data/examples/simple/root/article-form.ss +0 -20
- data/examples/simple/root/comments-form.ss +0 -16
- data/examples/simple/root/comments.si +0 -30
- data/examples/simple/root/index.sx +0 -44
- data/examples/simple/root/shader/shader.xsl +0 -100
- data/examples/simple/root/shader/style.css +0 -9
- data/examples/simple/root/view-article.sx +0 -29
- data/examples/tiny/conf/config.rb +0 -62
- data/examples/tiny/conf/requires.rb +0 -33
- data/examples/tiny/ctl +0 -16
- data/lib/n/parts.rb +0 -157
- data/lib/n/properties.rb +0 -199
- data/lib/n/server/dispatcher.rb +0 -55
- data/lib/n/server/handlers/code-handler.rb +0 -182
- data/lib/n/server/handlers/page-handler.rb +0 -612
- data/lib/n/server/webrick.rb +0 -283
- data/lib/n/shaders.rb +0 -166
- data/lib/n/sync/clc.rb +0 -110
- data/lib/n/sync/handler.rb +0 -229
- data/lib/n/sync/server.rb +0 -176
- data/lib/p/README +0 -1
data/examples/tiny/README
CHANGED
data/examples/tiny/app.rb
CHANGED
@@ -8,23 +8,13 @@
|
|
8
8
|
# * George Moschovitis <gm@navel.gr>
|
9
9
|
#
|
10
10
|
# (c) 2004 Navel, all rights reserved.
|
11
|
-
# $Id: app.rb
|
11
|
+
# $Id: app.rb 146 2004-11-13 19:05:06Z gmosx $
|
12
12
|
|
13
|
-
|
13
|
+
$DBG = false
|
14
14
|
|
15
|
-
|
16
|
-
$
|
15
|
+
$LOAD_PATH.unshift "lib"
|
16
|
+
$LOAD_PATH.unshift "../../lib"
|
17
17
|
|
18
|
-
require "
|
19
|
-
require "n/server/webrick"
|
20
|
-
|
21
|
-
module App
|
22
|
-
|
23
|
-
class Server < N::Webrick
|
24
|
-
include App::Config
|
25
|
-
end
|
26
|
-
|
27
|
-
end # module
|
28
|
-
|
29
|
-
$app = App::Server.new.exec()
|
18
|
+
require "config"
|
30
19
|
|
20
|
+
$app = N::WebrickServer.new.exec()
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# = Tiny Configuration
|
2
|
+
#
|
3
|
+
# You can find additional configuration variables in
|
4
|
+
# lib/n/config.rb. Just copy the variables you want to
|
5
|
+
# change in this file
|
6
|
+
#
|
7
|
+
# code:
|
8
|
+
# * George Moschovitis <gm@navel.gr>
|
9
|
+
#
|
10
|
+
# (c) 2004 Navel, all rights reserved.
|
11
|
+
# $Id: config.rb 155 2004-11-13 20:32:12Z gmosx $
|
12
|
+
|
13
|
+
require "nitro"
|
14
|
+
require "nitro/logger"
|
15
|
+
require "nitro/config"
|
16
|
+
|
17
|
+
require "nitro/utils/number"
|
18
|
+
require "nitro/utils/string"
|
19
|
+
require "nitro/utils/array"
|
20
|
+
require "nitro/utils/hash"
|
21
|
+
require "nitro/utils/html"
|
22
|
+
require "nitro/utils/gfx"
|
23
|
+
|
24
|
+
require "nitro/server/webrick"
|
25
|
+
|
26
|
+
$name = "Tiny Example"
|
27
|
+
|
28
|
+
$srv_address = $appsrv_address = "127.0.0.1"
|
29
|
+
$srv_port = 8080
|
30
|
+
$srv_url = "http://#$srv_address:#$srv_port"
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Logfile created on Sat Nov 13 20:02:50 EET 2004 by logger.rb/1.5.2.4
|
2
|
+
I: Web Server listening at http://127.0.0.1:8080
|
3
|
+
I: App Server listening at http://127.0.0.1:9090
|
4
|
+
I: Web Server listening at http://127.0.0.1:8080
|
5
|
+
I: App Server listening at http://127.0.0.1:9090
|
6
|
+
I: Web Server listening at http://127.0.0.1:8080
|
7
|
+
I: App Server listening at http://127.0.0.1:9090
|
8
|
+
I: Web Server listening at http://127.0.0.1:8080
|
9
|
+
I: App Server listening at http://127.0.0.1:9090
|
10
|
+
I: Web Server listening at http://127.0.0.1:8080
|
11
|
+
I: App Server listening at http://127.0.0.1:9090
|
12
|
+
I: Web Server listening at http://127.0.0.1:8080
|
13
|
+
I: App Server listening at http://127.0.0.1:9090
|
14
|
+
I: Web Server listening at http://127.0.0.1:8080
|
15
|
+
I: App Server listening at http://127.0.0.1:9090
|
16
|
+
I: Web Server listening at http://127.0.0.1:8080
|
17
|
+
I: App Server listening at http://127.0.0.1:9090
|
18
|
+
I: Web Server listening at http://127.0.0.1:8080
|
19
|
+
I: App Server listening at http://127.0.0.1:9090
|
20
|
+
INFO: Web Server listening at http://127.0.0.1:8080
|
21
|
+
INFO: App Server listening at http://127.0.0.1:9090
|
22
|
+
INFO: Web Server listening at http://127.0.0.1:8080
|
23
|
+
INFO: App Server listening at http://127.0.0.1:9090
|
@@ -5,14 +5,11 @@
|
|
5
5
|
<?r
|
6
6
|
# the code that populates the template comes here
|
7
7
|
|
8
|
-
unless name =
|
9
|
-
name =
|
8
|
+
unless name = params['name']
|
9
|
+
name = 'World'
|
10
10
|
end
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
session = request.session
|
15
|
-
session[:counter] = 0 unless session[:counter]
|
12
|
+
session[:counter] ||= 0
|
16
13
|
session[:counter] += 1
|
17
14
|
?>
|
18
15
|
|
data/lib/{n/std.rb → nitro.rb}
RENAMED
@@ -1,12 +1,18 @@
|
|
1
|
-
# = Nitro
|
1
|
+
# = Nitro
|
2
2
|
#
|
3
|
-
#
|
3
|
+
# Nitro is an efficient, yet simple engine for developing professional
|
4
|
+
# Web Applications using the Ruby language. Nitro aims to provide a
|
5
|
+
# robust infrastructure for scalable web applications that can be
|
6
|
+
# distributed over a server cluster. However, Nitro can also power
|
7
|
+
# simple web applications for deployment on intranets or even personal
|
8
|
+
# computers. Nitro integrates the powerful Og Object-Relational mapping
|
9
|
+
# library.
|
4
10
|
#
|
5
11
|
# code:
|
6
12
|
# * George Moschovitis <gm@navel.gr>
|
7
13
|
#
|
8
14
|
# (c) 2004 Navel, all rights reserved.
|
9
|
-
# $Id:
|
15
|
+
# $Id: nitro.rb 155 2004-11-13 20:32:12Z gmosx $
|
10
16
|
|
11
17
|
# we want readable code
|
12
18
|
|
@@ -50,4 +56,3 @@ end
|
|
50
56
|
# predefine some comonly used objects
|
51
57
|
|
52
58
|
EMPTY_STRING = ""
|
53
|
-
|
@@ -9,13 +9,13 @@
|
|
9
9
|
# Elias Karakoulakis <ekarak@ktismata.com>
|
10
10
|
#
|
11
11
|
# (c) 2004 Navel, all rights reserved.
|
12
|
-
# $Id: application.rb
|
12
|
+
# $Id: application.rb 155 2004-11-13 20:32:12Z gmosx $
|
13
13
|
|
14
14
|
require 'optparse'
|
15
15
|
require 'ostruct'
|
16
16
|
|
17
|
-
require "
|
18
|
-
require "
|
17
|
+
require "nitro/logger"
|
18
|
+
require "nitro"
|
19
19
|
|
20
20
|
module N
|
21
21
|
|
@@ -64,22 +64,22 @@ class Application
|
|
64
64
|
opts.separator "Specific options:"
|
65
65
|
|
66
66
|
opts.on("-s", "--start",
|
67
|
-
"Start
|
67
|
+
"Start '#$name'.") {
|
68
68
|
start()
|
69
69
|
}
|
70
70
|
|
71
71
|
opts.on("-S", "--stop",
|
72
|
-
"Stop
|
72
|
+
"Stop '#$name'.") {
|
73
73
|
stop()
|
74
74
|
}
|
75
75
|
|
76
76
|
opts.on("-r", "--restart",
|
77
|
-
"Restart
|
77
|
+
"Restart '#$name'.") {
|
78
78
|
restart()
|
79
79
|
}
|
80
80
|
|
81
81
|
opts.on("-d", "--daemon",
|
82
|
-
"Run
|
82
|
+
"Run '#$name' as a daemon.") {
|
83
83
|
daemonize()
|
84
84
|
start()
|
85
85
|
}
|
@@ -88,6 +88,12 @@ class Application
|
|
88
88
|
puts opts
|
89
89
|
exit
|
90
90
|
}
|
91
|
+
|
92
|
+
opts.on_tail("-v", "--version", "Show version.") {
|
93
|
+
puts $srv_version
|
94
|
+
exit
|
95
|
+
}
|
96
|
+
|
91
97
|
}
|
92
98
|
begin
|
93
99
|
opts.parse!(args)
|
data/lib/{n → nitro}/config.rb
RENAMED
@@ -6,13 +6,13 @@
|
|
6
6
|
# * George Moschovitis <gm@navel.gr>
|
7
7
|
#
|
8
8
|
# (c) 2004 Navel, all rights reserved.
|
9
|
-
# $Id: config.rb
|
9
|
+
# $Id: config.rb 155 2004-11-13 20:32:12Z gmosx $
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
11
|
+
require 'nitro/logger'
|
12
|
+
require 'nitro/utils/hash'
|
13
|
+
require 'nitro/version'
|
14
|
+
require 'nitro/service'
|
15
|
+
require 'nitro/server/shaders'
|
16
16
|
|
17
17
|
# monitor scripts for changes
|
18
18
|
#--
|
@@ -20,10 +20,14 @@ $srv_version = "0.3.0"
|
|
20
20
|
#++
|
21
21
|
$srv_monitor_scripts = true
|
22
22
|
|
23
|
+
# The root (public) directory.
|
24
|
+
$root_dir = "root"
|
25
|
+
|
23
26
|
# the default file to view in a direcotry
|
24
27
|
$index_filename = "index.sx"
|
25
28
|
|
26
29
|
# seconds till the autologin cookie expires
|
30
|
+
# TODO: move to filter.
|
27
31
|
$srv_autologin_expires = 60*60*24*30
|
28
32
|
|
29
33
|
# session timeout (in seconds)
|
@@ -39,7 +43,29 @@ $drb_state = false
|
|
39
43
|
$error_page_url = nil
|
40
44
|
|
41
45
|
# default encoding for the app.
|
42
|
-
$encoding =
|
46
|
+
$encoding = 'iso-8859-1'
|
47
|
+
|
48
|
+
# default content type.
|
49
|
+
$default_content_type = 'text/html'
|
50
|
+
|
51
|
+
# The services map.
|
52
|
+
# :index represents the '/' mount point
|
53
|
+
$services = { :index => N::Service }
|
54
|
+
|
55
|
+
# The service method map.
|
56
|
+
$methods = N::SafeHash.new
|
57
|
+
|
58
|
+
# The shader. The default shader is very simple, here
|
59
|
+
# is a typical example of a production shader pipeline:
|
60
|
+
#
|
61
|
+
# <tt>
|
62
|
+
# $shader = N::XSLTShader.new("#$root_dir/style.xsl",
|
63
|
+
# N::RubyShader.new(
|
64
|
+
# N::CompressShader.new
|
65
|
+
# )
|
66
|
+
# )
|
67
|
+
# </tt>
|
68
|
+
$shader = N::RubyShader.new
|
43
69
|
|
44
70
|
if $DBG
|
45
71
|
|
@@ -63,13 +89,16 @@ if $DBG
|
|
63
89
|
|
64
90
|
$srv_address = $appsrv_address = "127.0.0.1"
|
65
91
|
$srv_port = 8080
|
66
|
-
$appsrv_port =
|
92
|
+
$appsrv_port = 8080
|
67
93
|
$srv_url = "http://#$srv_address:#$srv_port"
|
68
94
|
|
69
95
|
else
|
70
96
|
|
71
97
|
puts "\nRunning LIVE configuration.\n\n"
|
72
98
|
|
99
|
+
$log = Logger.new("log/app.log", 10);
|
100
|
+
$log.level = Logger::INFO
|
101
|
+
|
73
102
|
# If set to true disables xsl caching. Usefull when debugging xsls.
|
74
103
|
|
75
104
|
$reload_xsl = false
|
@@ -86,4 +115,5 @@ else
|
|
86
115
|
$srv_port = 8080
|
87
116
|
$appsrv_port = 9090
|
88
117
|
$srv_url = "http://#$srv_address:#$srv_port"
|
118
|
+
|
89
119
|
end
|
data/lib/{n → nitro}/events.rb
RENAMED
data/lib/{n → nitro}/l10n.rb
RENAMED
data/lib/{n → nitro}/logger.rb
RENAMED
@@ -7,7 +7,7 @@
|
|
7
7
|
# * George Moschovitis <gm@navel.gr>
|
8
8
|
#
|
9
9
|
# (c) 2004 Navel, all rights reserved.
|
10
|
-
# $Id: logger.rb
|
10
|
+
# $Id: logger.rb 152 2004-11-13 20:02:35Z gmosx $
|
11
11
|
|
12
12
|
require "logger"
|
13
13
|
|
@@ -38,14 +38,14 @@ class Logger
|
|
38
38
|
|
39
39
|
private
|
40
40
|
|
41
|
-
|
42
|
-
|
43
|
-
|
41
|
+
# the default Ruby logger has a hardwired silly format.
|
42
|
+
# we use some Ruby magic to fix it!
|
43
|
+
remove_const "Format"
|
44
44
|
|
45
|
-
|
45
|
+
Format = "%5s: %s\n"
|
46
46
|
|
47
|
-
|
48
|
-
|
49
|
-
|
47
|
+
def format_message(severity, timestamp, msg, progname)
|
48
|
+
Format % [severity, msg]
|
49
|
+
end
|
50
50
|
end
|
51
51
|
|
data/lib/{n → nitro}/macros.rb
RENAMED
@@ -9,7 +9,7 @@
|
|
9
9
|
# George Moschovitis <gm@navel.gr>
|
10
10
|
#
|
11
11
|
# (c) 2004 Navel, all rights reserved.
|
12
|
-
# $Id: macros.rb
|
12
|
+
# $Id: macros.rb 155 2004-11-13 20:32:12Z gmosx $
|
13
13
|
|
14
14
|
$__macros__ = {}
|
15
15
|
$__required__ = {}
|
@@ -39,8 +39,8 @@ end
|
|
39
39
|
|
40
40
|
end
|
41
41
|
|
42
|
-
require "
|
43
|
-
require "
|
42
|
+
require "nitro/test1.rb"
|
43
|
+
require "nitro/test2.rb"
|
44
44
|
|
45
45
|
__END__
|
46
46
|
|
data/lib/{n → nitro}/mixins.rb
RENAMED
@@ -0,0 +1,301 @@
|
|
1
|
+
# code:
|
2
|
+
# * George Moschovitis <gm@navel.gr>
|
3
|
+
# design:
|
4
|
+
# * Anastastios Koutoumanos <ak@navel.gr>
|
5
|
+
# * Elias Karakoulakis <ekarak@ktismata.com>
|
6
|
+
#
|
7
|
+
# (c) 2004 Navel, all rights reserved.
|
8
|
+
# $Id: properties.rb 155 2004-11-13 20:32:12Z gmosx $
|
9
|
+
|
10
|
+
require "nitro/utils/array"
|
11
|
+
require "nitro/utils/hash"
|
12
|
+
|
13
|
+
module N
|
14
|
+
|
15
|
+
# = Property
|
16
|
+
#
|
17
|
+
# Ruby attributes are typeless and generally this is good. Some times
|
18
|
+
# we need extra metadata though, for example in relational mapping,
|
19
|
+
# or web form population.
|
20
|
+
#
|
21
|
+
# Only Fixnums, Strings, Floats, Times, Booleans are converted.
|
22
|
+
#
|
23
|
+
# The default = methods do not force the types. A special
|
24
|
+
# __force_set method should be used instead.
|
25
|
+
#
|
26
|
+
#--
|
27
|
+
# TODO:
|
28
|
+
# Inject only the really needd methods into Module.
|
29
|
+
# Perhaps a sync is needed in evals (!!!!)
|
30
|
+
#++
|
31
|
+
#
|
32
|
+
class Property
|
33
|
+
# the symbol of the property
|
34
|
+
attr_accessor :symbol
|
35
|
+
# the string representation of the symbol
|
36
|
+
attr_accessor :name
|
37
|
+
# the class of the property
|
38
|
+
attr_accessor :klass
|
39
|
+
# additional metadata (like sql declaratio, sql index, etc)
|
40
|
+
attr_accessor :meta
|
41
|
+
|
42
|
+
def initialize(symbol, klass, meta = {})
|
43
|
+
@symbol, @klass = symbol, klass
|
44
|
+
@meta = meta
|
45
|
+
@name = @symbol.to_s()
|
46
|
+
end
|
47
|
+
|
48
|
+
def ==(other)
|
49
|
+
return @symbol == other.symbol
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end # module
|
54
|
+
|
55
|
+
class Module
|
56
|
+
|
57
|
+
# Define a property (== typed attribute)
|
58
|
+
# This works like Ruby's standard attr method, ie creates
|
59
|
+
# only one property.
|
60
|
+
#
|
61
|
+
# Use the prop_reader, prop_writer, prop_accessor methods
|
62
|
+
# for multiple properties.
|
63
|
+
#
|
64
|
+
# Examples:
|
65
|
+
# prop String, :name, :sql => "char(32), :sql_index => "name(32)"
|
66
|
+
# --> creates only writer.
|
67
|
+
# prop Fixnum, :oid, writer = true, :sql => "integer PRIMARY KEY"
|
68
|
+
# --> creates reader and writer.
|
69
|
+
#
|
70
|
+
def prop(*params)
|
71
|
+
meta = {}
|
72
|
+
klass = Object
|
73
|
+
|
74
|
+
for param in params
|
75
|
+
if param.is_a?(Class)
|
76
|
+
klass = param
|
77
|
+
elsif param.is_a?(Symbol)
|
78
|
+
symbol = param
|
79
|
+
elsif param.is_a?(TrueClass) or param.is_a?(TrueClass)
|
80
|
+
writer = param
|
81
|
+
elsif param.is_a?(Hash)
|
82
|
+
# the meta hash.
|
83
|
+
meta = param
|
84
|
+
else
|
85
|
+
raise "Error when defining property!"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
unless self.methods.include?("__props")
|
90
|
+
eval %{
|
91
|
+
# Properties
|
92
|
+
# An array is used to enforce order.
|
93
|
+
def __props
|
94
|
+
@__props
|
95
|
+
end
|
96
|
+
|
97
|
+
def __props=(props)
|
98
|
+
@__props = props
|
99
|
+
end
|
100
|
+
|
101
|
+
def __meta
|
102
|
+
@__meta
|
103
|
+
end
|
104
|
+
|
105
|
+
def __meta=(meta)
|
106
|
+
@__meta = meta
|
107
|
+
end
|
108
|
+
}
|
109
|
+
end
|
110
|
+
|
111
|
+
@__props = N::SafeArray.new() unless @__props
|
112
|
+
|
113
|
+
property = N::Property.new(symbol, klass, meta)
|
114
|
+
|
115
|
+
reader = meta[:reader] || true
|
116
|
+
writer = writer || meta[:writer] || false
|
117
|
+
|
118
|
+
__add_prop(property, reader, writer)
|
119
|
+
end
|
120
|
+
|
121
|
+
# Helper method. Accepts a collection of symbols and generates
|
122
|
+
# properties. Only generates reader.
|
123
|
+
#
|
124
|
+
# Example:
|
125
|
+
# prop_reader String, :name, :title, :body, :sql => "char(32)"
|
126
|
+
#
|
127
|
+
def prop_reader(*params)
|
128
|
+
meta = {}
|
129
|
+
klass = Object
|
130
|
+
symbols = []
|
131
|
+
|
132
|
+
for param in params
|
133
|
+
if param.is_a?(Class)
|
134
|
+
klass = param
|
135
|
+
elsif param.is_a?(Symbol)
|
136
|
+
symbols << param
|
137
|
+
elsif param.is_a?(Hash)
|
138
|
+
# the meta hash.
|
139
|
+
meta = param
|
140
|
+
else
|
141
|
+
raise "Error when defining property!"
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
meta[:reader] = true
|
146
|
+
meta[:writer] = false
|
147
|
+
|
148
|
+
for symbol in symbols
|
149
|
+
prop(klass, symbol, meta)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# Helper method. Accepts a collection of symbols and generates
|
154
|
+
# properties. Only generates writer.
|
155
|
+
#
|
156
|
+
# Example:
|
157
|
+
# prop_writer String, :name, :title, :body, :sql => "char(32)"
|
158
|
+
#
|
159
|
+
def prop_writer(*params)
|
160
|
+
meta = {}
|
161
|
+
klass = Object
|
162
|
+
symbols = []
|
163
|
+
|
164
|
+
for param in params
|
165
|
+
if param.is_a?(Class)
|
166
|
+
klass = param
|
167
|
+
elsif param.is_a?(Symbol)
|
168
|
+
symbols << param
|
169
|
+
elsif param.is_a?(Hash)
|
170
|
+
# the meta hash.
|
171
|
+
meta = param
|
172
|
+
else
|
173
|
+
raise "Error when defining property!"
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
meta[:reader] = false
|
178
|
+
meta[:writer] = true
|
179
|
+
|
180
|
+
for symbol in symbols
|
181
|
+
prop(klass, symbol, meta)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
# Helper method. Accepts a collection of symbols and generates
|
186
|
+
# properties. Generates reader and writer.
|
187
|
+
#
|
188
|
+
# Example:
|
189
|
+
# prop_accessor String, :name, :title, :body, :sql => "char(32)"
|
190
|
+
#
|
191
|
+
def prop_accessor(*params)
|
192
|
+
meta = {}
|
193
|
+
klass = Object
|
194
|
+
symbols = []
|
195
|
+
|
196
|
+
for param in params
|
197
|
+
if param.is_a?(Class)
|
198
|
+
klass = param
|
199
|
+
elsif param.is_a?(Symbol)
|
200
|
+
symbols << param
|
201
|
+
elsif param.is_a?(Hash)
|
202
|
+
# the meta hash.
|
203
|
+
meta = param
|
204
|
+
else
|
205
|
+
raise "Error when defining property!"
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
meta[:reader] = true
|
210
|
+
meta[:writer] = true
|
211
|
+
|
212
|
+
for symbol in symbols
|
213
|
+
prop(klass, symbol, meta)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
# Add the property
|
218
|
+
#
|
219
|
+
def __add_prop(prop, reader = true, writer = true)
|
220
|
+
if idx = @__props.index(prop)
|
221
|
+
# override in case of duplicates. Keep the order of the props.
|
222
|
+
@__props[idx] = prop
|
223
|
+
else
|
224
|
+
@__props << prop
|
225
|
+
end
|
226
|
+
|
227
|
+
# Precompile the property read/write methods
|
228
|
+
|
229
|
+
s, klass = prop.symbol, prop.klass
|
230
|
+
|
231
|
+
if reader
|
232
|
+
module_eval %{
|
233
|
+
def #{s}
|
234
|
+
return @#{s}
|
235
|
+
end
|
236
|
+
}
|
237
|
+
end
|
238
|
+
|
239
|
+
if writer
|
240
|
+
module_eval %{
|
241
|
+
def #{s}=(val)
|
242
|
+
@#{s} = val
|
243
|
+
end
|
244
|
+
|
245
|
+
def __force_#{s}(val)
|
246
|
+
@#{s} = } + case klass.name
|
247
|
+
when Fixnum.name
|
248
|
+
"val.to_i()"
|
249
|
+
when String.name
|
250
|
+
"val.to_s()"
|
251
|
+
when Float.name
|
252
|
+
"val.to_f()"
|
253
|
+
when Time.name
|
254
|
+
"Time.parse(val.to_s())"
|
255
|
+
when TrueClass.name, FalseClass.name
|
256
|
+
"val.to_i() > 0"
|
257
|
+
else
|
258
|
+
"val"
|
259
|
+
end + %{
|
260
|
+
end
|
261
|
+
}
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
# Attach metadata
|
266
|
+
#
|
267
|
+
def meta(key, val)
|
268
|
+
@__meta = N::SafeHash.new unless @__meta
|
269
|
+
|
270
|
+
@__meta[key] = [] unless @__meta[key]
|
271
|
+
|
272
|
+
# guard against duplicates, no need to keep order.
|
273
|
+
@__meta[key].delete_if { |v| val == v }
|
274
|
+
@__meta[key] << val
|
275
|
+
end
|
276
|
+
|
277
|
+
# This method is typically called before including other
|
278
|
+
# modules to preserve properties order.
|
279
|
+
#
|
280
|
+
def inherit_meta(mod = superclass)
|
281
|
+
# concat props.
|
282
|
+
if mod.__props
|
283
|
+
@__props = N::SafeArray.new unless @__props
|
284
|
+
|
285
|
+
mod.__props.each { |p|
|
286
|
+
__add_prop(p)
|
287
|
+
}
|
288
|
+
end
|
289
|
+
|
290
|
+
# concat metadata
|
291
|
+
if mod.__meta
|
292
|
+
mod.__meta.each { |k, val|
|
293
|
+
val.each { |v|
|
294
|
+
meta(k, v)
|
295
|
+
} if val
|
296
|
+
}
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
end
|
301
|
+
|