nitro 0.3.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
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
+