nitro 0.27.0 → 0.28.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 +276 -0
  2. data/ProjectInfo +4 -4
  3. data/README +9 -1
  4. data/Rakefile +1 -1
  5. data/doc/AUTHORS +30 -17
  6. data/doc/RELEASES +110 -23
  7. data/lib/glue/sweeper.rb +1 -1
  8. data/lib/glue/webfile.rb +1 -1
  9. data/lib/nitro.rb +1 -1
  10. data/lib/nitro/adapter/acgi.rb +5 -1
  11. data/lib/nitro/adapter/cgi.rb +4 -0
  12. data/lib/nitro/adapter/fastcgi.rb +12 -1
  13. data/lib/nitro/adapter/mongrel.rb +219 -0
  14. data/lib/nitro/adapter/scgi.rb +62 -69
  15. data/lib/nitro/caching.rb +6 -5
  16. data/lib/nitro/caching/actions.rb +14 -8
  17. data/lib/nitro/caching/fragments.rb +32 -17
  18. data/lib/nitro/caching/output.rb +10 -2
  19. data/lib/nitro/cgi.rb +7 -3
  20. data/lib/nitro/cgi/stream.rb +1 -3
  21. data/lib/nitro/compiler.rb +5 -4
  22. data/lib/nitro/compiler/errors.rb +1 -1
  23. data/lib/nitro/compiler/morphing.rb +2 -2
  24. data/lib/nitro/compiler/script.rb +1 -1
  25. data/lib/nitro/context.rb +8 -2
  26. data/lib/nitro/controller.rb +1 -1
  27. data/lib/nitro/dispatcher.rb +0 -2
  28. data/lib/nitro/element.rb +5 -5
  29. data/lib/nitro/flash.rb +1 -1
  30. data/lib/nitro/helper.rb +2 -2
  31. data/lib/nitro/helper/form.rb +1 -1
  32. data/lib/nitro/helper/form/controls.rb +2 -1
  33. data/lib/nitro/helper/javascript.rb +1 -1
  34. data/lib/nitro/helper/javascript/morphing.rb +1 -1
  35. data/lib/nitro/helper/layout.rb +1 -1
  36. data/lib/nitro/helper/pager.rb +7 -3
  37. data/lib/nitro/helper/rss.rb +1 -1
  38. data/lib/nitro/render.rb +1 -1
  39. data/lib/nitro/scaffolding.rb +26 -4
  40. data/lib/nitro/server/drb.rb +106 -0
  41. data/lib/nitro/server/runner.rb +23 -2
  42. data/lib/nitro/session.rb +33 -16
  43. data/lib/nitro/session/drb.rb +6 -20
  44. data/lib/nitro/session/file.rb +4 -49
  45. data/lib/nitro/session/memory.rb +16 -0
  46. data/lib/nitro/session/og.rb +4 -46
  47. data/src/part/admin/controller.rb +2 -3
  48. data/src/part/admin/template/index.xhtml +1 -1
  49. data/test/nitro/tc_cgi.rb +72 -3
  50. data/test/nitro/tc_render.rb +1 -1
  51. data/test/nitro/tc_session.rb +16 -15
  52. metadata +12 -14
  53. data/lib/nitro/caching/invalidation.rb +0 -25
  54. data/lib/nitro/caching/stores.rb +0 -94
  55. data/lib/nitro/helper/form/test.xhtml +0 -0
  56. data/lib/nitro/session/drbserver.rb +0 -84
@@ -1,5 +1,3 @@
1
- require 'fileutils'
2
-
3
1
  require 'glue/attribute'
4
2
  require 'glue/configuration'
5
3
  require 'glue/sweeper'
@@ -10,7 +8,11 @@ require 'nitro/caching/fragments'
10
8
 
11
9
  module Nitro
12
10
 
13
- # Adds support for caching.
11
+ # Nitro Hierarchical Caching system.
12
+ #
13
+ # # Output caching (caches the whole page, main action)
14
+ # # Action caching (cache the fragment generated by an action)
15
+ # # Fragment caching (fine-grained fragment caching, cache snippets of code)
14
16
  #--
15
17
  # TODO: add per controller caching_enabled.
16
18
  #++
@@ -21,8 +23,7 @@ module Caching
21
23
 
22
24
  setting :caching_enabled, :default => true, :doc => 'Globaly enable/disable caching'
23
25
 
24
- def self.append_features(base) #:nodoc:
25
- super
26
+ def self.included(base) #:nodoc:
26
27
  base.send :include, Output, Actions, Fragments
27
28
  base.module_eval do
28
29
  # @caching_enabled = true
@@ -1,17 +1,21 @@
1
1
  require 'fileutils'
2
2
 
3
+ require 'nitro/caching/fragments'
4
+
3
5
  module Nitro
4
6
 
5
7
  # Adds support for caching.
6
8
 
7
9
  module Caching
8
10
 
9
- # Action caching.
11
+ # Action caching is a set of helper to allow the caching
12
+ # generated by an action. In the caching hierarchy it lies
13
+ # between Output caching (top action, full page) and fragment
14
+ # caching (fine-grained caching).
10
15
 
11
16
  module Actions
12
17
 
13
- def self.append_features(base) # :nodoc:
14
- super
18
+ def self.included(base) # :nodoc:
15
19
  base.extend(ClassMethods)
16
20
  end
17
21
 
@@ -20,10 +24,10 @@ module Caching
20
24
  def cache_action(*actions)
21
25
  return unless caching_enabled?
22
26
 
23
- before_filter(
27
+ before(
24
28
  %{
25
29
  fragment_name = "\#\{@action_name\}\#{@request.query_string}"
26
- if fragment = Fragment.get(fragment_name)
30
+ if fragment = Fragments.get(fragment_name)
27
31
  @out = fragment
28
32
  return
29
33
  end
@@ -31,10 +35,10 @@ module Caching
31
35
  :only => actions
32
36
  )
33
37
 
34
- after_filter(
38
+ after(
35
39
  %{
36
40
  fragment_name = "\#\{@action_name\}\#{@request.query_string}"
37
- Fragment.put(fragment_name, @out)
41
+ Fragments.put(fragment_name, @out)
38
42
  },
39
43
  :only => actions
40
44
  )
@@ -44,8 +48,10 @@ module Caching
44
48
 
45
49
  private
46
50
 
51
+ # Expire the cached fragment of the given actions.
52
+ #
47
53
  #--
48
- # FIXME: not implemented.
54
+ # FIXME: not very good implementation?
49
55
  #++
50
56
 
51
57
  def expire_action(*actions)
@@ -1,7 +1,8 @@
1
1
  require 'fileutils'
2
2
 
3
+ require 'glue/configuration'
3
4
  require 'glue/attribute'
4
- require 'nitro/caching/stores'
5
+ require 'glue/cache/memory'
5
6
 
6
7
  module Nitro
7
8
 
@@ -10,40 +11,53 @@ module Nitro
10
11
  module Caching
11
12
 
12
13
  # Action caching. Caches a fragment, ie a page part.
13
- # Use output cachingfor full page caching.
14
+ # Use output caching for full page caching.
14
15
 
15
16
  module Fragments
16
17
 
17
- @@store = FileStore.new # MemoryStore.new
18
-
19
- def self.store
20
- @@store
21
- end
18
+ # The cache used to store the fragments.
22
19
 
23
- def self.store=(store)
24
- @@store = store
25
- end
20
+ setting :cache, :default => nil, :doc => 'The cache used to store the fragments'
21
+
22
+ #--
23
+ # gmosx, FIXME: this is a hack, improve setting
24
+ # implementation.
25
+ #++
26
+
27
+ @@cache = Glue::MemoryCache.new
26
28
 
27
29
  def self.get(name, options = {})
28
- return @@store.read(name, options)
30
+ return @@cache.get(name, options)
29
31
  end
30
32
 
31
33
  def self.put(name, content = nil, options = {})
32
- @@store.write(name, content, options)
34
+ @@cache.put(name, content, options)
33
35
  return content
34
36
  end
35
37
 
36
- def self.append_features(base) # :nodoc:
37
- super
38
- end
39
-
40
38
  private
41
39
 
40
+ # Helper method to cache a fragment.
41
+ #
42
+ # === Example
43
+ #
44
+ # ...
45
+ # <h1>Article list</h1>
46
+ #
47
+ # <?r cache(:my_cache_key) do ?>
48
+ # <ul>
49
+ # <li each="a in Article.all">#{a.title}</li>
50
+ # </ul>
51
+ # <?r end ?>
52
+ # ...
53
+
42
54
  def cache(name = nil, options = {}, &block)
43
55
  name = @action_name unless name
44
56
  cache_fragment(block, "#{name}#{options}", options)
45
57
  end
46
58
 
59
+ # Internal method, prefer to use cache instead.
60
+
47
61
  def cache_fragment(block, name, options = {})
48
62
  unless caching_enabled?
49
63
  block.call
@@ -59,13 +73,14 @@ module Caching
59
73
  end
60
74
  end
61
75
 
76
+ # Expire a cached fragment.
62
77
  #--
63
78
  # gmosx: If you modify the code here, don't forget to modify
64
79
  # the same method on the sweeper.
65
80
  #++
66
81
 
67
82
  def expire_fragment(name, options = {})
68
- Fragments.store.delete(name, options)
83
+ Fragments.cache.delete(name, options)
69
84
  end
70
85
  end
71
86
 
@@ -6,12 +6,20 @@ module Nitro
6
6
 
7
7
  module Caching
8
8
 
9
- # Output caching.
9
+ # The Output caching subsystem stores whole pages in the
10
+ # filesystem to be served directly be the front web server
11
+ # (Lighttpd, Apache, etc) for optimal performance.
12
+ #
13
+ # Nitro promotes coding your application in such a way as to
14
+ # allow for output caching to the greatest extend.
15
+ #--
16
+ # gmosx, FIXME: Don't create excessive directories, use better
17
+ # rewrite rules to handle xxx.html files.
18
+ #++
10
19
 
11
20
  module Output
12
21
 
13
22
  def self.included(base) # :nodoc:
14
- super
15
23
  base.extend(ClassMethods)
16
24
  base.module_eval do
17
25
  cattr_accessor :output_cache_root, 'public'
@@ -45,9 +45,13 @@ class Cgi
45
45
  out.print(Cgi.response_headers(context))
46
46
 
47
47
  if context.out.is_a?(IO)
48
- while buf = context.out.read(4096)
49
- out.write(buf)
50
- end
48
+ begin
49
+ while buf = context.out.read(4096)
50
+ out.write(buf)
51
+ end
52
+ ensure
53
+ context.out.close
54
+ end
51
55
  else
52
56
  out.print(context.out)
53
57
  end
@@ -27,10 +27,8 @@ module Render
27
27
  Thread.new do
28
28
  begin
29
29
  yield
30
- rescue Object => ex
31
- p ex
32
30
  ensure
33
- w.close
31
+ w.close
34
32
  end
35
33
  end
36
34
  end
@@ -1,5 +1,3 @@
1
- require 'nano/kernel/singleton'
2
-
3
1
  require 'glue/template'
4
2
 
5
3
  require 'nitro/compiler/elements'
@@ -215,14 +213,17 @@ class Compiler
215
213
  code << "params = [];"
216
214
  end
217
215
  code << %{
218
- if context.query_string
219
- context.query_string.split(/[&;]/).each_with_index do |qs, i|
216
+ unless context.query_string.blank?
217
+ all_params = context.query_string.split(/[&;]/)
218
+ is_hash = all_params.first.index('=')
219
+ all_params.each_with_index do |qs, i|
220
220
  }
221
221
  # Don't pass more parameters than the action's arity.
222
222
  if param_count > 0
223
223
  code << "break unless i < #{param_count};"
224
224
  end
225
225
  code << %{
226
+ break if qs.index('=') and not is_hash
226
227
  params[i] = CGI.unescape(qs.split(/=/).last)
227
228
  end
228
229
  end
@@ -1,4 +1,4 @@
1
- require 'mega/orm_support'
1
+ require 'facet/ormsupport'
2
2
 
3
3
  module Nitro
4
4
 
@@ -1,8 +1,8 @@
1
1
  require 'rexml/document'
2
2
  require 'rexml/streamlistener'
3
3
 
4
- require 'mega/dictionary'
5
- require 'nano/string/blank'
4
+ require 'facet/dictionary'
5
+ require 'facet/string/blank'
6
6
 
7
7
  require 'glue/html'
8
8
 
@@ -1,4 +1,4 @@
1
- require 'nano/kernel/constant'
1
+ require 'facet/kernel/constant'
2
2
 
3
3
  require 'nitro/helper/javascript'
4
4
 
@@ -1,4 +1,4 @@
1
- require 'nano/kernel/assign_with'
1
+ require 'facet/kernel/assign_with'
2
2
 
3
3
  require 'nitro/cgi'
4
4
  require 'nitro/cgi/request'
@@ -55,7 +55,13 @@ class Context
55
55
  # end of the HTTP request handling code.
56
56
 
57
57
  def close
58
- @session.sync if @session
58
+ if @session
59
+ # Ugly hack: need to use AOP instead
60
+ if @session.has_key?(:FLASH)
61
+ @session[:FLASH].clean
62
+ end
63
+ @session.sync
64
+ end
59
65
  end
60
66
  alias_method :finish, :close
61
67
 
@@ -1,4 +1,4 @@
1
- require 'mega/annotation'
1
+ require 'facet/annotation'
2
2
 
3
3
  require 'glue/aspects'
4
4
  require 'glue/markup'
@@ -1,5 +1,3 @@
1
- require 'nano/kernel/singleton'
2
-
3
1
  require 'nitro/controller'
4
2
  require 'nitro/compiler'
5
3
  require 'nitro/routing'
@@ -1,8 +1,8 @@
1
- require 'nano/string/capitalized'
2
- require 'nano/string/camelize'
3
- require 'nano/string/underscore'
4
- require 'nano/dir/self/recurse'
5
- require 'mega/annotation'
1
+ require 'facet/string/capitalized'
2
+ require 'facet/string/camelize'
3
+ require 'facet/string/underscore'
4
+ require 'facet/dir/self/recurse'
5
+ require 'facet/annotation'
6
6
 
7
7
  require 'glue/flexob'
8
8
  require 'glue/configuration'
@@ -9,7 +9,7 @@ module Nitro
9
9
  def self.append_features(base)
10
10
  super
11
11
  base.before 'flash.discard'
12
- base.after 'flash.clean'
12
+ #base.after 'flash.clean'
13
13
  end
14
14
 
15
15
  # A Flash is a special hash object that lives in the session.
@@ -1,5 +1,5 @@
1
- require 'nano/kernel/constant'
2
- require 'nano/string/camelize'
1
+ require 'facet/kernel/constant'
2
+ require 'facet/string/camelize'
3
3
 
4
4
  require 'glue/attribute'
5
5
 
@@ -1,4 +1,4 @@
1
- require 'nano/inflect'
1
+ require 'facet/inflect'
2
2
 
3
3
  require 'nitro/helper/form/controls'
4
4
 
@@ -266,7 +266,8 @@ class HasManyControl < Control
266
266
  # to extend and customise the HasManyControl
267
267
 
268
268
  def all_items
269
- rel.target_class.all
269
+ return @all_items unless @all_items.nil?
270
+ @all_items = rel.target_class.all
270
271
  end
271
272
 
272
273
  def selected_items
@@ -1,4 +1,4 @@
1
- require 'nano/inflect'
1
+ require 'facet/inflect'
2
2
 
3
3
  module Nitro
4
4
 
@@ -1,4 +1,4 @@
1
- require 'mega/dictionary'
1
+ require 'facet/dictionary'
2
2
 
3
3
  require 'nitro/compiler/morphing'
4
4
 
@@ -1,4 +1,4 @@
1
- require 'nano/string/camelize'
1
+ require 'facet/inflect'
2
2
 
3
3
  require 'nitro/element'
4
4
 
@@ -120,12 +120,16 @@ class Pager
120
120
  end
121
121
  end
122
122
 
123
+ # Is the pager empty, ie has one page only?
124
+
123
125
  def empty?
124
- return @items.empty?
126
+ return @page_count < 1
125
127
  end
126
128
 
129
+ # The items count.
130
+
127
131
  def size
128
- return @items.size()
132
+ return @total_count
129
133
  end
130
134
 
131
135
  # Returns the range of the current page.
@@ -271,7 +275,7 @@ private
271
275
  when Array
272
276
  items = items.dup
273
277
  pager = Pager.new(request, per_page, items.size, pager_key)
274
- items = items.slice(pager.offset, pager.per_page)
278
+ items = items.slice(pager.offset, pager.per_page) || []
275
279
  return items, pager
276
280
 
277
281
  when Og::Collection
@@ -1,7 +1,7 @@
1
1
  require 'cgi'
2
2
  require 'rss/0.9'
3
3
 
4
- require 'nano/string/first_char'
4
+ require 'facet/string/first_char'
5
5
 
6
6
  require 'glue/markup'
7
7
 
@@ -2,7 +2,7 @@ require 'singleton'
2
2
  require 'sync'
3
3
  require 'stringio'
4
4
 
5
- require 'nano/string/blank'
5
+ require 'facet/string/blank'
6
6
 
7
7
  require 'glue/attribute'
8
8
  require 'glue/settings'
@@ -56,8 +56,13 @@ module Scaffolding
56
56
  @plural = options[:plural_name]
57
57
  @suffix = options[:suffix]
58
58
  @compiler = Compiler.new(@controller)
59
+
59
60
  @base = options[:base] || options[:mount] || options[:at]
60
- @base = @plural.dup if @base == true
61
+ if @base == true
62
+ @base = @plural.dup
63
+ elsif @base == :ROOT
64
+ @base = nil
65
+ end
61
66
  @base__ = "#{@base}__" if @base
62
67
  end
63
68
 
@@ -257,6 +262,16 @@ module Scaffolding
257
262
  # This method modifies both the controller and the
258
263
  # scaffolded Class.
259
264
  #
265
+ #
266
+ # === Options
267
+ #
268
+ # * base/mount : mountpoint for the action, defines a
269
+ # prefix for the scaffolded action.
270
+ # If mount => true, the prefix is the plural of the
271
+ # scaffolded class name.
272
+ # If mount => :ROOT or nil, the actions are mounted at the
273
+ # root of the controller.
274
+ #
260
275
  # === Example
261
276
  #
262
277
  # scaffold Article
@@ -278,6 +293,8 @@ module Scaffolding
278
293
  #--
279
294
  # This is the first phase of the scaffolding proccess,
280
295
  # scaffold targets are marked, and default options set.
296
+ #
297
+ # FIXME: Rethink the options, make :ROOT the default.
281
298
  #++
282
299
 
283
300
  def scaffold(klass, options = {})
@@ -301,7 +318,7 @@ module Scaffolding
301
318
 
302
319
  def compile_scaffolding_code
303
320
  # load scaffolding for all og classes if specified
304
-
321
+
305
322
  if scaffold_all?
306
323
  options = scaffold_all_options
307
324
  Og.manager.manageable_classes.each do |klass|
@@ -320,8 +337,13 @@ module Scaffolding
320
337
  end
321
338
 
322
339
  #--
323
- # set the options flag to trigger scaffolding of all classes in second phase
324
- # use exclude to ignore classes.... scaffold_all :exclude => [Product, Category]
340
+ # set the options flag to trigger scaffolding of all classes
341
+ # in second phase.
342
+ # use exclude to ignore classes:
343
+ # scaffold_all :exclude => [Product, Category]
344
+ #
345
+ # gmosx: I do NOT lke this, will remove this in a future
346
+ # version.
325
347
  #++
326
348
 
327
349
  def scaffold_all(options = {})