nitro 0.25.0 → 0.26.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 (76) hide show
  1. data/CHANGELOG +531 -1
  2. data/ProjectInfo +29 -5
  3. data/README +1 -1
  4. data/doc/AUTHORS +12 -6
  5. data/doc/RELEASES +114 -0
  6. data/lib/glue/sweeper.rb +71 -0
  7. data/lib/nitro.rb +19 -12
  8. data/lib/nitro/adapter/cgi.rb +4 -0
  9. data/lib/nitro/adapter/webrick.rb +4 -2
  10. data/lib/nitro/caching.rb +1 -0
  11. data/lib/nitro/caching/fragments.rb +7 -1
  12. data/lib/nitro/caching/output.rb +6 -1
  13. data/lib/nitro/caching/stores.rb +13 -1
  14. data/lib/nitro/cgi.rb +9 -1
  15. data/lib/nitro/cgi/request.rb +11 -3
  16. data/lib/nitro/cgi/utils.rb +24 -2
  17. data/lib/nitro/compiler.rb +89 -63
  18. data/lib/nitro/compiler/cleanup.rb +16 -0
  19. data/lib/nitro/compiler/elements.rb +117 -0
  20. data/lib/nitro/compiler/markup.rb +3 -1
  21. data/lib/nitro/compiler/morphing.rb +203 -73
  22. data/lib/nitro/compiler/script_generator.rb +14 -0
  23. data/lib/nitro/compiler/shaders.rb +1 -1
  24. data/lib/nitro/context.rb +5 -6
  25. data/lib/nitro/controller.rb +43 -21
  26. data/lib/nitro/dispatcher.rb +86 -37
  27. data/lib/nitro/element.rb +3 -105
  28. data/lib/nitro/helper/benchmark.rb +3 -0
  29. data/lib/nitro/helper/dojo.rb +0 -0
  30. data/lib/nitro/helper/form.rb +85 -255
  31. data/lib/nitro/helper/form/controls.rb +274 -0
  32. data/lib/nitro/helper/javascript.rb +86 -6
  33. data/lib/nitro/helper/pager.rb +5 -0
  34. data/lib/nitro/helper/prototype.rb +49 -0
  35. data/lib/nitro/helper/scriptaculous.rb +0 -0
  36. data/lib/nitro/helper/xhtml.rb +11 -8
  37. data/lib/nitro/helper/xml.rb +1 -1
  38. data/lib/nitro/routing.rb +8 -1
  39. data/lib/nitro/scaffolding.rb +344 -0
  40. data/lib/nitro/server.rb +5 -1
  41. data/lib/nitro/server/runner.rb +19 -15
  42. data/lib/nitro/session.rb +32 -56
  43. data/lib/nitro/session/drbserver.rb +1 -1
  44. data/lib/nitro/session/file.rb +34 -15
  45. data/lib/nitro/session/memory.rb +13 -4
  46. data/lib/nitro/session/og.rb +56 -0
  47. data/proto/public/js/controls.js +30 -1
  48. data/proto/public/js/dragdrop.js +211 -146
  49. data/proto/public/js/effects.js +261 -399
  50. data/proto/public/js/prototype.js +131 -72
  51. data/proto/public/scaffold/edit.xhtml +10 -3
  52. data/proto/public/scaffold/form.xhtml +1 -7
  53. data/proto/public/scaffold/index.xhtml +20 -0
  54. data/proto/public/scaffold/list.xhtml +15 -8
  55. data/proto/public/scaffold/new.xhtml +10 -3
  56. data/proto/public/scaffold/search.xhtml +28 -0
  57. data/proto/public/scaffold/view.xhtml +8 -0
  58. data/proto/run.rb +93 -1
  59. data/src/part/admin.rb +4 -2
  60. data/src/part/admin/controller.rb +62 -28
  61. data/src/part/admin/skin.rb +8 -8
  62. data/src/part/admin/system.css +135 -0
  63. data/src/part/admin/template/index.xhtml +8 -12
  64. data/test/nitro/caching/tc_stores.rb +17 -0
  65. data/test/nitro/tc_caching.rb +1 -4
  66. data/test/nitro/tc_dispatcher.rb +22 -10
  67. data/test/nitro/tc_element.rb +1 -1
  68. data/test/nitro/tc_session.rb +23 -11
  69. data/test/public/blog/another/very_litle/index.xhtml +1 -0
  70. metadata +29 -15
  71. data/lib/nitro/dispatcher/general.rb +0 -62
  72. data/lib/nitro/dispatcher/nice.rb +0 -57
  73. data/lib/nitro/scaffold.rb +0 -171
  74. data/proto/public/index.xhtml +0 -83
  75. data/proto/public/js/scaffold.js +0 -74
  76. data/proto/public/settings.xhtml +0 -66
File without changes
@@ -37,21 +37,24 @@ private
37
37
  if labels = options[:labels] || options[:labels_values]
38
38
  str = ''
39
39
 
40
- unless values = options[:values]
41
- if values = options[:labels_values]
42
- else
43
- values = (0...labels.size).to_a
44
- end
45
- end
40
+ values = options[:values] || options[:labels_values] || (0...labels.size).to_a
46
41
 
47
42
  selected = (options[:selected] || -1).to_i
48
43
 
49
44
  labels.each_with_index do |label, idx|
50
45
  value = values[idx]
46
+ if options[:style]
47
+ style = if options[:style].is_a?(Array)
48
+ options[:style][idx]
49
+ else
50
+ options[:style]
51
+ end
52
+ style = %{ style="#{style}"}
53
+ end
51
54
  if value == selected
52
- str << %|<option value="#{value}" selected="1">#{label}</option>|
55
+ str << %|<option value="#{value}" selected="selected"#{style}>#{label}</option>|
53
56
  else
54
- str << %|<option value="#{value}">#{label}</option>|
57
+ str << %|<option value="#{value}"#{style}>#{label}</option>|
55
58
  end
56
59
  end
57
60
 
@@ -99,7 +99,7 @@ end
99
99
  # output to a target buffer.
100
100
 
101
101
  class XmlBuilder
102
- include XmlMixin
102
+ include XmlHelper
103
103
 
104
104
  # The target receives the generated xml,
105
105
  # should respond_to :<<
@@ -3,6 +3,9 @@ module Nitro
3
3
  # Router mixin. Typically used to generate 'nice' urls.
4
4
  # Nice urls are considered (?) more Search Engine
5
5
  # friendly.
6
+ #
7
+ # However, due to the power of Nitro'w intelligent dispatching
8
+ # mechanism, routing is almost never used!
6
9
 
7
10
  module Router
8
11
 
@@ -10,6 +13,10 @@ module Router
10
13
  # can be handled by the Dispatcher.
11
14
 
12
15
  attr_accessor :routes
16
+
17
+ # Strip the beginning of the path, used by cgi adapter.
18
+
19
+ setting :strip_path, :default => nil, :doc => 'Strip the beginning of the path, used by cgi adapter'
13
20
 
14
21
  # Apply routing rules to the path.
15
22
 
@@ -23,6 +30,7 @@ module Router
23
30
  end
24
31
  end
25
32
 
33
+ path.sub!(Router.strip_path, '') if Router.strip_path
26
34
  return path
27
35
  end
28
36
 
@@ -31,4 +39,3 @@ end
31
39
  end
32
40
 
33
41
  # * George Moschovitis <gm@navel.gr>
34
-
@@ -0,0 +1,344 @@
1
+ require 'nitro/helper/form'
2
+ require 'nitro/helper/pager'
3
+
4
+
5
+ module Nitro
6
+
7
+ # This module is applied to controllers to provide
8
+ # automatically generated CRUD methods.
9
+ #--
10
+ # TODO: add search, add base, add to_title, validate/error
11
+ # handling.
12
+ #++
13
+
14
+ module Scaffolding
15
+
16
+ # The directory where the default scaffold templates reside.
17
+
18
+ setting :template_root, :default => File.join(Nitro.proto_path, 'public', 'scaffold'), :doc => 'The directory where the default scaffold templates reside'
19
+
20
+ # The items to show per page in the scaffolder lists.
21
+
22
+ setting :per_page, :default => 20, :doc => 'The items to show per page in the scaffolder lists'
23
+
24
+ def self.included(base)
25
+ super
26
+ base.helper(:form)
27
+ base.helper(:pager)
28
+ base.extend(ClassMethods)
29
+ end
30
+
31
+ def self.class_to_name(klass)
32
+ klass.to_s.demodulize.underscore.downcase
33
+ end
34
+
35
+ def self.class_to_list(klass)
36
+ klass.to_s.demodulize.underscore.downcase.plural
37
+ end
38
+
39
+ #--
40
+ # Compiles the scaffolding code.
41
+ #++
42
+
43
+ class ScaffoldCompiler
44
+
45
+ def initialize(controller, klass, options)
46
+ @controller = controller
47
+ @klass = klass
48
+ @options = options
49
+ @oid = options[:oid] || options[:pk]
50
+ @name = options[:name]
51
+ @plural = options[:plural_name]
52
+ @suffix = options[:suffix]
53
+ @compiler = Compiler.new(@controller)
54
+ @base = options[:base] || options[:mount] || options[:at]
55
+ @base = @plural.dup if @base == true
56
+ @base__ = "#{@base}__" if @base
57
+ end
58
+
59
+ def class_to_name(klass)
60
+ klass.to_s.demodulize.underscore.downcase
61
+ end
62
+
63
+ def define_class_method(meth, code)
64
+ unless @klass.instance_methods.include?(meth.to_s)
65
+ @klass.module_eval %{
66
+ def #{meth}
67
+ #{code}
68
+ end
69
+ }
70
+ end
71
+ end
72
+
73
+ def define_controller_action(definition, code, template = nil)
74
+ sym, args = definition.to_s.split(/\(|\)/)
75
+
76
+ if sym == 'index'
77
+ action = "#{@base__}index"
78
+ else
79
+ action = "#@base__#{sym}#@suffix"
80
+ end
81
+
82
+ unless @controller.action?(action)
83
+ @controller.module_eval %{
84
+ def #{action}(#{args})
85
+ @klass = #{@klass}
86
+ #{code}
87
+ end
88
+ }
89
+ end
90
+
91
+ unless @compiler.template?(action)
92
+
93
+ # Use the standard scaffold template.
94
+ path = File.join(Scaffolding.template_root, "#{template || sym}.xhtml")
95
+
96
+ if File.exist?(path) and source = File.read(path)
97
+ # Interpolate the source.
98
+ source.gsub!(/%base%/, @base.to_s)
99
+ source.gsub!(/%name%/, @name)
100
+ source.gsub!(/%plural%/, @plural)
101
+
102
+ # Transform the source.
103
+ source = @compiler.transform_template(source)
104
+
105
+ @controller.module_eval %{
106
+ def #{action}_template
107
+ #{source}
108
+ end
109
+ }
110
+ end
111
+ end
112
+ end
113
+
114
+ # Scaffold the class and the controller.
115
+
116
+ def scaffold
117
+ scaffold_class
118
+ scaffold_controller
119
+ end
120
+
121
+ # Scaffold the class.
122
+
123
+ def scaffold_class
124
+ define_class_method :scaffold_base, %{
125
+ "#{@controller.ann.self.mount_point}/#@base"
126
+ }
127
+
128
+ define_class_method :to_href, %{
129
+ "#{@controller.ann.self.mount_point}/#@base/view/\#@#{@oid}"
130
+ }
131
+
132
+ define_class_method :to_edit_href, %{
133
+ "#{@controller.ann.self.mount_point}/#@base/edit/\#@#{@oid}"
134
+ }
135
+ end
136
+
137
+ # Scaffold the controller.
138
+
139
+ def scaffold_controller
140
+ define_controller_action 'index', %{
141
+ #{Aspects.gen_advice_code(:scaffold_index, @controller.advices, :pre)}
142
+ @list, @pager = paginate(@klass, :per_page => Scaffolding.per_page)
143
+ }
144
+
145
+ define_controller_action 'list', %{
146
+ #{Aspects.gen_advice_code(:scaffold_list, @controller.advices, :pre)}
147
+ @list, @pager = paginate(@klass, :per_page => Scaffolding.per_page)
148
+ }
149
+
150
+ define_controller_action 'view(oid)', %{
151
+ #{Aspects.gen_advice_code(:scaffold_view, @controller.advices, :pre)}
152
+ @obj = @klass[oid]
153
+ }
154
+
155
+ define_controller_action 'new(all = false)', %{
156
+ #{Aspects.gen_advice_code(:scaffold_new, @controller.advices, :pre)}
157
+ @obj = @klass.new
158
+ @all = all
159
+ }
160
+
161
+ define_controller_action 'edit(oid = nil, all = false)', %{
162
+ #{Aspects.gen_advice_code(:scaffold_edit, @controller.advices, :pre)}
163
+ @obj = @klass[oid]
164
+ @all = all
165
+ }
166
+
167
+ # FIXME: investigate save, improve.
168
+
169
+ define_controller_action 'save', %{
170
+ if oid = request['#@oid']
171
+ oid = oid.to_s # fix StringIO (post).
172
+ obj = request.fill(@klass[oid], :assign_relations => true, :force_boolean => true, :preprocess => true)
173
+ else
174
+ obj = request.fill(@klass.create, :assign_relations => true, :preprocess => true)
175
+ end
176
+ #{Aspects.gen_advice_code(:scaffold_save, @controller.advices, :pre)}
177
+ unless obj.valid?
178
+ flash[:ERRORS] = obj.errors
179
+ redirect_to_referer
180
+ end
181
+ obj.save
182
+ #{Aspects.gen_advice_code(:scaffold_save, @controller.advices, :post)}
183
+ redirect '#{action_path(:list)}'
184
+ }
185
+
186
+ define_controller_action 'search(query)', %{
187
+ #{Aspects.gen_advice_code(:scaffold_search, @controller.advices, :pre)}
188
+ @query = query
189
+ if @klass.respond_to? :search
190
+ @list = #@klass.search(query)
191
+ end
192
+ }
193
+
194
+ define_controller_action 'delete(oid)', %{
195
+ #{Aspects.gen_advice_code(:scaffold_delete, @controller.advices, :pre)}
196
+ @klass.delete(oid)
197
+ #{Aspects.gen_advice_code(:scaffold_delete, @controller.advices, :post)}
198
+ redirect_to_referer
199
+ }
200
+
201
+ # Actions for the relations
202
+
203
+ for rel in @klass.relations
204
+ define_controller_action "remove_#{rel.target_singular_name}(oid, rid)", %{
205
+ obj = @klass[oid]
206
+ #{Aspects.gen_advice_code(:scaffold_remove_relation, @controller.advices, :pre)}
207
+ rob = #{rel.target_class}[rid]
208
+ obj.#{rel.name}.remove(rob)
209
+ #{Aspects.gen_advice_code(:scaffold_remove_relation, @controller.advices, :post)}
210
+ redirect_to_referer
211
+ }
212
+ define_controller_action "delete_#{rel.target_singular_name}(oid, rid)", %{
213
+ #{Aspects.gen_advice_code(:scaffold_delete_relation, @controller.advices, :pre)}
214
+ obj = @klass[oid]
215
+ rob = #{rel.target_class}[rid]
216
+ obj.#{rel.name}.delete(rob)
217
+ #{Aspects.gen_advice_code(:scaffold_delete_relation, @controller.advices, :post)}
218
+ redirect_to_referer
219
+ }
220
+ end
221
+ end
222
+
223
+ private
224
+
225
+ def action_method(sym)
226
+ action = "#{@base__}#{sym}"
227
+ action << @suffix unless @suffix.nil? or sym == :index
228
+ return action
229
+ end
230
+
231
+ def action_path(sym)
232
+ action = "#{@base}/#{sym}"
233
+ action << @suffix unless @suffix.nil? or sym == :index
234
+ return action
235
+ end
236
+ end
237
+
238
+ module ClassMethods
239
+
240
+ # This method modifies both the controller and the
241
+ # scaffolded Class.
242
+ #
243
+ # === Example
244
+ #
245
+ # scaffold Article
246
+ #
247
+ # ==== Actions/Methods added to the Controller
248
+ #
249
+ # * articles
250
+ # * edit_article
251
+ # * view_article
252
+ # * delete_article
253
+ # * search_artile
254
+ # * query_article
255
+ #
256
+ # ==== Methods added to the Class (ex: Article)
257
+ #
258
+ # * to_href
259
+ # * to_edit_href
260
+ #
261
+ #--
262
+ # This is the first phase of the scaffolding proccess,
263
+ # scaffold targets are marked, and default options set.
264
+ #++
265
+
266
+ def scaffold(klass, options = {})
267
+ o = {
268
+ :pk => 'oid',
269
+ :name => Scaffolding.class_to_name(klass),
270
+ :plural_name => Scaffolding.class_to_list(klass),
271
+ :mount => true
272
+ }
273
+ o.merge!(options)
274
+ if scaffolding_classes.has_key? klass
275
+ scaffolding_classes[klass].merge!(o)
276
+ else
277
+ scaffolding_classes[klass] = o
278
+ end
279
+ end
280
+
281
+ #--
282
+ # This is the second phase of the scaffolding process
283
+ #++
284
+
285
+ def compile_scaffolding_code
286
+ # load scaffolding for all og classes if specified
287
+
288
+ if scaffold_all?
289
+ options = scaffold_all_options
290
+ Og.manager.manageable_classes.each do |klass|
291
+ unless klass.ancestors.include?(Og::Unmanageable) or options[:except] && options[:except].include?(klass)
292
+ scaffold(klass, options)
293
+ end
294
+ end
295
+ scaffold_all false
296
+ end
297
+
298
+ # compile the scaffold methods
299
+
300
+ scaffolding_classes.each do |klass, options|
301
+ Scaffolding::ScaffoldCompiler.new(self, klass, options).scaffold
302
+ end
303
+ end
304
+
305
+ #--
306
+ # set the options flag to trigger scaffolding of all classes in second phase
307
+ # use exclude to ignore classes.... scaffold_all :exclude => [Product, Category]
308
+ #++
309
+
310
+ def scaffold_all(options = {})
311
+ if options
312
+ o = if options.kind_of? Hash then options else Hash.new end
313
+ else
314
+ o = nil
315
+ end
316
+ @scaffold_all_options = o
317
+ end
318
+
319
+ #--
320
+ # Keep track of scaffolded classes on this controller
321
+ #++
322
+
323
+ def scaffolding_classes
324
+ # TODO: maybe make this with a inhertitor?
325
+ # although inhertited scaffolding might be pointless
326
+ @scaffolding_classes ||= {}
327
+ end
328
+
329
+ #--
330
+ # Scaffold all classes flag
331
+ #++
332
+
333
+ def scaffold_all_options
334
+ @scaffold_all_options
335
+ end
336
+ alias_method :scaffold_all?, :scaffold_all_options
337
+
338
+ end
339
+
340
+ end
341
+
342
+ end
343
+
344
+ # * George Moschovitis <gm@navel.gr>
@@ -120,7 +120,11 @@ class Server
120
120
  server = Server.new
121
121
  server.start(options)
122
122
 
123
- runner.invoke(server) unless $NITRO_NO_INVOKE
123
+ unless $NITRO_NO_INVOKE
124
+ runner.invoke(server)
125
+ else
126
+ Logger.info 'Running in console mode.'
127
+ end
124
128
 
125
129
  return server
126
130
  end
@@ -1,6 +1,7 @@
1
1
  require 'optparse'
2
2
 
3
3
  require 'glue/configuration'
4
+ require 'nitro/compiler'
4
5
 
5
6
  module Nitro
6
7
 
@@ -151,6 +152,8 @@ class Runner
151
152
  irb_name = 'irb'
152
153
  end
153
154
  ENV['NITRO_INVOKE'] = 'irb'
155
+ $NITRO_NO_INVOKE = true
156
+ @server = :console
154
157
  conf_file = File.basename(caller.last.split(':').first)
155
158
  exec "#{irb_name} -r #{conf_file} -r irb/completion --noinspect"
156
159
  exit
@@ -284,31 +287,35 @@ class Runner
284
287
 
285
288
  @server ||= Runner.adapter
286
289
 
287
- puts "\n",
288
- "==> Listening at #{server.address}:#{server.port}. (#{self.class.mode} mode)",
289
- "==> Press Ctrl-C to shutdown; Run with --help for options.\n\n"
290
+ puts "\n==> Setup for #{self.class.mode} mode"
290
291
 
291
292
  case @server
292
293
  when :webrick
293
294
  require 'nitro/adapter/webrick'
295
+ puts "==> Listening at #{server.address}:#{server.port}."
296
+ puts "==> Press Ctrl-C to shutdown; Run with --help for options.\n\n"
294
297
  Webrick.start(server)
295
298
 
296
299
  when :lhttpd
297
300
  require 'nitro/adapter/fastcgi'
301
+ puts "==> Launching lighttpd (FastCGI)."
298
302
  `lighttpd -f conf/lhttpd_fcgi.conf`
299
303
 
300
304
  when :lhttpd_scgi
301
305
  require 'nitro/adapter/scgi'
306
+ puts "==> Launching lighttpd (SCGI)."
302
307
  `lighttpd -f conf/lhttpd_scgi.conf`
303
308
 
304
309
  when :apache
305
310
  require 'nitro/adapter/fastcgi'
311
+ puts "==> Launching apache (FastCGI)."
306
312
  `apachectl -d #{Dir.pwd} -f conf/apache.conf -k start`
307
313
 
308
314
  when :cgi
309
315
  require 'nitro/adapter/cgi'
316
+ puts "==> Using standard CGI. Please look into using Fast/Scgi"
310
317
  end
311
-
318
+
312
319
  when :stop
313
320
 
314
321
  case @server
@@ -342,24 +349,21 @@ class Runner
342
349
  # Attempt to load external configuration in Ruby or
343
350
  # YAML format. The files:
344
351
  #
345
- # * conf/mode.rb
352
+ # * conf/mode.rb
346
353
  # * conf/mode.yaml
347
354
  #
348
355
  # are considered.
349
356
 
350
357
  def load_external_configuration(mode = :debug)
351
- begin
352
- # gmosx: Workaround for an RDoc bug.
353
- # require "conf/#{mode}.rb"
354
- eval %|require 'conf/#{mode}.rb'|
355
- rescue Object
356
- end
358
+
359
+ # require "conf/#{mode}.rb"
360
+ ruby_conf = "conf/#{mode}.rb"
361
+ load ruby_conf if File.exist?(ruby_conf)
357
362
 
358
363
  # Try to configure from a yaml file.
359
- begin
360
- Configuration.load "conf/#{mode}.yml"
361
- rescue Object => ex
362
- end
364
+ yml_conf = "conf/#{mode}.yml"
365
+ Configuration.load yml_conf if File.exist?(yml_conf)
366
+
363
367
  end
364
368
 
365
369
  end