nitro 0.10.0 → 0.11.0

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