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.
Files changed (99) hide show
  1. data/AUTHORS +4 -1
  2. data/ChangeLog +290 -7
  3. data/README +3 -3
  4. data/RELEASES +94 -0
  5. data/Rakefile +7 -7
  6. data/benchmark/og/bench.rb +11 -10
  7. data/{ChangeLog.1 → doc/ChangeLog.1} +0 -0
  8. data/doc/apache.txt +9 -0
  9. data/doc/architecture.txt +1 -27
  10. data/doc/bugs.txt +11 -4
  11. data/doc/config.txt +22 -0
  12. data/doc/og_config.txt +35 -0
  13. data/doc/og_tutorial.txt +595 -0
  14. data/doc/tutorial.txt +22 -0
  15. data/examples/blog/conf/apache.conf +30 -0
  16. data/examples/blog/conf/lhttpd.conf +2 -2
  17. data/examples/blog/lib/blog/controller.rb +11 -2
  18. data/examples/blog/log/apache.error_log +5528 -0
  19. data/examples/blog/root/fcgi.rb +1 -1
  20. data/examples/blog/run.rb +9 -3
  21. data/examples/flash/run.rb +2 -2
  22. data/examples/no_xsl_blog/conf/apache.conf +30 -0
  23. data/examples/no_xsl_blog/conf/lhttpd.conf +1 -1
  24. data/examples/no_xsl_blog/lib/blog/controller.rb +2 -2
  25. data/examples/no_xsl_blog/log/apache.error_log +68 -0
  26. data/examples/no_xsl_blog/root/fcgi.rb +2 -2
  27. data/examples/no_xsl_blog/run.rb +3 -3
  28. data/examples/og/run.rb +1 -1
  29. data/examples/tiny/conf/apache.conf +29 -4
  30. data/examples/tiny/conf/lhttpd.conf +1 -1
  31. data/examples/tiny/log/apache.error_log +30 -0
  32. data/examples/tiny/root/fcgi.rb +2 -2
  33. data/examples/tiny/root/index.xhtml +1 -1
  34. data/examples/tiny/run.rb +3 -2
  35. data/examples/wee_style/run.rb +7 -9
  36. data/examples/why_wiki/README +5 -0
  37. data/examples/why_wiki/run.rb +57 -0
  38. data/examples/why_wiki/wiki.yml +6 -0
  39. data/examples/wiki.yml +1 -0
  40. data/lib/glue/array.rb +14 -33
  41. data/lib/glue/hash.rb +32 -53
  42. data/lib/glue/pool.rb +9 -12
  43. data/lib/glue/property.rb +31 -9
  44. data/lib/nitro.rb +30 -8
  45. data/lib/nitro/adapters/cgi.rb +23 -3
  46. data/lib/nitro/adapters/webrick.rb +9 -3
  47. data/lib/nitro/builders/form.rb +21 -13
  48. data/lib/nitro/builders/rss.rb +20 -9
  49. data/lib/nitro/builders/table.rb +69 -10
  50. data/lib/nitro/builders/xhtml.rb +13 -4
  51. data/lib/nitro/component.rb +15 -0
  52. data/lib/nitro/conf.rb +4 -3
  53. data/lib/nitro/context.rb +22 -14
  54. data/lib/nitro/controller.rb +63 -5
  55. data/lib/nitro/dispatcher.rb +11 -6
  56. data/lib/nitro/output.rb +28 -0
  57. data/lib/nitro/render.rb +78 -59
  58. data/lib/nitro/request.rb +5 -1
  59. data/lib/nitro/runner.rb +20 -6
  60. data/lib/nitro/session.rb +89 -18
  61. data/lib/nitro/session/drb.rb +31 -0
  62. data/lib/nitro/session/drbserver.rb +71 -0
  63. data/lib/nitro/session/memory.rb +13 -0
  64. data/lib/nitro/simple.rb +7 -0
  65. data/lib/nitro/ui/date-select.rb +2 -5
  66. data/lib/nitro/ui/pager.rb +4 -4
  67. data/lib/nitro/ui/tabs.rb +2 -4
  68. data/lib/nitro/uri.rb +7 -4
  69. data/lib/og.rb +20 -12
  70. data/lib/og/adapter.rb +40 -13
  71. data/lib/og/adapters/filesys.rb +121 -0
  72. data/lib/og/adapters/mysql.rb +10 -5
  73. data/lib/og/adapters/oracle.rb +374 -0
  74. data/lib/og/adapters/psql.rb +10 -23
  75. data/lib/og/adapters/sqlite.rb +3 -3
  76. data/lib/og/backend.rb +2 -2
  77. data/lib/og/connection.rb +6 -6
  78. data/lib/og/database.rb +5 -5
  79. data/lib/og/enchant.rb +6 -2
  80. data/lib/og/meta.rb +56 -26
  81. data/lib/og/mock.rb +1 -1
  82. data/lib/og/typemacros.rb +23 -0
  83. data/lib/parts/content.rb +4 -10
  84. data/test/nitro/adapters/tc_cgi.rb +1 -1
  85. data/test/nitro/builders/tc_rss.rb +1 -1
  86. data/test/nitro/builders/tc_table.rb +30 -0
  87. data/test/nitro/tc_context.rb +4 -0
  88. data/test/nitro/tc_controller.rb +9 -2
  89. data/test/og/tc_filesys.rb +83 -0
  90. data/test/og/tc_meta.rb +55 -0
  91. data/test/tc_og.rb +115 -36
  92. data/vendor/README +11 -5
  93. data/vendor/breakpoint.rb +35 -38
  94. data/vendor/breakpoint_client.rb +119 -80
  95. data/vendor/composite_sexp_processor.rb +43 -0
  96. data/vendor/parse_tree.rb +745 -0
  97. data/vendor/sexp_processor.rb +453 -0
  98. metadata +34 -7
  99. data/examples/no_xsl_blog/conf/app.conf.rb +0 -47
@@ -1,20 +1,16 @@
1
- # code:
2
1
  # * George Moschovitis <gm@navel.gr>
3
- #
4
- # (c) 2004 Navel, all rights reserved.
5
- # $Id: form.rb 202 2005-01-17 10:44:13Z gmosx $
2
+ # (c) 2004-2005 Navel, all rights reserved.
3
+ # $Id: form.rb 266 2005-02-28 14:50:48Z gmosx $
6
4
 
7
5
  require 'glue/hash'
8
6
  require 'nitro/markup'
9
7
 
10
8
  module N
11
9
 
12
- # = FormBuilder
13
- #
14
- class FormBuilder
15
-
16
- @@cache = N::SafeHash.new
10
+ # FormBuilder.
17
11
 
12
+ module FormBuilderMixin
13
+
18
14
  # Render a standard form for the given managed object.
19
15
  # If show_all is false then apply field filtering.
20
16
  #
@@ -25,8 +21,8 @@ class FormBuilder
25
21
  # #{N::FormBuilder.render(entry)}
26
22
  # </form>
27
23
  # </p>
28
- #
29
- def self.render(obj, lc = nil, show_all = false)
24
+
25
+ def build_form(obj, lc = nil, show_all = false)
30
26
  str = '<dl>'
31
27
 
32
28
  for p in obj.class.__props
@@ -85,9 +81,21 @@ class FormBuilder
85
81
  str << %{
86
82
  </dl>}
87
83
 
88
- return str
84
+ self << str
89
85
  end
90
86
 
91
87
  end
92
88
 
93
- end # module
89
+ # Abstract class for the FormBuilderMixin.
90
+
91
+ class FormBuilder
92
+ include FormBuilderMixin
93
+
94
+ class << self
95
+ def build(obj, lc = nil, show_all = false)
96
+ FormBuilder.new.build_form(obj, lc, show_all)
97
+ end
98
+ end
99
+ end
100
+
101
+ end
@@ -1,6 +1,6 @@
1
1
  # * George Moschovitis <gm@navel.gr>
2
2
  # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id: rss.rb 249 2005-02-04 14:03:00Z gmosx $
3
+ # $Id: rss.rb 266 2005-02-28 14:50:48Z gmosx $
4
4
 
5
5
  require 'rss/0.9'
6
6
 
@@ -10,15 +10,15 @@ module N
10
10
 
11
11
  # Build RSS represenations of ruby object collections.
12
12
  # Utilize duck typing to grab the attributes to render.
13
+ # Add this mixin to you classes to support RSS rendering.
14
+ #
13
15
  #--
14
16
  # TODO: add more options here, 1.0/2.0 support and more.
15
17
  #++
16
18
 
17
- class RssBuilder
19
+ module RssBuilderMixin
18
20
 
19
- class << self
20
-
21
- # Options:
21
+ # === Options
22
22
  #
23
23
  # [+:description+]
24
24
  # Description of the Feed
@@ -27,7 +27,7 @@ class RssBuilder
27
27
  # [+:link+]
28
28
  # Link of the Feed.
29
29
 
30
- def render_0_9(objects, options = {})
30
+ def build_rss_09(objects, options = {})
31
31
  c = {
32
32
  :description => 'Syndication'
33
33
  }.update(options)
@@ -51,12 +51,23 @@ class RssBuilder
51
51
  rss = RSS::Rss.new '0.9'
52
52
  rss.channel = channel
53
53
 
54
- return rss.to_s
54
+ self << rss.to_s
55
55
  end
56
- alias_method :render, :render_0_9
56
+ alias_method :build_rss, :build_rss_09
57
+
58
+ end
59
+
60
+ # Abstract class for the RssBuilderMixin.
57
61
 
62
+ class RssBuilder < String
63
+ include RssBuilderMixin
64
+
65
+ class << self
66
+ def build_09(objects, options = {})
67
+ RssBuilder.new.build_rss_09(objects, options)
68
+ end
69
+ alias_method :build, :build_09
58
70
  end
59
-
60
71
  end
61
72
 
62
73
  end
@@ -1,23 +1,82 @@
1
- # code:
2
1
  # * George Moschovitis <gm@navel.gr>
3
- #
4
- # (c) 2004 Navel, all rights reserved.
5
- # $Id: table.rb 185 2004-12-10 13:29:09Z gmosx $
2
+ # (c) 2004-2005 Navel, all rights reserved.
3
+ # $Id: table.rb 266 2005-02-28 14:50:48Z gmosx $
6
4
 
7
5
  module N
8
6
 
9
- # = TableBuilder
7
+ # The TableBuilder is a helper class that automates the creation
8
+ # of tables from collections of objects. The resulting html
9
+ # can be styled using css.
10
10
  #
11
- # Example:
11
+ # === Example
12
12
  #
13
- # users = User.all
13
+ # <?r
14
+ # users = User.all.map { |u| [u.name, u.first_name, u.last_name, u.email] }
14
15
  # header = ['Username', 'First name', 'Last name', 'Email']
15
- # N::TableBuilder.render(users, header)
16
+ # ?>
17
+ #
18
+ # <div class="custom-table-class">
19
+ # #{N::TableBuilder.build(users, header)}
20
+ # </div>
16
21
  #
17
- class TableBuilder
22
+ # or:
23
+ #
24
+ # <div class="custom-table-class">
25
+ # #{@out.build_table(users, header)}
26
+ # </div>
27
+ #--
28
+ # TODO: sorting, thead/tbody/legend etc, verbose...
29
+ #++
30
+
31
+ module TableBuilderMixin
32
+
33
+ # [+options+]
34
+ # A hash of options.
35
+ #
36
+ # :id = id of the component.
37
+ # :headers = an array of the header values
38
+ # :values = an array of arrays.
39
+
40
+ def build_table(options)
41
+ c = options
42
+
43
+ buf = '<table'
44
+ buf << %| id="#{c[:id]}"| if c[:id]
45
+ buf << '><tr>'
46
+
47
+ for h in c[:headers]
48
+ buf << %|<th>#{h}</th>|
49
+ end
50
+
51
+ buf << "</tr>"
52
+
53
+ for row in c[:values]
54
+ buf << "<tr>"
55
+
56
+ for v in row
57
+ buf << %|<td>#{v}</td>|
58
+ end
59
+
60
+ buf << "</tr>"
61
+ end
62
+
63
+ buf << "</table>"
64
+
65
+ return buf
66
+ end
67
+
18
68
  end
19
69
 
20
- end # module
70
+ # Abstract class for the TableBuilderMixin.
21
71
 
72
+ class TableBuilder
73
+ include TableBuilderMixin
22
74
 
75
+ class << self
76
+ def build(options)
77
+ TableBuilder.new.build_table(options)
78
+ end
79
+ end
80
+ end
23
81
 
82
+ end
@@ -74,14 +74,23 @@ module XhtmlBuilderMixin
74
74
  end
75
75
  end
76
76
  end
77
+
78
+ def submit(options = nil)
79
+ if options
80
+ opts = options.collect { |k, v| %[#{k}="#{v}"] }.join(' ')
81
+ self << %[<input type="submit" #{opts} />]
82
+ else
83
+ self << %|<input type="submit" />|
84
+ end
85
+ end
77
86
  end
78
87
 
79
88
  # A String extension with XHTML generation
80
89
  # functionality.
81
90
 
82
91
  class XhtmlString < String
83
- include N::XmlBuilderMixin
84
- include N::XhtmlBuilderMixin
92
+ include XmlBuilderMixin
93
+ include XhtmlBuilderMixin
85
94
  end
86
95
 
87
96
  # A class that encapsulats the XHTML generation
@@ -89,8 +98,8 @@ end
89
98
  # output to a target buffer.
90
99
 
91
100
  class XhtmlBuilder
92
- include N::XmlBuilderMixin
93
- include N::XhtmlBuilderMixin
101
+ include XmlBuilderMixin
102
+ include XhtmlBuilderMixin
94
103
 
95
104
  # The target receives the generated xml,
96
105
  # should respond_to :<<
@@ -0,0 +1,15 @@
1
+ # * George Moschovitis <gm@navel.gr>
2
+ # (c) 2004-2005 Navel, all rights reserved.
3
+ # $Id: component.rb 266 2005-02-28 14:50:48Z gmosx $
4
+
5
+ require 'nitro/controller'
6
+
7
+ module N
8
+
9
+ # A Web Component. A Component extends from the
10
+ # base controller class.
11
+
12
+ class Component < Controller
13
+ end
14
+
15
+ end
@@ -1,6 +1,6 @@
1
1
  # * George Moschovitis <gm@navel.gr>
2
2
  # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id: conf.rb 260 2005-02-15 08:58:04Z gmosx $
3
+ # $Id: conf.rb 266 2005-02-28 14:50:48Z gmosx $
4
4
 
5
5
  require 'glue/flexob'
6
6
 
@@ -19,8 +19,9 @@ class Conf < Flexob
19
19
 
20
20
  hash = {
21
21
  :name => 'Nitro Application',
22
- :host => 'localhost',
23
- :port => 8069,
22
+ # this is accessible as localhost on windows
23
+ :host => '0.0.0.0',
24
+ :port => 9999,
24
25
  :dispatcher => Dispatcher.new
25
26
  }
26
27
 
@@ -6,8 +6,8 @@ require 'nitro/request'
6
6
  require 'nitro/response'
7
7
  require 'nitro/render'
8
8
  require 'nitro/session'
9
-
10
- require 'nitro/builders/xhtml'
9
+ require 'nitro/output'
10
+ require 'nitro/adapters/cgi.rb'
11
11
 
12
12
  module N
13
13
 
@@ -25,7 +25,8 @@ class Context
25
25
 
26
26
  # The session contains variables that stay alive
27
27
  # for the full user session. Session variables
28
- # should be generally avoided.
28
+ # should be generally avoided. This variable
29
+ # becomes populated ONLY if needed.
29
30
 
30
31
  attr_reader :session
31
32
 
@@ -33,27 +34,34 @@ class Context
33
34
 
34
35
  attr_accessor :dispatcher
35
36
 
36
- # The sessions.
37
-
38
- attr_accessor :sessions
39
-
40
37
  def initialize(conf)
41
38
  @conf = conf
42
39
  @dispatcher = @conf.dispatcher
43
40
  @context = self
44
- @sessions = Session.manager
45
-
46
- # gmosx, FIXME: try to avoid creating this hash!
47
- @response_headers = {}
48
- @out = XhtmlString.new
41
+
42
+ # initialize response.
43
+
44
+ @status = CgiUtils::STATUS_OK
45
+ @response_headers = { 'Content-Type' => 'text/html' }
46
+
47
+ # initialize the output buffer.
48
+
49
+ @out = OutputBuffer.new
49
50
  end
50
51
 
52
+ # Close the context, should be called at the
53
+ # end of the HTTP request handling code.
54
+
55
+ def close
56
+ @session.sync if @session
57
+ end
58
+ alias_method :finish, :close
59
+
51
60
  # Lazy lookup of the session to avoid costly cookie
52
61
  # lookup when not needed.
53
62
 
54
63
  def session
55
- return @session if @session
56
- return @session = Session.lookup(self)
64
+ @session || @session = Session.lookup(self)
57
65
  end
58
66
 
59
67
  # Populate an object from request parameters.
@@ -36,14 +36,72 @@ class Controller
36
36
  }
37
37
  __old_inherited(subclass)
38
38
  end
39
- end
40
39
 
41
- end
40
+ # Return the 'action' methods for this Controller.
41
+ # Some dangerous methods from ancestors are removed.
42
+
43
+ def action_methods
44
+ classes = self.ancestors.reject do |a|
45
+ [Object, Kernel, Render].include?(a)
46
+ end
47
+
48
+ methods = classes.inject([]) do |action_methods, klass|
49
+ action_methods + klass.public_instance_methods(false)
50
+ end
51
+
52
+ methods.delete('method_missing')
53
+
54
+ # temp hack, FIXME:
55
+
56
+ methods.delete('pretty_print')
57
+ methods.delete('pretty_print_cycle')
58
+ methods.delete('pretty_print_instance_variables')
59
+ methods.delete('pretty_print_inspect')
60
+
61
+ return methods
62
+ end
42
63
 
43
- # A simple controller, only handles templates.
44
- # Useful to implement php/asp/jsp style applications.
64
+ # Return the arguments of the given action.
65
+
66
+ def action_method_arguments(action)
67
+ if Nitro.resolve_action_arguments
68
+ unless defined?(ArgsProcessor)
69
+ begin
70
+ require_gem 'ParseTree'
71
+ require 'parse_tree'
72
+ require 'sexp_processor'
73
+ rescue
74
+ # No parse tree support
75
+ end
76
+
77
+ Object.class_eval %{
78
+ class ArgsProcessor < SexpProcessor # :nodoc:
79
+ attr_accessor :args
45
80
 
46
- class SimpleController < Controller
81
+ def initialize
82
+ super
83
+ @require_empty = false
84
+ end
85
+
86
+ def process_args(exp)
87
+ @args = exp.slice(1..-1)
88
+ return Sexp.new(exp)
89
+ end
90
+ end
91
+ }
92
+ end
93
+
94
+ ptree = ParseTree.new
95
+ sexpp = ArgsProcessor.new
96
+ sexp = ptree.parse_tree_for_method(self, action)
97
+ sexpp.process(sexp)
98
+
99
+ return sexpp.args
100
+ else
101
+ return []
102
+ end
103
+ end
104
+ end
47
105
  end
48
106
 
49
107
  end
@@ -5,6 +5,7 @@
5
5
  module N
6
6
 
7
7
  require 'nitro/controller'
8
+ require 'nitro/simple'
8
9
 
9
10
  # The Dispatcher manages a set of controllers.
10
11
 
@@ -42,7 +43,7 @@ class Dispatcher
42
43
  @controllers = controllers || { :root => SimpleController }
43
44
  end
44
45
 
45
- @apis = apis
46
+ @apis = apis || {}
46
47
  end
47
48
 
48
49
  # Process the given hash and mount the
@@ -71,6 +72,10 @@ class Dispatcher
71
72
  # API symbol
72
73
  # [+data+]
73
74
  # Data for this API [content_type, ..]
75
+ #
76
+ # === Example
77
+ #
78
+ # dispatcher.add_api(:xml, 'text/xml')
74
79
 
75
80
  def add_api(api, data)
76
81
  (@apis ||= {})[api] = data
@@ -86,7 +91,7 @@ class Dispatcher
86
91
  # [:context]
87
92
  # The dispatching context.
88
93
 
89
- def dispatch(path, context)
94
+ def dispatch(path, context = nil)
90
95
  api = :xhtml
91
96
 
92
97
  if @apis
@@ -101,7 +106,7 @@ class Dispatcher
101
106
  base = @root
102
107
  klass = controller_class_for(:root, context)
103
108
  action = 'index'
104
-
109
+
105
110
  when 2
106
111
  if klass = controller_class_for(parts[1], context)
107
112
  # controller/ -> controller.index
@@ -121,7 +126,7 @@ class Dispatcher
121
126
  action = parts[2]
122
127
  end
123
128
 
124
- content_type = @apis ? @apis[:api] : 'text/html'
129
+ content_type = @apis[:api] || 'text/html'
125
130
 
126
131
  return klass, "__#{api}__#{action}", base, content_type
127
132
  end
@@ -133,11 +138,11 @@ class Dispatcher
133
138
  def controller_class_for(key, context)
134
139
  klass = @controllers[key]
135
140
 
136
- if context[:__RELOADED__].nil? and (:full == Rendering.reload) and klass
141
+ if (:full == Rendering.reload) and context and context[:__RELOADED__].nil? and klass
137
142
  def_file = klass::DEF_FILE
138
143
  Controller.remove_subclasses
139
144
  load(def_file)
140
- klass = @controllers[key] = Object.const_get(klass.name.intern)
145
+ klass = @controllers[key] = Object.const_get(klass.name.intern)
141
146
  context[:__RELOADED__] = true
142
147
  end
143
148