nitro 0.11.0 → 0.12.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 (56) hide show
  1. data/ChangeLog +150 -0
  2. data/README +1 -1
  3. data/RELEASES +89 -0
  4. data/Rakefile +3 -3
  5. data/{AUTHORS → doc/AUTHORS} +0 -0
  6. data/{LICENSE → doc/LICENSE} +0 -0
  7. data/doc/bugs.txt +2 -1
  8. data/examples/README.windows +2 -2
  9. data/examples/blog/lib/blog/controller.rb +9 -8
  10. data/examples/blog/log/apache.error_log +71 -0
  11. data/{lib/xsl → examples/blog/root}/base.xsl +0 -0
  12. data/examples/blog/root/error.xhtml +56 -0
  13. data/examples/blog/root/index.xhtml +2 -2
  14. data/examples/blog/root/recent_posts.xhtml +1 -1
  15. data/examples/blog/root/style.xsl +4 -4
  16. data/examples/blog/run.rb +1 -2
  17. data/examples/no_xsl_blog/root/index.xhtml +2 -2
  18. data/examples/no_xsl_blog/root/recent_posts.xhtml +1 -1
  19. data/examples/why_wiki/run.rb +19 -19
  20. data/lib/nitro.rb +2 -21
  21. data/lib/nitro/adapters/webrick.rb +19 -3
  22. data/lib/nitro/context.rb +15 -1
  23. data/lib/nitro/controller.rb +84 -49
  24. data/lib/nitro/dispatcher.rb +30 -6
  25. data/lib/nitro/markup.rb +4 -2
  26. data/lib/nitro/render.rb +15 -11
  27. data/lib/nitro/routing.rb +33 -0
  28. data/lib/nitro/runner.rb +38 -3
  29. data/lib/nitro/scaffold.rb +7 -4
  30. data/lib/nitro/shaders.rb +11 -4
  31. data/lib/nitro/template.rb +140 -0
  32. data/lib/og.rb +25 -11
  33. data/lib/og/adapter.rb +141 -7
  34. data/lib/og/adapters/mysql.rb +41 -3
  35. data/lib/og/adapters/oracle.rb +4 -3
  36. data/lib/og/adapters/psql.rb +3 -3
  37. data/lib/og/adapters/sqlite.rb +3 -3
  38. data/lib/og/connection.rb +5 -1
  39. data/lib/og/database.rb +26 -12
  40. data/lib/og/enchant.rb +50 -16
  41. data/lib/og/meta.rb +15 -15
  42. data/lib/og/observer.rb +53 -0
  43. data/test/glue/tc_property_type_checking.rb +3 -0
  44. data/test/nitro/tc_controller.rb +1 -1
  45. data/test/nitro/tc_dispatcher.rb +1 -1
  46. data/test/nitro/tc_template.rb +32 -0
  47. data/test/og/tc_many_to_many.rb +62 -0
  48. data/test/og/tc_observer.rb +85 -0
  49. data/test/tc_og.rb +16 -2
  50. metadata +12 -14
  51. data/bin/cluster +0 -218
  52. data/examples/why_wiki/wiki.yml +0 -6
  53. data/examples/wiki.yml +0 -1
  54. data/lib/nitro/ui/select.rb +0 -40
  55. data/lib/nitro/ui/sitemap.rb +0 -183
  56. data/test/nitro/ui/tc_sitemap.rb +0 -37
@@ -13,8 +13,8 @@
13
13
  <h3 class="title">#{entry.title}</h3>
14
14
  #{entry.body}
15
15
  <div class="footer">
16
- posted by #{entry.author} at <a href="view_entry?oid=#{entry.oid}">#{entry.create_time.strftime('%R %p')}</a> |
17
- <a href="view_entry?oid=#{entry.oid}#comments">#{entry.comments_count} comments</a>.
16
+ posted by #{entry.author} at <a href="#{entry.view_uri}">#{entry.create_time.strftime('%R %p')}</a> |
17
+ <a href="#{entry.view_uri}#comments">#{entry.comments_count} comments</a>.
18
18
  <?r if session[:owner] ?>
19
19
  [<a href="del_entry?oid=#{entry.oid}">del</a>]
20
20
  <?r end ?>
@@ -5,7 +5,7 @@
5
5
  <?r if @entries ?>
6
6
  <ul>
7
7
  <?r for entry in @entries ?>
8
- <li><a href="view_entry?oid=#{entry.oid}">#{entry.title}</a></li>
8
+ <li><a href="#{entry.view_uri}">#{entry.title}</a></li>
9
9
  <?r end ?>
10
10
  </ul>
11
11
  <?r else ?>
@@ -5,7 +5,7 @@ A Simple Shader
5
5
 
6
6
  * George Moschovitis <gm@navel.gr>
7
7
  (c) 2004-2005 Navel, all rights reserved.
8
- $Id: style.xsl 259 2005-02-15 08:54:54Z gmosx $
8
+ $Id: style.xsl 270 2005-03-07 17:52:16Z gmosx $
9
9
  -->
10
10
 
11
11
  <!DOCTYPE shader
@@ -23,13 +23,13 @@ $Id: style.xsl 259 2005-02-15 08:54:54Z gmosx $
23
23
  xmlns:x="http://www.navel.gr/xml/shader.xsd" version="1.0"
24
24
  exclude-result-prefixes="x xl">
25
25
 
26
- <xsl:include href="../../lib/xsl/base.xsl" />
26
+ <xsl:include href="root/base.xsl" />
27
27
 
28
28
  <xsl:output method="xml" indent="yes" encoding="iso-8859-1" />
29
29
 
30
30
  <xsl:template name="x:head">
31
31
  <head>
32
- <title>#{@context.conf.name}</title>
32
+ <title>#(@context.conf.name)</title>
33
33
  <meta name="title" content="Blog" />
34
34
  <meta name="description" content="Example" />
35
35
  <meta name="keywords" content="nitro, example, blog" />
@@ -39,7 +39,7 @@ $Id: style.xsl 259 2005-02-15 08:54:54Z gmosx $
39
39
 
40
40
  <xsl:apply-templates select="x:block[@id='meta']"/>
41
41
 
42
- <base href="#{@context.host_url}/" />
42
+ <base href="#(@context.host_url)/" />
43
43
  <link href="/style.css" rel="stylesheet" type="text/css" media="screen" />
44
44
  <link rel="alternate" type="application/rss+xml" title="Latest Entries" href="#{@context.host_url}/xml/list_entry" />
45
45
  <link rel="alternate" type="application/rss+xml" title="Latest Comments" href="#{@context.host_url}/xml/list_comment" />
data/examples/blog/run.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # * George Moschovitis <gm@navel.gr>
2
2
  # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id: run.rb 266 2005-02-28 14:50:48Z gmosx $
3
+ # $Id: run.rb 270 2005-03-07 17:52:16Z gmosx $
4
4
 
5
5
  # $:.unshift '/home/gmosx/navel/nitro/lib'
6
6
 
@@ -11,7 +11,6 @@ require 'og'
11
11
 
12
12
  require 'lib/blog'
13
13
 
14
- # Nitro.resolve_action_arguments = true
15
14
  # Og.create_schema = false
16
15
  # Session.store_type = :drb
17
16
 
@@ -12,8 +12,8 @@
12
12
  <h3 class="title">#{entry.title}</h3>
13
13
  #{entry.body}
14
14
  <div class="footer">
15
- posted by #{entry.author} at <a href="view_entry?oid=#{entry.oid}">#{entry.create_time.strftime('%R %p')}</a> |
16
- <a href="view_entry?oid=#{entry.oid}#comments">#{entry.comments_count} comments</a>.
15
+ posted by #{entry.author} at <a href="#{entry.view_uri}">#{entry.create_time.strftime('%R %p')}</a> |
16
+ <a href="#{entry.view_uri}#comments">#{entry.comments_count} comments</a>.
17
17
  <?r if session[:owner] ?>
18
18
  [<a href="del_entry?oid=#{entry.oid}">del</a>]
19
19
  <?r end ?>
@@ -5,7 +5,7 @@
5
5
  <?r if @entries ?>
6
6
  <ul>
7
7
  <?r for entry in @entries ?>
8
- <li><a href="view_entry?oid=#{entry.oid}">#{entry.title}</a></li>
8
+ <li><a href="#{entry.view_uri}">#{entry.title}</a></li>
9
9
  <?r end ?>
10
10
  </ul>
11
11
  <?r else ?>
@@ -1,57 +1,57 @@
1
1
  # * George Moschovitis <gm@navel.gr>
2
- # $Id: run.rb 267 2005-02-28 14:52:41Z gmosx $
2
+ # $Id: run.rb 270 2005-03-07 17:52:16Z gmosx $
3
3
 
4
4
  require 'cgi'
5
5
  require 'redcloth'
6
6
  require 'yaml/store'
7
7
 
8
8
  require 'nitro'; include N
9
+ require 'nitro/adapters/webrick'
9
10
 
10
11
  # A simple wiki. A straight conversion of the redhanded.hobix.com
11
12
  # example. Original code by why the lucky stiff.
12
13
  # This is just a cool example, not the preffered way to write
13
14
  # Nitro applications.
14
15
 
16
+ WIKI = YAML::Store.new('wiki.yml')
17
+
15
18
  class Wiki < Component
16
- HP = 'HomePage'
17
- WIKI = YAML::Store.new('wiki.yml')
18
19
 
19
20
  def index
20
- request['p'] = HP
21
+ @p = 'Home'
21
22
  show
22
23
  end
23
24
 
24
25
  def show
25
- p = request['p'].to_s
26
- o.h1(p)
27
- o.a(HP, :href => '/') unless p == HP
26
+ o.h1(@p)
27
+ o.a('Home', :href => '/') unless @p == 'Home'
28
28
  WIKI.transaction do
29
- if WIKI[p]
30
- o << RedCloth.new(WIKI[p]).to_html.gsub(/([A-Z]\w+){2}/) { "<a href='show?p=#$&'>#$&</a>" }
31
- o.a 'Edit', :href => "edit?p=#{p}"
29
+ if WIKI[@p]
30
+ o << RedCloth.new(WIKI[@p]).to_html.gsub(/([A-Z]\w+){2}/) { "<a href='/show/#$&'>#$&</a>" }
31
+ o.a 'Edit', :href => "/edit/#@p"
32
32
  else
33
- o.p("No page #{p}. ").a('Create?', :href => "edit?p=#{p}")
33
+ o.p("No page #{p}. ").a('Create?', :href => "/edit/#@p")
34
34
  end
35
35
  end
36
36
  end
37
+ action :show, :route => /show\/(.*)/, 'p' => String
37
38
 
38
39
  def edit
39
- p = request['p'].to_s
40
40
  if c = request['c']
41
- WIKI.transaction { WIKI[p] = c.to_s }
42
- redirect "show?p=#{p}"
41
+ WIKI.transaction { WIKI[@p] = c }
42
+ redirect "/show/#@p"
43
43
  end
44
44
  WIKI.transaction do
45
- o.h1 "Editing #{p}"
46
- o.a('Show', :href => "show?p=#{p}").br.br
45
+ o.h1 "Editing #@p"
46
+ o.a('Show', :href => "/show/#@p").br.br
47
47
  o.form(:method => 'post') {
48
- o.input :type => 'hidden', :name => 'p', :value => p
49
- o.textarea WIKI[p].to_s, :name => 'c', :style => 'width: 90%; height: 200px'
48
+ o.input :type => 'hidden', :name => 'p', :value => @p
49
+ o.textarea WIKI[@p].to_s, :name => 'c', :style => 'width: 90%; height: 200px'
50
50
  o.br.br.submit
51
51
  }
52
52
  end
53
53
  end
54
+ action :edit, :route => /edit\/(.*)/, 'p' => String
54
55
  end
55
56
 
56
- require 'nitro/adapters/webrick'
57
57
  Webrick.start(:dispatcher => Dispatcher.new(Wiki))
data/lib/nitro.rb CHANGED
@@ -12,7 +12,7 @@
12
12
  #
13
13
  # * George Moschovitis <gm@navel.gr>
14
14
  # (c) 2004-2005 Navel, all rights reserved.
15
- # $Id: nitro.rb 266 2005-02-28 14:50:48Z gmosx $
15
+ # $Id: nitro.rb 270 2005-03-07 17:52:16Z gmosx $
16
16
 
17
17
  require 'glue'
18
18
  require 'glue/logger'
@@ -27,31 +27,12 @@ module Nitro
27
27
 
28
28
  # The version.
29
29
 
30
- Version = '0.11.0'
30
+ Version = '0.12.0'
31
31
 
32
32
  # Library path.
33
33
 
34
34
  LibPath = File.dirname(__FILE__)
35
35
 
36
- # If set to true, action methods can have arguments which are
37
- # automatically resolved.
38
- #
39
- # === Example
40
- #
41
- # def list(username, oid)
42
- # ...
43
- # end
44
- #
45
- # http://www.mysite.com/list?username=tml;oid=2
46
- #
47
- # calls list() with the correct parameters, no need to
48
- # use request['oid'], just use oid.
49
- #
50
- # WARNING: this feature requires the ParseTree library which
51
- # is not compatible with Windows.
52
-
53
- mattr_accessor :resolve_action_arguments, false
54
-
55
36
  end
56
37
 
57
38
  # gmosx: leave them here.
@@ -10,6 +10,10 @@ require 'nitro/context'
10
10
  require 'nitro/dispatcher'
11
11
 
12
12
  module WEBrick
13
+
14
+ class HTTPRequest
15
+ attr :socket
16
+ end
13
17
 
14
18
  class HTTPResponse
15
19
  def header=(header)
@@ -103,13 +107,25 @@ class WebrickAdapter < WEBrick::HTTPServlet::AbstractServlet
103
107
 
104
108
  context = Context.new(@conf)
105
109
 
106
- context.params = req.query
107
110
  context.headers = {}
108
111
  req.header.each { |h, v| context.headers[h.upcase] = v.first }
109
112
  context.headers.update(req.meta_vars)
110
- context.cookies = {}
111
- req.cookies.each { |c| context.cookies[c.name] = c.value }
112
113
 
114
+ context.params = {}
115
+ req.query.each do |k, v|
116
+ if k =~ /(.*)\[\]$/
117
+ context.params[k] = v
118
+ else
119
+ context.params[k] = v.to_s
120
+ end
121
+ end
122
+ # context.in = req.socket
123
+ # CgiUtils.parse_params(context)
124
+
125
+ #context.cookies = {}
126
+ #req.cookies.each { |c| context.cookies[c.name] = c.value }
127
+ CgiUtils.parse_cookies(context)
128
+
113
129
  context.render(path)
114
130
 
115
131
  res.status = context.status
data/lib/nitro/context.rb CHANGED
@@ -56,7 +56,21 @@ class Context
56
56
  @session.sync if @session
57
57
  end
58
58
  alias_method :finish, :close
59
-
59
+
60
+ #--
61
+ # FIXME: something more elegant/efficient.
62
+ #++
63
+
64
+ def out
65
+ if @out == '(error)'
66
+ @out = ''
67
+ render '/error'
68
+ @out
69
+ else
70
+ @out
71
+ end
72
+ end
73
+
60
74
  # Lazy lookup of the session to avoid costly cookie
61
75
  # lookup when not needed.
62
76
 
@@ -7,7 +7,70 @@ require 'nitro/scaffold'
7
7
  require 'nitro/filters'
8
8
 
9
9
  module N
10
+
11
+ # Encapsulates metadata that describe an action
12
+ # parameter.
13
+ #
14
+ # [+default+]
15
+ # The default value.
16
+ #
17
+ # [+format+]
18
+ # The expected format.
19
+ #
20
+ # [+required+]
21
+ # Is this parameter required?
22
+
23
+ ActionParam = Struct.new(:default, :format, :required)
24
+
25
+ # Encapsulates metadata that describe an action.
26
+
27
+ class ActionMeta < Hash
28
+
29
+ # The arguments of the given method.
30
+
31
+ attr_accessor :params
32
+
33
+ # Initialize the metadata.
34
+
35
+ def initialize(options)
36
+ @params = {}
37
+ update(options)
38
+ end
39
+
40
+ # Update the metadata.
41
+ #
42
+ # [+options+]
43
+ # A hash containing the metadata. Options with Symbol
44
+ # keys are considered metadata, options with
45
+ # String keys are the named parameters for the action.
10
46
 
47
+ def update(options)
48
+ options.each do |k, v|
49
+ case k
50
+ when String
51
+ # A key of type String denotes a parameter.
52
+ case v
53
+ when Regexp
54
+ @params[k] = ActionParam.new(nil, v, nil)
55
+ when ActionParam
56
+ @params[k] = v
57
+ else
58
+ if v == :required
59
+ @params[k] = ActionParam.new(nil, nil, true)
60
+ else
61
+ @params[k] = ActionParam.new(v, nil, nil)
62
+ end
63
+ end
64
+ when Symbol
65
+ self[k] = v
66
+ else
67
+ raise TypeError.new('The keys must be either Symbols or Strings.')
68
+ end
69
+ end
70
+ end
71
+
72
+ end
73
+
11
74
  # The Controller part in the MVC paradigm.
12
75
  # A Controller encpsulates a set of actions.
13
76
 
@@ -16,6 +79,11 @@ class Controller
16
79
  include Scaffolding
17
80
  include Filtering
18
81
 
82
+ # A hash containing metadata for the action
83
+ # methods.
84
+
85
+ cattr_accessor :action_metadata, {}
86
+
19
87
  # Use the method_missing hook to compile the actions
20
88
  # for this controller.
21
89
 
@@ -28,6 +96,7 @@ class Controller
28
96
  end
29
97
 
30
98
  class << self
99
+
31
100
  alias __old_inherited inherited
32
101
 
33
102
  def inherited(subclass)
@@ -37,70 +106,36 @@ class Controller
37
106
  __old_inherited(subclass)
38
107
  end
39
108
 
109
+ # Define metadata for an action. This is a helper
110
+ # macro.
111
+
112
+ def action(name, options)
113
+ if meta = @@action_metadata[name]
114
+ meta.update(options)
115
+ else
116
+ @@action_metadata[name] = ActionMeta.new(options)
117
+ end
118
+ end
119
+
40
120
  # Return the 'action' methods for this Controller.
41
121
  # Some dangerous methods from ancestors are removed.
42
122
 
43
123
  def action_methods
44
124
  classes = self.ancestors.reject do |a|
45
- [Object, Kernel, Render].include?(a)
125
+ [Object, Kernel, Render, Controller].include?(a)
46
126
  end
127
+
128
+ classes.delete(PP::ObjectMixin) if defined?(PP::ObjectMixin)
47
129
 
48
130
  methods = classes.inject([]) do |action_methods, klass|
49
131
  action_methods + klass.public_instance_methods(false)
50
132
  end
51
133
 
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')
134
+ # methods.delete('method_missing')
60
135
 
61
136
  return methods
62
137
  end
63
138
 
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
80
-
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
139
  end
105
140
  end
106
141