nitro 0.22.0 → 0.23.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 (54) hide show
  1. data/CHANGELOG +109 -1250
  2. data/INSTALL +3 -2
  3. data/README +5 -4
  4. data/Rakefile +1 -1
  5. data/bin/nitrogen +1 -1
  6. data/doc/AUTHORS +20 -6
  7. data/doc/CHANGELOG.3 +1314 -0
  8. data/doc/RELEASES +90 -0
  9. data/lib/nitro.rb +6 -17
  10. data/lib/nitro/adapter/cgi.rb +11 -0
  11. data/lib/nitro/adapter/webrick.rb +7 -1
  12. data/lib/nitro/caching/stores.rb +4 -6
  13. data/lib/nitro/compiler.rb +1 -1
  14. data/lib/nitro/compiler/errors.rb +1 -1
  15. data/lib/nitro/context.rb +11 -4
  16. data/lib/nitro/controller.rb +0 -3
  17. data/lib/nitro/cookie.rb +4 -3
  18. data/lib/nitro/dispatcher.rb +7 -1
  19. data/lib/nitro/dispatcher/nice.rb +6 -1
  20. data/lib/nitro/element.rb +2 -2
  21. data/lib/nitro/mixin/benchmark.rb +16 -0
  22. data/lib/nitro/mixin/form.rb +171 -55
  23. data/lib/nitro/mixin/rss.rb +1 -1
  24. data/lib/nitro/mixin/xhtml.rb +91 -4
  25. data/lib/nitro/render.rb +25 -6
  26. data/lib/nitro/request.rb +13 -3
  27. data/lib/nitro/scaffold.rb +91 -68
  28. data/lib/nitro/scaffold/relations.rb +54 -0
  29. data/lib/nitro/server.rb +8 -5
  30. data/lib/nitro/server/runner.rb +4 -3
  31. data/lib/nitro/service.rb +3 -1
  32. data/lib/nitro/service/xmlrpc.rb +1 -1
  33. data/lib/nitro/session.rb +69 -51
  34. data/lib/nitro/session/drb.rb +5 -7
  35. data/lib/nitro/session/drbserver.rb +4 -6
  36. data/lib/nitro/session/memory.rb +4 -6
  37. data/lib/part/admin.rb +6 -0
  38. data/lib/part/admin/controller.rb +24 -0
  39. data/lib/part/admin/skin.rb +21 -0
  40. data/lib/part/admin/template/index.xhtml +9 -0
  41. data/proto/public/js/cookies.js +122 -0
  42. data/proto/public/scaffold/edit.xhtml +4 -0
  43. data/proto/public/scaffold/form.xhtml +7 -0
  44. data/proto/public/scaffold/list.xhtml +15 -0
  45. data/proto/public/scaffold/new.xhtml +4 -0
  46. data/proto/public/scaffold/view.xhtml +0 -0
  47. data/proto/script/benchmark +19 -0
  48. data/test/nitro/adapter/tc_cgi.rb +32 -2
  49. data/test/nitro/mixin/tc_xhtml.rb +6 -0
  50. data/test/nitro/tc_dispatcher.rb +0 -17
  51. data/test/nitro/tc_render.rb +58 -0
  52. data/test/nitro/tc_server.rb +2 -0
  53. data/test/nitro/tc_session.rb +16 -0
  54. metadata +104 -85
@@ -0,0 +1,54 @@
1
+ require 'nitro/scaffold'
2
+
3
+ module Nitro::Scaffolding
4
+
5
+ # A collection of scaffolding helper for Og relations.
6
+
7
+ module Og
8
+
9
+ private
10
+
11
+ # Scaffold the relations of an Og managed object.
12
+
13
+ def scaffold_relations(obj)
14
+ end
15
+
16
+ # Scaffold a +belongs_to+ relation.
17
+
18
+ def belongs_to_editor(obj, rel, options)
19
+ entities = rel.target_class.all
20
+ labels = entities.map { |e| e.to_s }
21
+ values = entities.map { |e| e.oid }
22
+ element(
23
+ label(rel.name),
24
+ %{
25
+ <select id="#{rel.name}" name="#{rel.name}">
26
+ #{options(:labels => labels, :values => values, :selected => 1)}
27
+ </select>
28
+ }
29
+ )
30
+ end
31
+
32
+ # Scaffold a +has_many+ relation.
33
+
34
+ def has_many_editor(obj, rel, options)
35
+ entities = obj.send(rel.target_plural_name)
36
+ unless entities.empty?
37
+ str = entities.inject('') do |acc, e|
38
+ acc << "<tr><td>#{e.to_edit_link(@base)}</td></tr>"
39
+ end
40
+ str = "<table>#{str}</table>"
41
+ else
42
+ str = 'No entities found.<br /><br />'
43
+ end
44
+ element(
45
+ label(rel.name) + '&nbsp;<a href="#">Add</a>',
46
+ %{
47
+ #{str}
48
+ }
49
+ )
50
+ end
51
+
52
+ end
53
+
54
+ end
@@ -1,5 +1,4 @@
1
- require 'glue/autoreload'
2
-
1
+ require 'nitro/controller'
3
2
  require 'nitro/server/runner'
4
3
 
5
4
  module Nitro
@@ -29,6 +28,11 @@ class Server
29
28
 
30
29
  setting :access_log, :default => nil, :doc => 'The access log'
31
30
 
31
+ # Additional server options. Useful to pass options to
32
+ # Webrick for example.
33
+
34
+ setting :options, :default => {}, :doc => "Additional server options"
35
+
32
36
  # The name of the application.
33
37
 
34
38
  attr_accessor :name
@@ -68,7 +72,8 @@ class Server
68
72
  @address, @port = self.class.address, self.class.port
69
73
  @public_root = self.class.public_root
70
74
  @access_log = self.class.access_log
71
- @options = options
75
+ @options = self.class.options.dup
76
+ @options.update(options)
72
77
  end
73
78
 
74
79
  # Return the dispatcher.
@@ -146,5 +151,3 @@ end
146
151
  # Alias for the Server class.
147
152
 
148
153
  App = Nitro::Server unless Object.const_defined?(:App)
149
-
150
- # * George Moschovitis <gm@navel.gr>
@@ -1,6 +1,5 @@
1
1
  require 'optparse'
2
2
 
3
- require 'glue/misc'
4
3
  require 'glue/configuration'
5
4
 
6
5
  module Nitro
@@ -202,7 +201,7 @@ class Runner
202
201
  def setup_debug
203
202
  $DBG = true
204
203
  Compiler.reload = true
205
- require 'glue/autoreload'
204
+ require 'nano/kernel/autoreload'
206
205
  autoreload(3)
207
206
  Caching.caching_enabled = false
208
207
 
@@ -273,7 +272,9 @@ class Runner
273
272
 
274
273
  @server ||= Runner.adapter
275
274
 
276
- puts "\n==> Listening at #{server.address}:#{server.port}. (#{self.class.mode} mode)\n\n"
275
+ puts "\n",
276
+ "==> Listening at #{server.address}:#{server.port}. (#{self.class.mode} mode)",
277
+ "==> Press Ctrl-C to shutdown; Run with --help for options.\n\n"
277
278
 
278
279
  case @server
279
280
  when :webrick
@@ -2,6 +2,8 @@ require 'nitro/controller'
2
2
 
3
3
  module Nitro
4
4
 
5
+ # A Web Service endpoint. This is a specialized controller.
6
+
5
7
  class Service < Nitro::Controller
6
8
 
7
9
  def index
@@ -10,7 +12,7 @@ class Service < Nitro::Controller
10
12
  res = send(method, *args)
11
13
 
12
14
  response.content_type = 'text/xml'
13
-
15
+
14
16
  print encode_response(method, res)
15
17
 
16
18
  return :stop
@@ -20,7 +20,7 @@ module XmlRpc
20
20
 
21
21
  def decode_request(request)
22
22
  method, args = XMLRPC::Marshal.load_call(request)
23
- Logger.debug "Calling XML-RPC method '#{method}'" if $DBG
23
+ Logger.debug "Calling XML-RPC method '#{method}', args: #{args.inspect}" if $DBG
24
24
  return method.gsub(/\./, '__'), args
25
25
  end
26
26
 
@@ -1,7 +1,9 @@
1
1
  require 'md5'
2
2
  require 'webrick'
3
3
 
4
- require 'glue/hash'
4
+ require 'mega/synchash'
5
+ require 'mega/time_in_english'
6
+
5
7
  require 'glue/attribute'
6
8
  require 'glue/configuration'
7
9
 
@@ -30,51 +32,68 @@ class Session < Hash
30
32
 
31
33
  setting :cookie_name, :default => 'nsid', :doc => 'The name of the cookie that stores the session id'
32
34
 
35
+ # The session keepalive time. The session is eligable for
36
+ # garbage collection after this time passes.
37
+
38
+ setting :keepalive, :default => 30.minutes, :doc => 'The session keepalive time'
39
+
33
40
  # The sessions store. By default sessions are
34
41
  # stored in memory.
35
42
 
36
- cattr_accessor :store; @@store = Glue::SafeHash.new
43
+ cattr_accessor :store; @@store = SyncHash.new
37
44
 
38
- # Set the session store. The following options are
39
- # available:
40
- #
41
- # * :memory [default]
42
- # * :drb
43
- # * :memcached (not available yet)
44
- # * :og (not available yet)
45
- # * :file (not available yet)
46
-
47
- def self.store_type=(store_type)
48
- # gmosx: RDoc complains about this, so lets use an
49
- # eval, AAAAAAAARGH!
50
- # require "nitro/session/#{store_type}"
51
- eval %{ require 'nitro/session/#{store_type}' }
52
- end
53
-
54
- # Lookup the session in the store by using the session
55
- # cookie value as a key. If the session does not exist
56
- # creates a new session, inserts it in the store and
57
- # appends a new session cookie in the response.
45
+ class << self
58
46
 
59
- def self.lookup(context)
60
- if session_id = context.cookies[Session.cookie_name]
61
- session = Session.store[session_id]
47
+ # Set the session store. The following options are
48
+ # available:
49
+ #
50
+ # * :memory [default]
51
+ # * :drb
52
+ # * :memcached (not available yet)
53
+ # * :og (not available yet)
54
+ # * :file (not available yet)
55
+
56
+ def store_type=(store_type)
57
+ # gmosx: RDoc complains about this, so lets use an
58
+ # eval, AAAAAAAARGH!
59
+ # require "nitro/session/#{store_type}"
60
+ eval %{ require 'nitro/session/#{store_type}' }
62
61
  end
63
62
 
64
- unless session
65
- # Create new session.
66
- session = Session.new(context)
67
- cookie = Cookie.new(Session.cookie_name, session.session_id)
68
- context.add_cookie(cookie)
69
- Session.store[session.session_id] = session
70
- else
71
- # Access ('touch') the existing session.
72
- session.touch!
63
+ # Lookup the session in the store by using the session
64
+ # cookie value as a key. If the session does not exist
65
+ # creates a new session, inserts it in the store and
66
+ # appends a new session cookie in the response.
67
+
68
+ def lookup(context)
69
+ if session_id = context.cookies[Session.cookie_name]
70
+ session = Session.store[session_id]
71
+ end
72
+
73
+ unless session
74
+ # Create new session.
75
+ session = Session.new(context)
76
+ cookie = Cookie.new(Session.cookie_name, session.session_id)
77
+ context.add_cookie(cookie)
78
+ Session.store[session.session_id] = session
79
+ else
80
+ # Access ('touch') the existing session.
81
+ session.touch!
82
+ end
83
+
84
+ return session
73
85
  end
86
+
87
+ # Perform session garbage collection. Typically this method
88
+ # is called from a cron like mechanism (for example using
89
+ # script/runner).
74
90
 
75
- return session
91
+ def garbage_collection!
92
+ Session.store.delete_if { |key, s| s.invalid? }
93
+ end
94
+ alias_method :gc!, :garbage_collection!
76
95
  end
77
-
96
+
78
97
  # The unique id of this session.
79
98
 
80
99
  attr_reader :session_id
@@ -101,7 +120,7 @@ class Session < Hash
101
120
  @ctime = @mtime = @atime = Time.now
102
121
  end
103
122
 
104
- # Like the unix touch command, upadtes
123
+ # Like the unix touch command, updates
105
124
  # the atime to now.
106
125
 
107
126
  def touch!
@@ -117,6 +136,19 @@ class Session < Hash
117
136
  end
118
137
  alias_method :restore, :sync
119
138
 
139
+ # Keep this session alive?
140
+
141
+ def valid?
142
+ Time.now < @atime + Session.keepalive
143
+ end
144
+ alias_method :alive?, :valid?
145
+
146
+ # The reverse of keepalive?
147
+
148
+ def invalid?
149
+ Time.now > @atime + Session.keepalive
150
+ end
151
+
120
152
  protected
121
153
 
122
154
  # Calculates a unique id.
@@ -138,20 +170,6 @@ protected
138
170
 
139
171
  end
140
172
 
141
- # Abstract class for a session store manager.
142
-
143
- class SessionStore
144
- def []=(sid, session)
145
- end
146
-
147
- def [](sid)
148
- end
149
-
150
- def delete(sid)
151
- end
152
-
153
- end
154
-
155
173
  end
156
174
 
157
175
  # * George Moschovitis <gm@navel.gr>
@@ -1,10 +1,6 @@
1
- # * George Moschovitis <gm@navel.gr>
2
- # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id: drb.rb 182 2005-07-22 10:07:50Z gmosx $
4
-
5
1
  require 'drb'
6
2
 
7
- require 'glue/attribute'
3
+ require 'glue/configuration'
8
4
  require 'nitro/session'
9
5
 
10
6
  Logger.debug 'Using Drb sessions.'
@@ -15,11 +11,11 @@ class Session
15
11
 
16
12
  # The address of the Session DRb server.
17
13
 
18
- cattr_accessor :drb_address, '127.0.0.1'
14
+ setting :drb_address, :default => '127.0.0.1', :doc => 'The address of the Session DRb server'
19
15
 
20
16
  # The port of the Session DRb server.
21
17
 
22
- cattr_accessor :drb_port, 9069
18
+ setting :drb_port, :default => 9069, :doc => 'The port of the Session DRb server'
23
19
 
24
20
  end
25
21
 
@@ -29,3 +25,5 @@ Session.store = DRbObject.new(
29
25
  )
30
26
 
31
27
  end
28
+
29
+ # * George Moschovitis <gm@navel.gr>
@@ -1,13 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- # * George Moschovitis <gm@navel.gr>
4
- # (c) 2004-2005 Navel, all rights reserved.
5
- # $Id: drbserver.rb 182 2005-07-22 10:07:50Z gmosx $
6
-
7
3
  require 'drb'
8
4
  require 'optparse'
9
5
 
10
- require 'glue/hash'
6
+ require 'mega/synchash'
11
7
  require 'nitro/session'
12
8
 
13
9
  # A distributes session store implemented as
@@ -49,7 +45,7 @@ rescue OptionParser::InvalidOption
49
45
  exit
50
46
  end
51
47
 
52
- sessions = Glue::SafeHash.new
48
+ sessions = SyncHash.new
53
49
 
54
50
  if debug
55
51
 
@@ -69,3 +65,5 @@ end
69
65
 
70
66
  DRb.start_service("druby://#{address}:#{port}", sessions)
71
67
  DRb.thread.join
68
+
69
+ # * George Moschovitis <gm@navel.gr>
@@ -1,13 +1,11 @@
1
- # * George Moschovitis <gm@navel.gr>
2
- # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id: memory.rb 1 2005-04-11 11:04:30Z gmosx $
4
-
5
- require 'glue/hash'
1
+ require 'mega/synchash'
6
2
 
7
3
  Logger.debug 'Using In-Memory sessions.'
8
4
 
9
5
  module Nitro
10
6
 
11
- Session.store = SafeHash.new
7
+ Session.store = SyncHash.new
12
8
 
13
9
  end
10
+
11
+ # * George Moschovitis <gm@navel.gr>
@@ -0,0 +1,6 @@
1
+ require 'nitro/server'
2
+
3
+ require 'part/admin/controller'
4
+ require 'part/admin/skin'
5
+
6
+ Nitro::Server.map['/admin'] = AdminController
@@ -0,0 +1,24 @@
1
+ require 'nitro/controller'
2
+
3
+ class AdminController < Nitro::Controller
4
+
5
+ @template_root = File.join(File.dirname(__FILE__), 'template')
6
+
7
+ def index
8
+ @classes = self.class.managed_classes
9
+ end
10
+
11
+ class << self
12
+ # The managed classes of this application.
13
+
14
+ attr_accessor :managed_classes
15
+
16
+ # Called when this controller is mounted.
17
+
18
+ def mounted
19
+ @managed_classes = Og.manager.manageable_classes
20
+ @managed_classes.each { |c| scaffold(c) }
21
+ end
22
+ end
23
+
24
+ end
@@ -0,0 +1,21 @@
1
+ require 'nitro/element'
2
+
3
+ class SystemPage < Nitro::Element
4
+ def render
5
+ %~
6
+ <html>
7
+ <head>
8
+ <title>#@name</title>
9
+ <base href="\#{context.host_url}/" />
10
+ <link rel="stylesheet" href="/system.css" type="text/css" media="screen" />
11
+ </head>
12
+ <body>
13
+ <h1>#@name</h1>
14
+ #{content}
15
+ <br />
16
+ Powered by <a href="http://www.nitrohq.com">Nitro</a> version #{Nitro::Version}
17
+ </body>
18
+ </html>
19
+ ~
20
+ end
21
+ end
@@ -0,0 +1,9 @@
1
+ <SystemPage name="System">
2
+ <table>
3
+ <?r for c in @classes ?>
4
+ <tr>
5
+ <td><a href="#@base/#{c.name.plural.underscore}">#{c.name}</a> (#{c.count})</td>
6
+ </tr>
7
+ <?r end ?>
8
+ </table>
9
+ </SystemPage>