nitro 0.19.0 → 0.20.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 (58) hide show
  1. data/CHANGELOG +187 -0
  2. data/INSTALL +5 -0
  3. data/README +11 -5
  4. data/doc/AUTHORS +11 -1
  5. data/doc/RELEASES +217 -0
  6. data/doc/tutorial.txt +1 -2
  7. data/lib/nitro.rb +9 -6
  8. data/lib/nitro/adapter/webrick.rb +13 -2
  9. data/lib/nitro/builder/form.rb +11 -9
  10. data/lib/nitro/builder/rss.rb +2 -2
  11. data/lib/nitro/builder/xhtml.rb +15 -0
  12. data/lib/nitro/caching.rb +15 -10
  13. data/lib/nitro/conf.rb +0 -5
  14. data/lib/nitro/controller.rb +118 -81
  15. data/lib/nitro/cookie.rb +6 -6
  16. data/lib/nitro/dispatcher.rb +62 -18
  17. data/lib/nitro/element.rb +4 -1
  18. data/lib/nitro/element/java_script.rb +15 -0
  19. data/lib/nitro/localization.rb +3 -4
  20. data/lib/nitro/markup.rb +4 -4
  21. data/lib/nitro/mixin/debug.rb +30 -0
  22. data/lib/nitro/mixin/helper.rb +14 -0
  23. data/lib/nitro/mixin/javascript.rb +137 -0
  24. data/lib/nitro/{ui → mixin}/pager.rb +110 -82
  25. data/lib/nitro/render.rb +20 -8
  26. data/lib/nitro/request.rb +6 -0
  27. data/lib/nitro/routing.rb +6 -5
  28. data/lib/nitro/runner.rb +21 -9
  29. data/lib/nitro/server.rb +95 -0
  30. data/lib/nitro/service.rb +0 -1
  31. data/lib/nitro/session.rb +4 -5
  32. data/lib/nitro/shaders.rb +2 -2
  33. data/lib/nitro/template.rb +1 -1
  34. data/lib/nitro/testing/assertions.rb +2 -4
  35. data/lib/nitro/testing/context.rb +4 -6
  36. data/proto/public/js/behaviour.js +254 -0
  37. data/proto/public/js/controls.js +446 -0
  38. data/proto/public/js/dragdrop.js +537 -0
  39. data/proto/public/js/effects.js +612 -0
  40. data/proto/public/js/prototype.js +644 -370
  41. data/proto/public/settings.xhtml +64 -0
  42. data/test/nitro/adapter/tc_cgi.rb +2 -2
  43. data/test/nitro/builder/tc_rss.rb +1 -1
  44. data/test/nitro/mixin/tc_pager.rb +35 -0
  45. data/test/nitro/tc_controller.rb +1 -1
  46. data/test/nitro/tc_cookie.rb +14 -0
  47. data/test/nitro/tc_dispatcher.rb +11 -6
  48. data/test/nitro/tc_server.rb +35 -0
  49. metadata +20 -15
  50. data/lib/nitro/builder/atom.rb +0 -74
  51. data/lib/nitro/part.rb +0 -22
  52. data/lib/nitro/simple.rb +0 -11
  53. data/lib/nitro/ui/popup.rb +0 -41
  54. data/lib/nitro/ui/tabs.rb +0 -25
  55. data/lib/nitro/uri.rb +0 -193
  56. data/test/nitro/builder/tc_atom.rb +0 -24
  57. data/test/nitro/tc_uri.rb +0 -97
  58. data/test/nitro/ui/tc_pager.rb +0 -49
@@ -1,78 +1,58 @@
1
- # * George Moschovitis <gm@navel.gr>
2
- # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id: pager.rb 1 2005-04-11 11:04:30Z gmosx $
1
+ require 'glue/uri'
2
+ require 'glue/configuration'
4
3
 
5
- require 'nitro/uri'
6
-
7
- module Nitro; module UI
4
+ module Nitro
8
5
 
9
6
  # Displays a collection of entitities in multiple pages.
10
7
  #
11
8
  # === Design
12
9
  #
13
- # The new version is carefully designed for scaleability. It stores
10
+ # This pager is carefully designed for scaleability. It stores
14
11
  # only the items for one page. The name parameter is needed, multiple
15
12
  # pagers can coexist in a single page. Unlike older pagers this
16
- # pager leverages the SQL LIMIT option to optimize database interaction.
17
- #
18
- # === Example
19
- #
20
- # @pager = UI::Pager.new('entries', @request, 5)
21
- # @entries = BlogEntry.all("ORDER BY oid #{@pager.sql_limit}")
22
- # @pager.set(BlogEntry.count)
23
- #
24
- # default navigation (customize with css):
25
- # <div class="pager">#{@pager.navigation}</div>
26
- #
27
- # custom navigation:
28
- #
29
- # <table cellspacing="0" width="100%" border="1">
30
- # <tr>
31
- # <td width="64"><x:pager-prev>Previous</x:pager-prev></td>
32
- # <td width="100%"></td>
33
- # <td width="64"><x:pager-next>Next</x:pager-next></td>
34
- # </tr>
35
- # </table>
36
- #--
37
- # INVESTIGATE:
38
- # mysql> SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name
39
- # -> WHERE id > 100 LIMIT 10;
40
- # mysql> SELECT FOUND_ROWS();
41
- #++
42
-
43
- class Pager < Array
44
-
45
- attr_accessor :name, :idx, :page, :page_count
46
-
47
- # Total count of items
48
- attr_accessor :total_count
13
+ # pager leverages the SQL LIMIT option to optimize database
14
+ # interaction.
15
+
16
+ class Pager
17
+ # Items per page.
49
18
 
50
- # Page items
51
- attr_accessor :page_items
19
+ setting :per_page, :default => 10, :doc => 'Items per page'
52
20
 
53
- # Read needed variables from the request.
54
- attr_accessor :request
21
+ # The request key.
55
22
 
56
- def initialize(name, request, items_per_page = 10, items = nil)
57
- raise "items_per_page should be > 0" unless items_per_page > 0
23
+ setting :key, :default => '_page', :doc => 'The request key'
24
+
25
+ # The current page.
26
+
27
+ attr_accessor :page
28
+
29
+ # Items per page.
30
+
31
+ attr_accessor :per_page
58
32
 
59
- @request, @name = request, name
60
- @page = request.query.fetch("__pg#{@name}", 1).to_i
61
- @items_per_page = items_per_page
62
- @start_idx = (@page - 1) * items_per_page
33
+ # The total number of pages.
34
+
35
+ attr_accessor :page_count
36
+
37
+ # Total count of items.
38
+
39
+ attr_accessor :total_count
63
40
 
64
- if items
65
- set(items.size())
66
- # gmosx, FIXME: not exactly what i want!
67
- items.slice!(@start_idx, @items_per_page)
68
- end
69
- end
41
+ def initialize(request, per_page, total_count, key = Pager.key)
42
+ raise 'per_page should be > 0' unless per_page > 0
70
43
 
71
- def set(total_count)
44
+ @request, @key = request, key
45
+ @page = request.query.fetch(key, 1).to_i
46
+ @per_page = per_page
47
+ set_count(total_count)
48
+ @start_idx = (@page - 1) * per_page
49
+ end
50
+
51
+ def set_count(total_count)
72
52
  @total_count = total_count
73
- @page_count = (@total_count.to_f() / @items_per_page).ceil()
53
+ @page_count = (@total_count.to_f / @per_page).ceil
74
54
  end
75
-
55
+
76
56
  def first_page
77
57
  return 1
78
58
  end
@@ -135,10 +115,33 @@ class Pager < Array
135
115
 
136
116
  return (s..e)
137
117
  end
118
+
119
+ # To be used with Og queries.
120
+
121
+ def limit
122
+ { :limit => @per_page, :offset => @start_idx }
123
+ end
124
+
125
+ def offset
126
+ @start_idx
127
+ end
128
+
129
+ # Create an appropriate SQL limit clause.
130
+ # Returns postgres/mysql compatible limit.
138
131
 
139
- # Override this method in your application
140
- # if needed.
132
+ def to_sql
133
+ if @start_idx > 0
134
+ return "LIMIT #{@per_page} OFFSET #{@start_idx}"
135
+ else
136
+ # gmosx: perhaps this is optimized ? naaaaaah...
137
+ return "LIMIT #{@per_page}"
138
+ end
139
+ end
140
+
141
+ # Override this method in your application if needed.
142
+ #--
141
143
  # TODO: better markup.
144
+ #++
142
145
 
143
146
  def navigation
144
147
  nav = ""
@@ -175,32 +178,57 @@ class Pager < Array
175
178
 
176
179
  return nav
177
180
  end
181
+ alias_method :links, :navigation
182
+
183
+ private
178
184
 
179
- # Create an appropriate SQL limit clause.
180
- # Returns postgres/mysql compatible limit.
181
-
182
- def sql_limit
183
- if @start_idx > 0
184
- return "LIMIT #{@items_per_page} OFFSET #{@start_idx}"
185
- else
186
- # gmosx: perhaps this is optimized ? naaaaaah...
187
- return "LIMIT #{@items_per_page}"
188
- end
189
- end
190
-
191
- # Returns the current offset. The offset is zero-based.
192
-
193
- def offset
194
- (@page-1) * @items_per_page
195
- end
196
-
197
185
  # Generate the target URI.
198
- #
186
+
199
187
  def target_uri(page)
200
- params = {"__pg#{@name}" => page}
188
+ params = { @key => page }
201
189
  return UriUtils.update_query_string(@request.uri.to_s, params)
202
190
  end
203
191
 
204
192
  end
205
193
 
206
- end; end
194
+ # Pager related helper methods.
195
+
196
+ module PagerMixin
197
+
198
+ private
199
+
200
+ # Helper method that generates a collection of items and the
201
+ # asorted pager object.
202
+ #
203
+ # === Example
204
+ #
205
+ # entries, pager = paginate(Article, :condition => 'title LIKE %Ab%', :per_page => 10)
206
+ #
207
+ # <ul>
208
+ # <?r for entry in entries ?>
209
+ # <li>#{entry.to_link}</li>
210
+ # <?r end ?>
211
+ # </ul>
212
+ # #{pager.links}
213
+
214
+ def paginate(klass_or_array, options = {})
215
+ per_page = options.delete(:per_page) || Pager.per_page
216
+
217
+ if klass_or_array.is_a? Array
218
+ items = klass_or_array.dup
219
+ pager = Pager.new(request, per_page, items.size, key = Pager.key)
220
+ items = items.slice(pager.offset, pager.per_page)
221
+ return items, pager
222
+ else
223
+ pager = Pager.new(request, per_page, klass_or_array.count(options), key = Pager.key)
224
+ options.update(pager.limit)
225
+ items = klass_or_array.all(options)
226
+ return items, pager
227
+ end
228
+ end
229
+
230
+ end
231
+
232
+ end
233
+
234
+ # * George Moschovitis <gm@navel.gr>
data/lib/nitro/render.rb CHANGED
@@ -1,8 +1,11 @@
1
1
  require 'sync'
2
2
 
3
+ require 'facet/string/blank%3F'
4
+
3
5
  require 'glue/attribute'
4
6
  require 'glue/misc'
5
7
  require 'glue/object'
8
+ require 'glue/settings'
6
9
 
7
10
  require 'nitro/shaders'
8
11
  require 'nitro/buffering'
@@ -27,12 +30,12 @@ module Rendering
27
30
  @@sync = Sync.new
28
31
 
29
32
  # The default template root
30
-
31
- mattr_accessor :default_template_root, 'public'
32
-
33
+
34
+ setting :default_template_root, :default => 'public', :doc => 'The default template root'
35
+
33
36
  # The default template name (no extension).
34
37
 
35
- mattr_accessor :default_template, 'index'
38
+ setting :default_template, :default => 'index', :doc => 'The default template name (no extension).'
36
39
 
37
40
  # The shader used for transforming templates.
38
41
  # The default shader is very simple, here is a
@@ -48,11 +51,12 @@ module Rendering
48
51
  # </tt>
49
52
 
50
53
  mattr_accessor :shader; @@shader = RubyShader.new
54
+ # setting :shader, :default => RubyShader.new, :doc => 'The shader used for transforming templates'
51
55
 
52
56
  # If set to :full, reloads all controllers. Useful in
53
57
  # development.
54
58
 
55
- mattr_accessor :reload, false
59
+ setting :reload, :default => false, :doc => 'If set to :full reloads everything, useful in development'
56
60
 
57
61
  # Given the action try find the matching template.
58
62
  # Can search for xhtml or xml templates.
@@ -133,15 +137,17 @@ module Rendering
133
137
 
134
138
  param_count = klass.instance_method(action.intern).arity
135
139
 
140
+ # gmosx, FIXME: REIMPLEMENT THIS!!!!
141
+
136
142
  if param_count > 0
137
143
  code << %{
144
+ params = []
138
145
  qs = context.query_string.split(/[&;]/)
139
146
 
140
- params = []
141
147
  #{param_count}.times do |i|
142
148
  params << qs.shift.split(/=/).last
143
149
  end
144
-
150
+
145
151
  unless :stop == #{action}(*params)
146
152
  }
147
153
  else
@@ -272,7 +278,11 @@ module Render
272
278
  # The name of the currently executing action.
273
279
 
274
280
  attr_accessor :action_name
275
-
281
+
282
+ # The name of the current controller.
283
+
284
+ attr_accessor :controller_name
285
+
276
286
  # Initialize the render.
277
287
  #
278
288
  # [+context+]
@@ -280,6 +290,7 @@ module Render
280
290
 
281
291
  def initialize(context, base = nil)
282
292
  @request = @response = @context = context
293
+ @controller_name = base
283
294
  @out = context.out
284
295
  end
285
296
 
@@ -324,6 +335,7 @@ private
324
335
  def redirect(url, status = 303)
325
336
  url = url.to_s
326
337
  url = "#{@context.host_url}/#{url.gsub(/^\//, '')}" unless url =~ /http/
338
+
327
339
  @context.status = status
328
340
  @context.out = "<html><a href=\"#{url}\">#{url}</a>.</html>\n"
329
341
  @context.response_headers['location'] = url
data/lib/nitro/request.rb CHANGED
@@ -152,6 +152,12 @@ module Request
152
152
  def []=(param, value)
153
153
  @params[param] = value
154
154
  end
155
+
156
+ # Fetch a parameter with default value.
157
+
158
+ def fetch(param, default = nil)
159
+ @params.fetch(param, default)
160
+ end
155
161
  end
156
162
 
157
163
  end
data/lib/nitro/routing.rb CHANGED
@@ -1,10 +1,8 @@
1
- # * George Moschovitis <gm@navel.gr>
2
- # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id: routing.rb 1 2005-04-11 11:04:30Z gmosx $
4
-
5
1
  module Nitro
6
2
 
7
- # Router mixin.
3
+ # Router mixin. Typically used to generate 'nice' urls.
4
+ # Nice urls are considered (?) more Search Engine
5
+ # friendly.
8
6
 
9
7
  module Router
10
8
 
@@ -31,3 +29,6 @@ module Router
31
29
  end
32
30
 
33
31
  end
32
+
33
+ # * George Moschovitis <gm@navel.gr>
34
+
data/lib/nitro/runner.rb CHANGED
@@ -3,6 +3,8 @@
3
3
  require 'optparse'
4
4
 
5
5
  require 'glue/misc'
6
+ require 'glue/configuration'
7
+
6
8
  require 'nitro/conf'
7
9
 
8
10
  module Nitro
@@ -135,7 +137,8 @@ class Runner
135
137
  end
136
138
  ENV['NITRO_INVOKE'] = 'irb'
137
139
  conf_file = File.basename(caller.last.split(':').first)
138
- exec "#{irb_name} -r #{conf_file} -r irb/completion --noinspect"
140
+ # exec "#{irb_name} -r #{conf_file} -r irb/completion --noinspect"
141
+ exec "#{irb_name} -r #{conf_file} --noinspect"
139
142
  exit
140
143
  end
141
144
 
@@ -170,20 +173,19 @@ class Runner
170
173
  # using the passed configuration parameters.
171
174
 
172
175
  def run(conf)
173
-
174
176
  if conf.is_a?(Hash)
175
177
  conf = Conf.new(conf)
176
178
  end
177
179
 
178
180
  case @mode
179
- when :debug
180
- setup_debug(conf)
181
+ when :debug
182
+ setup_debug(conf)
181
183
 
182
- when :stage
183
- setup_stage(conf)
184
-
185
- when :live
186
- setup_live(conf)
184
+ when :stage
185
+ setup_stage(conf)
186
+
187
+ when :live
188
+ setup_live(conf)
187
189
  end
188
190
 
189
191
  if 'fcgi_proc' == ENV['NITRO_INVOKE']
@@ -330,6 +332,16 @@ def self.run(conf = nil)
330
332
  runner.run(conf)
331
333
  end
332
334
 
335
+ #--
336
+ # Experimental.
337
+ #++
338
+
339
+ def self.start(controller)
340
+ # require 'glue/autoreload'
341
+ # autoreload(3)
342
+ Server.run(controller)
343
+ end
344
+
333
345
  end
334
346
 
335
347
  # * George Moschovitis <gm@navel.gr>
@@ -0,0 +1,95 @@
1
+ require 'glue/autoreload'
2
+ require 'nitro/adapter/webrick'
3
+
4
+ module Nitro
5
+
6
+ class Server
7
+
8
+ # :nodoc: all
9
+ # A Helper class used for CherryPy-style publishing.
10
+
11
+ class Mounter
12
+ def initialize(parent, base = '')
13
+ @parent, @base = parent, base
14
+ end
15
+
16
+ def method_missing(sym, *args)
17
+ sym = sym.to_s
18
+ if sym =~ /=$/
19
+ @parent.map["#@base/#{sym.gsub(/=/, '')}"] = args.first
20
+ else
21
+ Mounter.new(@parent, "#@base/#{sym}")
22
+ end
23
+ end
24
+ end
25
+
26
+ # The server listening address.
27
+ #--
28
+ # 0.0.0.0 may be a better default?
29
+ #++
30
+
31
+ setting :address, :default => '127.0.0.1', :doc => 'The server listening address'
32
+
33
+ # The server listening port.
34
+
35
+ setting :port, :default => 9999, :doc => 'The server listening port'
36
+
37
+ # The map.
38
+
39
+ setting :map, :default => { '/' => SimpleController }, :doc => 'The server map'
40
+
41
+ # The name of the application.
42
+
43
+ attr_accessor :name
44
+
45
+ # The sitemap. Defines how controller objects are published.
46
+
47
+ attr_accessor :map
48
+
49
+ def initialize(name = 'Nitro')
50
+ @name = name
51
+ @map = self.class.map.dup
52
+ end
53
+
54
+ # Start the server.
55
+
56
+ def start(controller = nil)
57
+ self.map['/'] = controller if controller
58
+
59
+ $DBG = true
60
+ autoreload(3)
61
+ Rendering.reload = :full
62
+
63
+ dispatcher = Dispatcher.new
64
+ dispatcher.publish(self.map)
65
+ conf = {
66
+ :dispatcher => dispatcher
67
+ }
68
+
69
+ Webrick.start(Conf.new(conf))
70
+ end
71
+
72
+ def root=(controller)
73
+ @map['/'] = controller
74
+ end
75
+
76
+ def root
77
+ Mounter.new(self)
78
+ end
79
+
80
+ # Helper method.
81
+
82
+ def self.run(controller = nil)
83
+ server = Server.new
84
+ server.start(controller)
85
+ end
86
+
87
+ end
88
+
89
+ end
90
+
91
+ # Alias for the Server class.
92
+
93
+ App = Nitro::Server unless Object.const_defined?(:App)
94
+
95
+ # * George Moschovitis <gm@navel.gr>