nitro 0.3.0 → 0.4.1

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 (148) hide show
  1. data/ChangeLog +284 -0
  2. data/{LICENCE → LICENSE} +1 -1
  3. data/README +13 -17
  4. data/RELEASES +13 -1
  5. data/Rakefile +1 -9
  6. data/bin/cluster.rb +5 -5
  7. data/examples/blog/README +45 -0
  8. data/examples/blog/apache.conf +0 -0
  9. data/examples/blog/app.rb +21 -0
  10. data/examples/blog/config.rb +88 -0
  11. data/examples/blog/lib/blog.rb +104 -0
  12. data/examples/blog/log/app.log +117 -0
  13. data/examples/blog/root/comments.xhtml +38 -0
  14. data/examples/blog/root/entry_form.xhtml +18 -0
  15. data/examples/blog/root/index.xhtml +43 -0
  16. data/examples/blog/root/login.xhtml +24 -0
  17. data/examples/blog/root/m/bubbles.gif +0 -0
  18. data/examples/blog/root/m/comments_curve.gif +0 -0
  19. data/examples/blog/root/m/down.gif +0 -0
  20. data/examples/blog/root/m/footer_bg.gif +0 -0
  21. data/examples/blog/root/m/garrow.gif +0 -0
  22. data/examples/blog/root/m/gbull.gif +0 -0
  23. data/examples/blog/root/m/grbull.gif +0 -0
  24. data/examples/blog/root/m/h1_bg.gif +0 -0
  25. data/examples/blog/root/m/header_bg.gif +0 -0
  26. data/examples/blog/root/m/obull.gif +0 -0
  27. data/examples/blog/root/m/page_bg.gif +0 -0
  28. data/examples/blog/root/m/side_title_bg.gif +0 -0
  29. data/examples/blog/root/m/sidebar_bg.gif +0 -0
  30. data/examples/blog/root/recent_posts.xhtml +14 -0
  31. data/examples/blog/root/style.css +201 -0
  32. data/examples/blog/root/style.xsl +118 -0
  33. data/examples/blog/root/view_entry.xhtml +29 -0
  34. data/examples/og/run.rb +27 -29
  35. data/examples/tiny/README +3 -4
  36. data/examples/tiny/app.rb +6 -16
  37. data/examples/tiny/config.rb +30 -0
  38. data/examples/tiny/log/app.log +23 -0
  39. data/examples/tiny/root/{index.sx → index.xhtml} +3 -6
  40. data/lib/{n/std.rb → nitro.rb} +9 -4
  41. data/lib/{n → nitro}/application.rb +13 -7
  42. data/lib/{n → nitro}/config.rb +38 -8
  43. data/lib/{n → nitro}/events.rb +1 -1
  44. data/lib/{n → nitro}/l10n.rb +1 -1
  45. data/lib/{n → nitro}/logger.rb +8 -8
  46. data/lib/{n → nitro}/macros.rb +3 -3
  47. data/lib/{n → nitro}/mixins.rb +1 -1
  48. data/lib/nitro/properties.rb +301 -0
  49. data/lib/{n → nitro}/server.rb +2 -2
  50. data/lib/{n → nitro}/server/appserver.rb +14 -5
  51. data/lib/{n → nitro}/server/cluster.rb +5 -5
  52. data/lib/{n → nitro}/server/cookie.rb +1 -1
  53. data/lib/nitro/server/dispatcher.rb +66 -0
  54. data/lib/{n → nitro}/server/filters.rb +7 -7
  55. data/lib/{n → nitro}/server/filters/autologin.rb +3 -3
  56. data/lib/{n → nitro}/server/fragment.rb +3 -3
  57. data/lib/{n → nitro}/server/handlers.rb +3 -3
  58. data/lib/nitro/server/render.rb +200 -0
  59. data/lib/{n → nitro}/server/request.rb +6 -6
  60. data/lib/{n → nitro}/server/requestpart.rb +5 -5
  61. data/lib/{n → nitro}/server/script.rb +3 -3
  62. data/lib/{n → nitro}/server/server.rb +4 -4
  63. data/lib/{n → nitro}/server/session.rb +3 -3
  64. data/lib/nitro/server/shaders.rb +165 -0
  65. data/lib/{n → nitro}/server/user.rb +1 -1
  66. data/lib/nitro/server/webrick.rb +175 -0
  67. data/lib/nitro/service.rb +25 -0
  68. data/lib/{n → nitro}/sitemap.rb +2 -2
  69. data/lib/{n → nitro}/ui/date-select.rb +0 -0
  70. data/lib/{n → nitro}/ui/pager.rb +1 -1
  71. data/lib/{n → nitro}/ui/popup.rb +1 -1
  72. data/lib/{n → nitro}/ui/select.rb +1 -1
  73. data/lib/{n → nitro}/ui/tabs.rb +1 -1
  74. data/lib/{n → nitro}/utils/array.rb +1 -1
  75. data/lib/{n → nitro}/utils/cache.rb +1 -1
  76. data/lib/{n → nitro}/utils/gfx.rb +1 -1
  77. data/lib/{n → nitro}/utils/hash.rb +1 -1
  78. data/lib/{n → nitro}/utils/html.rb +1 -1
  79. data/lib/{n → nitro}/utils/http.rb +1 -1
  80. data/lib/{n → nitro}/utils/mail.rb +1 -1
  81. data/lib/{n → nitro}/utils/number.rb +1 -1
  82. data/lib/{n → nitro}/utils/pool.rb +1 -1
  83. data/lib/{n → nitro}/utils/string.rb +19 -95
  84. data/lib/{n → nitro}/utils/template.rb +0 -0
  85. data/lib/{n → nitro}/utils/time.rb +1 -1
  86. data/lib/{n → nitro}/utils/uri.rb +3 -3
  87. data/lib/nitro/version.rb +11 -0
  88. data/lib/{n/og.rb → og.rb} +61 -31
  89. data/lib/{n/og → og}/backend.rb +13 -7
  90. data/lib/{n/og → og}/backends/mysql.rb +43 -39
  91. data/lib/{n/og → og}/backends/psql.rb +42 -38
  92. data/lib/{n/og → og}/connection.rb +21 -9
  93. data/lib/{n/og → og}/meta.rb +18 -12
  94. data/lib/xsl/base.xsl +11 -88
  95. data/test/n/server/tc_cookie.rb +1 -1
  96. data/test/n/server/tc_filters.rb +1 -1
  97. data/test/n/server/tc_request.rb +3 -3
  98. data/test/n/server/tc_requestpart.rb +2 -2
  99. data/test/n/server/tc_session.rb +1 -1
  100. data/test/n/tc_events.rb +1 -1
  101. data/test/n/tc_og.rb +16 -18
  102. data/test/n/tc_properties.rb +22 -18
  103. data/test/n/tc_sitemap.rb +2 -2
  104. data/test/n/ui/tc_pager.rb +4 -4
  105. data/test/n/utils/tc_cache.rb +1 -1
  106. data/test/n/utils/tc_hash.rb +1 -1
  107. data/test/n/utils/tc_html.rb +1 -1
  108. data/test/n/utils/tc_http.rb +1 -1
  109. data/test/n/utils/tc_number.rb +1 -1
  110. data/test/n/utils/tc_strings.rb +1 -46
  111. data/test/n/utils/tc_uri.rb +1 -1
  112. metadata +101 -108
  113. data/examples/simple/README +0 -42
  114. data/examples/simple/app.rb +0 -31
  115. data/examples/simple/conf/apache.conf +0 -100
  116. data/examples/simple/conf/config.rb +0 -72
  117. data/examples/simple/conf/debug-config.rb +0 -26
  118. data/examples/simple/conf/live-config.rb +0 -26
  119. data/examples/simple/conf/requires.rb +0 -43
  120. data/examples/simple/ctl +0 -32
  121. data/examples/simple/env.rb +0 -32
  122. data/examples/simple/install.rb +0 -12
  123. data/examples/simple/lib/articles/entities.rb +0 -37
  124. data/examples/simple/lib/articles/lc-en.rb +0 -36
  125. data/examples/simple/lib/articles/methods.rb +0 -55
  126. data/examples/simple/lib/articles/part.rb +0 -57
  127. data/examples/simple/root/add-article.sx +0 -15
  128. data/examples/simple/root/article-form.ss +0 -20
  129. data/examples/simple/root/comments-form.ss +0 -16
  130. data/examples/simple/root/comments.si +0 -30
  131. data/examples/simple/root/index.sx +0 -44
  132. data/examples/simple/root/shader/shader.xsl +0 -100
  133. data/examples/simple/root/shader/style.css +0 -9
  134. data/examples/simple/root/view-article.sx +0 -29
  135. data/examples/tiny/conf/config.rb +0 -62
  136. data/examples/tiny/conf/requires.rb +0 -33
  137. data/examples/tiny/ctl +0 -16
  138. data/lib/n/parts.rb +0 -157
  139. data/lib/n/properties.rb +0 -199
  140. data/lib/n/server/dispatcher.rb +0 -55
  141. data/lib/n/server/handlers/code-handler.rb +0 -182
  142. data/lib/n/server/handlers/page-handler.rb +0 -612
  143. data/lib/n/server/webrick.rb +0 -283
  144. data/lib/n/shaders.rb +0 -166
  145. data/lib/n/sync/clc.rb +0 -110
  146. data/lib/n/sync/handler.rb +0 -229
  147. data/lib/n/sync/server.rb +0 -176
  148. data/lib/p/README +0 -1
@@ -7,9 +7,8 @@ An example to test Nitro.
7
7
 
8
8
  $ cd examples/tiny
9
9
 
10
- $ ./ctl
10
+ $ ruby app.rb --start
11
11
 
12
- to stop the example press Ctrl+C or execute the
13
- following command:
12
+ browse http://127.0.0.1:9090
14
13
 
15
- $ ./ctl stop
14
+ to stop the example press Ctrl+C
@@ -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 112 2004-10-27 10:59:55Z gmosx $
11
+ # $Id: app.rb 146 2004-11-13 19:05:06Z gmosx $
12
12
 
13
- $:.unshift "../lib"
13
+ $DBG = false
14
14
 
15
- # Set this to false to optimize for speed.
16
- $DBG = true
15
+ $LOAD_PATH.unshift "lib"
16
+ $LOAD_PATH.unshift "../../lib"
17
17
 
18
- require "tiny/conf/config"
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 = request["name"]
9
- name = "World"
8
+ unless name = params['name']
9
+ name = 'World'
10
10
  end
11
11
 
12
- # maintain a session variable
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
 
@@ -1,12 +1,18 @@
1
- # = Nitro standard require
1
+ # = Nitro
2
2
  #
3
- # General utilities. Typically included in all Nitro applications.
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: std.rb 123 2004-11-01 11:55:11Z gmosx $
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 98 2004-10-22 07:36:20Z gmosx $
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 "n/logger"
18
- require "n/std"
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 Navel's Application Server.") {
67
+ "Start '#$name'.") {
68
68
  start()
69
69
  }
70
70
 
71
71
  opts.on("-S", "--stop",
72
- "Stop Navel's Application Server.") {
72
+ "Stop '#$name'.") {
73
73
  stop()
74
74
  }
75
75
 
76
76
  opts.on("-r", "--restart",
77
- "Restart Navel's Application Server.") {
77
+ "Restart '#$name'.") {
78
78
  restart()
79
79
  }
80
80
 
81
81
  opts.on("-d", "--daemon",
82
- "Run Navel's Application Server as a daemon.") {
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)
@@ -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 116 2004-10-29 16:26:32Z gmosx $
9
+ # $Id: config.rb 155 2004-11-13 20:32:12Z gmosx $
10
10
 
11
- # the name of the server
12
- $srv_name = "Nitro"
13
-
14
- # the version of the server
15
- $srv_version = "0.3.0"
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 = "iso-8859-1"
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 = 9090
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
@@ -6,7 +6,7 @@
6
6
  # George Moschovitis <gm@navel.gr>
7
7
  #
8
8
  # (c) 2002-2003 Navel, all rights reserved.
9
- # $Id: events.rb 98 2004-10-22 07:36:20Z gmosx $
9
+ # $Id: events.rb 152 2004-11-13 20:02:35Z gmosx $
10
10
 
11
11
  module N;
12
12
 
@@ -3,7 +3,7 @@
3
3
  # code: tml
4
4
  #
5
5
  # (c) 2002-2003 Navel, all rights reserved.
6
- # $Id: l10n.rb 71 2004-10-18 10:50:22Z gmosx $
6
+ # $Id: l10n.rb 152 2004-11-13 20:02:35Z gmosx $
7
7
 
8
8
  $lc_en = {}
9
9
  $lc_el = {}
@@ -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 109 2004-10-27 09:12:45Z gmosx $
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
- # the default Ruby logger has a hardwired silly format.
42
- # we use some Ruby magic to fix it!
43
- remove_const "Format"
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
- Format = "%c: %s\n"
45
+ Format = "%5s: %s\n"
46
46
 
47
- def format_message(severity, timestamp, msg, progname)
48
- Format % [severity[0], msg]
49
- end
47
+ def format_message(severity, timestamp, msg, progname)
48
+ Format % [severity, msg]
49
+ end
50
50
  end
51
51
 
@@ -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 98 2004-10-22 07:36:20Z gmosx $
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 "n/test1.rb"
43
- require "n/test2.rb"
42
+ require "nitro/test1.rb"
43
+ require "nitro/test2.rb"
44
44
 
45
45
  __END__
46
46
 
@@ -42,5 +42,5 @@ module Expirable
42
42
  end
43
43
  end
44
44
  end
45
-
45
+
46
46
  end # module
@@ -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
+