nitro 0.11.0 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -3,14 +3,16 @@
3
3
  # $Id$
4
4
 
5
5
  module N
6
-
6
+
7
7
  require 'nitro/controller'
8
+ require 'nitro/routing'
8
9
  require 'nitro/simple'
9
10
 
10
11
  # The Dispatcher manages a set of controllers.
11
12
 
12
13
  class Dispatcher
13
-
14
+ include Router
15
+
14
16
  # The root directory.
15
17
 
16
18
  attr_accessor :root
@@ -34,15 +36,17 @@ class Dispatcher
34
36
  # [+apis+]
35
37
  # A hash of apis supported by the Dispatcher.
36
38
 
37
- def initialize(controllers = nil, apis = nil)
39
+ def initialize(controllers = nil, apis = nil, routes = nil)
38
40
  @root = 'root'
39
41
 
40
42
  if controllers and controllers.is_a?(Class) and controllers.ancestors.include?(Controller)
41
- @controllers = { :root => controllers }
43
+ controllers = { :root => controllers }
42
44
  else
43
- @controllers = controllers || { :root => SimpleController }
45
+ controllers ||= { :root => SimpleController }
44
46
  end
45
47
 
48
+ mount(controllers)
49
+
46
50
  @apis = apis || {}
47
51
  end
48
52
 
@@ -62,9 +66,11 @@ class Dispatcher
62
66
  # 'users' => UsersController # mounts /users
63
67
  # }
64
68
 
65
- def mount(controllers)
69
+ def add_controller(controllers)
66
70
  (@controllers ||= {}).update(controllers)
71
+ update_routes
67
72
  end
73
+ alias_method :mount, :add_controller
68
74
 
69
75
  # Add a new api to the dispatcher
70
76
  #
@@ -81,6 +87,21 @@ class Dispatcher
81
87
  (@apis ||= {})[api] = data
82
88
  end
83
89
 
90
+ # Update the routes. Typically called after a new
91
+ # Controller is mounted.
92
+
93
+ def update_routes
94
+ @routes = []
95
+ @controllers.each do |base, c|
96
+ base = (base == :root ? '' : "/#{base}")
97
+ c.action_metadata.each do |action, meta|
98
+ if route = meta[:route]
99
+ @routes << [route, "#{base}/#{action}", *meta.params.keys]
100
+ end
101
+ end
102
+ end
103
+ end
104
+
84
105
  # Processes the path and dispatches to the corresponding
85
106
  # controller/action pair.
86
107
  # The base returned contains a trailing '/'.
@@ -94,7 +115,10 @@ class Dispatcher
94
115
  def dispatch(path, context = nil)
95
116
  api = :xhtml
96
117
 
118
+ path = route(path, context)
119
+
97
120
  if @apis
121
+ # OPTIMIZE: check only if lookup fails.
98
122
  @apis.each { |k, v| api = k if path.slice!(/#{k}\//) }
99
123
  end
100
124
 
data/lib/nitro/markup.rb CHANGED
@@ -52,8 +52,6 @@ module PropertyUtils
52
52
  end
53
53
  end
54
54
 
55
- # = Markup
56
- #
57
55
  # Generalised Markup transformations.
58
56
  #
59
57
  # The expand methods evaluate (expand) the markup
@@ -76,6 +74,8 @@ module Markup
76
74
  return unless str
77
75
  str.gsub!(/"/, '&quot;')
78
76
  str.gsub!(/'/, '&#39;')
77
+ str.gsub!(/</, '&lt;')
78
+ str.gsub!(/>/, '&gt;')
79
79
  str.gsub!(/\r\n/, ' <br />')
80
80
  return str
81
81
  end
@@ -84,6 +84,8 @@ module Markup
84
84
  return unless str
85
85
  str.gsub!(/&quot;/, '"')
86
86
  str.gsub!(/&#39;/, "'")
87
+ str.gsub!(/&lt;/, '<')
88
+ str.gsub!(/&gt;/, '>')
87
89
  # gmosx: SOS! double quotes ARE needed for \r\n!!
88
90
  str.gsub!(/\s<br \/>/, "\r\n")
89
91
  return str
data/lib/nitro/render.rb CHANGED
@@ -4,8 +4,6 @@
4
4
 
5
5
  require 'sync'
6
6
 
7
- require 'nitro'
8
-
9
7
  require 'glue/attribute'
10
8
  require 'glue/misc'
11
9
  require 'glue/object'
@@ -118,10 +116,14 @@ module Rendering
118
116
  if klass.action_methods.include?(action)
119
117
  valid = true
120
118
 
121
- args = klass.action_method_arguments(action).map { |a| "@#{a} = @context['#{a}']" }
119
+ if meta = klass.action_metadata[action.intern]
120
+ params = meta.params.keys
121
+ params = params.collect { |p| "@#{p} = @context['#{p}']" }
122
+ code << "#{params.join(';')}"
123
+ end
122
124
 
123
125
  code << %{
124
- #{action}(#{args.join(',')});
126
+ #{action}
125
127
  }
126
128
  end
127
129
 
@@ -166,7 +168,9 @@ module Rendering
166
168
  end
167
169
  }
168
170
  end
169
-
171
+
172
+ # puts '---', code, '---'
173
+
170
174
  klass.class_eval(code)
171
175
  end
172
176
 
@@ -235,9 +239,8 @@ module Render
235
239
  # For example called by redirects.
236
240
 
237
241
  rescue Exception, StandardError => e
238
- log_error "Error while handling '#{path}'."
239
- log_error pp_exception(e)
240
-
242
+ log_error(e, path)
243
+
241
244
  # More fault tolerant, only flags the erroneous box with
242
245
  # error not the full page.
243
246
 
@@ -264,14 +267,15 @@ private
264
267
 
265
268
  # Log a rendering error.
266
269
 
267
- def log_error(str)
270
+ def log_error(error, path)
268
271
  @rendering_errors ||= []
269
- @rendering_errors << str
272
+ @rendering_errors << [error, path]
270
273
 
271
274
  # gmosx: Hmm perhaps this should not be logged
272
275
  # to avoid DOS attacks.
273
276
 
274
- Logger.error str
277
+ Logger.error "Error while handling '#{path}'."
278
+ Logger.error pp_exception(error)
275
279
  end
276
280
 
277
281
  # Convenience method to lookup the session.
@@ -0,0 +1,33 @@
1
+ # * George Moschovitis <gm@navel.gr>
2
+ # (c) 2004-2005 Navel, all rights reserved.
3
+ # $Id: routing.rb 271 2005-03-07 17:56:45Z gmosx $
4
+
5
+ module N
6
+
7
+ # Router mixin.
8
+
9
+ module Router
10
+
11
+ # The route table maps 'nice URLs' to real URLs that
12
+ # can be handled by the Dispatcher.
13
+
14
+ attr_accessor :routes
15
+
16
+ # Apply routing rules to the path.
17
+
18
+ def route(path, context)
19
+ for rule, real_path, *params in @routes
20
+ if md = path.match(rule)
21
+ params.each_with_index do |p, idx|
22
+ context[p] = md.captures[idx]
23
+ end
24
+ return real_path
25
+ end
26
+ end
27
+
28
+ return path
29
+ end
30
+
31
+ end
32
+
33
+ end
data/lib/nitro/runner.rb CHANGED
@@ -44,19 +44,28 @@ class Runner
44
44
  #
45
45
  # The default mode is :debug
46
46
 
47
- attr_accessor :mode
47
+ attr :mode
48
48
 
49
49
  # :start, :stop, :restart
50
50
 
51
- attr_accessor :action
51
+ attr :action
52
52
 
53
53
  # The server used to run this web application.
54
54
  # :webrick, :nitro, :lhttp, :apache, :mod_apache
55
55
  #
56
56
  # At the moment only :webrick and :lhttp are available.
57
57
 
58
- attr_accessor :server
58
+ attr :server
59
59
 
60
+ # Run as daemon.
61
+
62
+ attr :daemon
63
+
64
+ # Spidering mode. Acceptable values are :crawl, :render
65
+ # and false.
66
+
67
+ attr :spider
68
+
60
69
  # Parse the command line arguments and the environment
61
70
  # parameters to setup the application.
62
71
 
@@ -66,6 +75,7 @@ class Runner
66
75
  @action = :start
67
76
  @server = :webrick
68
77
  @daemon = false
78
+ @spider = false
69
79
 
70
80
  parser = OptionParser.new do |opts|
71
81
 
@@ -127,6 +137,16 @@ class Runner
127
137
  exit
128
138
  end
129
139
 
140
+ opts.on('--crawl', 'Crawl the application.') do
141
+ @server = :webrick
142
+ @spider = :crawl
143
+ end
144
+
145
+ opts.on('--render', 'Crawl the application and render all pages as static html files.') do
146
+ @server = :webrick
147
+ @spider = :render
148
+ end
149
+
130
150
  opts.on_tail('-v', '--version', 'Show version.') do
131
151
  puts "Nitro #{Nitro::Version}"
132
152
  exit
@@ -202,9 +222,24 @@ class Runner
202
222
  end
203
223
 
204
224
  def invoke_server(conf)
225
+ spider_thread = nil
226
+
205
227
  case @action
206
228
  when :start
207
229
 
230
+ case @spider
231
+ when :render
232
+ spider_thread = Thread.new do
233
+ sleep(6)
234
+ `wget -k -m -p #{conf.host}:#{conf.port} -directory-prefix=rendered`
235
+ end
236
+ when :crawl
237
+ spider_thread = Thread.new do
238
+ sleep(6)
239
+ `wget -m --spider #{conf.host}:#{conf.port}`
240
+ end
241
+ end
242
+
208
243
  puts "\n==> Application listening at #{conf.host}:#{conf.port}.\n\n"
209
244
 
210
245
  case @server
@@ -1,6 +1,6 @@
1
1
  # * George Moschovitis <gm@navel.gr>
2
2
  # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id: scaffold.rb 248 2005-01-31 13:38:34Z gmosx $
3
+ # $Id: scaffold.rb 270 2005-03-07 17:52:16Z gmosx $
4
4
 
5
5
  require 'glue/inflector'
6
6
 
@@ -26,14 +26,15 @@ module Scaffolding
26
26
  oid = options[:oid] || 'oid'
27
27
  name = options[:name] || N::Inflector.name(klass.name)
28
28
  list_name = options[:list_name] || N::Inflector.plural_name(name)
29
- suffix = "_#{name}"
29
+ options[:nosuffix] ? suffix = nil : suffix = "_#{name}"
30
30
 
31
31
  # Add methods to the scaffolded class.
32
32
 
33
33
  klass.module_eval <<-"end_eval", __FILE__, __LINE__
34
34
 
35
35
  def view_uri
36
- "view#{suffix}?oid=\#\{@oid\}"
36
+ # "view#{suffix}?oid=\#\{@oid\}"
37
+ "view#{suffix}/\#\{@oid\}"
37
38
  end
38
39
 
39
40
  end_eval
@@ -59,8 +60,10 @@ module Scaffolding
59
60
  end
60
61
 
61
62
  def view#{suffix}
62
- @#{name} = #{klass}[@context['#{oid}']]
63
+ # @#{name} = #{klass}[@context['#{oid}']]
64
+ @#{name} = #{klass}[@#{oid}]
63
65
  end
66
+ action :view#{suffix}, :route => \%r\{view#{suffix}/(.*)\}, 'oid' => 1
64
67
 
65
68
  def save#{suffix}
66
69
  end
data/lib/nitro/shaders.rb CHANGED
@@ -1,8 +1,8 @@
1
- #--
2
1
  # George Moschovitis <gm@navel.gr>
3
2
  # (c) 2004-2005 Navel, all rights reserved.
4
3
  # $Id: shaders.rb 202 2005-01-17 10:44:13Z gmosx $
5
- #++
4
+
5
+ require 'nitro/template'
6
6
 
7
7
  module N
8
8
 
@@ -56,6 +56,7 @@ end
56
56
  # evaluated.
57
57
 
58
58
  class RubyShader < Shader
59
+ include TemplateMixin
59
60
 
60
61
  # Convert the xhtml script to actual Ruby code, ready to be
61
62
  # evaluated.
@@ -65,10 +66,16 @@ class RubyShader < Shader
65
66
  # perhaps xl:href should be used to be XLink compatible?
66
67
  #++
67
68
 
69
+ def process(hash, text)
70
+ text = compile_template(text)
71
+ process_next(hash, text)
72
+ end
73
+
74
+ =begin
68
75
  def process(hash, text)
69
76
  # strip the xml header! (interracts with the following gsub!)
70
77
  text.gsub!(/<\?xml.*\?>/, "")
71
-
78
+
72
79
  # Statically include sub script files.
73
80
  # The target file is included at compile time.
74
81
  #
@@ -134,6 +141,7 @@ class RubyShader < Shader
134
141
 
135
142
  process_next(hash, text)
136
143
  end
144
+ =end
137
145
 
138
146
  # Loads and statically includes a file.
139
147
 
@@ -223,4 +231,3 @@ class CompressShader < Shader
223
231
  end
224
232
 
225
233
  end
226
-
@@ -0,0 +1,140 @@
1
+ # * George Moschovitis <gm@navel.gr>
2
+ # (c) 2004-2005 Navel, all rights reserved.
3
+ # $Id: template.rb 271 2005-03-07 17:56:45Z gmosx $
4
+
5
+ module N
6
+
7
+ # A template is a text file with embeded Ruby code. The template
8
+ # processor converts the original text file to ruby code and
9
+ # then evaluates this code to produce the result of the
10
+ # template transformation.
11
+
12
+ module TemplateMixin
13
+
14
+ # Convert a template to actual Ruby code, ready to be
15
+ # evaluated.
16
+ #
17
+ # [+template+]
18
+ # The template as a String.
19
+ #
20
+ # [+buffer+]
21
+ # The variable to act as a buffer where the ruby code
22
+ # for this template will be generated. Passed as a|
23
+ # String.
24
+ #
25
+ # [+base_dir+]
26
+ # The base directory where the templates reside.
27
+
28
+ def compile_template(template, buffer = '@out', base_dir = Dir.pwd)
29
+ text = template.dup
30
+
31
+ # Strip the xml header! (interracts with the following gsub!)
32
+ text.gsub!(/<\?xml.*\?>/, "")
33
+
34
+ # Statically include sub-template files.
35
+ # The target file is included at compile time.
36
+ #
37
+ # gmosx: must be xformed before the <?r pi.
38
+ #
39
+ # Example:
40
+ # <?include href="root/myfile.sx" ?>
41
+
42
+ text.gsub!(/<\?include href="(.*?)"(.*)\?>/) do |match|
43
+ text = File.read("#{base_dir}/#$1")
44
+ text.gsub!(/<\?xml.*\?>/, '')
45
+ text.gsub!(/<\/?root(.*?)>/m, ' ');
46
+ text
47
+ end
48
+
49
+ # Transform include instructions <include href="xxx" />
50
+ # must be transformed before the processinc instructions.
51
+ # Useful to include fragments cached on disk
52
+ #
53
+ # gmosx, FIXME: NOT TESTED! test and add caching.
54
+ # add load_statically_included fixes.
55
+
56
+ text.gsub!(/<include href="(.*?)"(.*)(.?)\/>/) do |match|
57
+ "<?r File.read( '\#\{@dispatcher.root\}/#$1' ?>"
58
+ end
59
+
60
+ # xform render/inject instructions <render href="xxx" />
61
+ # must be transformed before the processinc instructions.
62
+
63
+ text.gsub!(/<inject href="(.*?)"(.*)(.?)\/>/) do |match|
64
+ "<?r render '/#$1' ?>"
65
+ end
66
+
67
+ text.gsub!(/<render href="(.*?)"(.*)(.?)\/>/) do |match|
68
+ "<?r render '/#$1' ?>"
69
+ end
70
+
71
+ # Remove <root> elements. typically removed by xslt but lets
72
+ # play it safe. The <root> element is typically added to
73
+ # template files to make them XHTML valid.
74
+
75
+ text.gsub!(/<(\/)?root>/, '')
76
+
77
+ # Transform the processing instructions, use <?r as
78
+ # a marker.
79
+
80
+ text.gsub!(/\?>/, "\n#{buffer} << %^")
81
+ text.gsub!(/<\?r(\s?)/, "^\n")
82
+
83
+ # Transform alternative code tags.
84
+ # (very useful in xsl stylesheets)
85
+
86
+ text.gsub!(/<\/ruby>/, "\n#{buffer} << %^")
87
+ text.gsub!(/<ruby>/, "^\n")
88
+
89
+ # Alterative versions of interpolation.
90
+ # (very useful in xsl stylesheets)
91
+
92
+ text.gsub!(/\#\((.*?)\)/, '#{\1}')
93
+
94
+ # Compile time ruby code. This code is evaluated when
95
+ # compiling the template and the result injected directly
96
+ # into the result. Usefull for example to prevaluate
97
+ # localization.
98
+
99
+ text.gsub!(/\#\[(.*?)\]/) do |match|
100
+ eval($1)
101
+ end
102
+
103
+ text = "#{buffer} << %^" + text + "^"
104
+
105
+ return text
106
+ end
107
+
108
+ # Render the template.
109
+ #
110
+ # [+ruby+]
111
+ # A String containing the compiled template
112
+ # code.
113
+ #
114
+ # [+binding+]
115
+ # The evaluation binding for the rendering.
116
+
117
+ def render_template(ruby, the_binding = nil)
118
+ eval(ruby, the_binding)
119
+ end
120
+
121
+ # Compile and render the template.
122
+
123
+ def process_template(template, buffer = '@out', the_binding = nil)
124
+ render_template(compile_template(template, buffer), the_binding)
125
+ end
126
+
127
+ end
128
+
129
+ # A template class implementing the Template mixin.
130
+
131
+ class Template
132
+ class << self
133
+ include TemplateMixin
134
+ alias_method :compile, :compile_template
135
+ alias_method :render, :render_template
136
+ alias_method :process, :process_template
137
+ end
138
+ end
139
+
140
+ end