nitro 0.14.0 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. data/CHANGELOG +117 -0
  2. data/INSTALL +4 -0
  3. data/README +30 -31
  4. data/Rakefile +2 -2
  5. data/bin/nitro +10 -1
  6. data/bin/{new_app.rb → nitrogen} +12 -22
  7. data/doc/AUTHORS +4 -13
  8. data/doc/RELEASES +98 -0
  9. data/examples/ajax/run.rb +1 -3
  10. data/examples/blog/cache/entriesadmin +1 -1
  11. data/examples/blog/conf/locales/de.yml +4 -0
  12. data/examples/blog/conf/locales/en.yml +4 -0
  13. data/examples/blog/public/fcgi.rb +2 -3
  14. data/examples/blog/run.rb +10 -5
  15. data/examples/blog/src/controller.rb +21 -10
  16. data/examples/blog/src/mailer.rb +1 -1
  17. data/examples/blog/src/views/index.xhtml +2 -2
  18. data/examples/blog/src/xsl/style.xsl +6 -1
  19. data/examples/flash/run.rb +1 -3
  20. data/examples/no_xsl_blog/conf/locales/de.yml +4 -0
  21. data/examples/no_xsl_blog/conf/locales/en.yml +4 -0
  22. data/examples/no_xsl_blog/lib/blog/controller.rb +10 -0
  23. data/examples/no_xsl_blog/lib/blog/template.rb +4 -0
  24. data/examples/no_xsl_blog/public/fcgi.rb +2 -1
  25. data/examples/no_xsl_blog/public/index.xhtml +1 -1
  26. data/examples/no_xsl_blog/run.rb +8 -4
  27. data/examples/tiny/public/deep/dir/hello.xhtml +1 -0
  28. data/examples/tiny/public/fcgi.rb +2 -1
  29. data/examples/tiny/public/index.xhtml +5 -2
  30. data/examples/tiny/run.rb +1 -3
  31. data/examples/wee_style/run.rb +1 -3
  32. data/examples/why_wiki/run.rb +1 -3
  33. data/lib/nitro.rb +5 -2
  34. data/lib/nitro/builders/form.rb +8 -3
  35. data/lib/nitro/caching/stores.rb +3 -3
  36. data/lib/nitro/controller.rb +26 -6
  37. data/lib/nitro/dispatcher.rb +21 -13
  38. data/lib/nitro/environment.rb +23 -0
  39. data/lib/nitro/filters.rb +10 -8
  40. data/lib/nitro/localization.rb +127 -13
  41. data/lib/nitro/part.rb +24 -0
  42. data/lib/nitro/render.rb +19 -15
  43. data/lib/nitro/runner.rb +2 -1
  44. data/lib/nitro/scaffold.rb +69 -17
  45. data/lib/nitro/shaders.rb +54 -83
  46. data/lib/nitro/template.rb +7 -1
  47. data/proto/README +11 -0
  48. data/proto/conf/apache.conf +51 -0
  49. data/proto/conf/lhttpd.conf +107 -0
  50. data/proto/public/error.xhtml +56 -0
  51. data/proto/public/fcgi.rb +5 -0
  52. data/proto/public/index.xhtml +83 -0
  53. data/proto/public/js/ajax.js +63 -0
  54. data/proto/public/media/nitro.png +0 -0
  55. data/proto/run.rb +11 -0
  56. data/test/nitro/tc_controller.rb +1 -4
  57. data/test/nitro/tc_dispatcher.rb +8 -0
  58. data/test/nitro/tc_localization.rb +49 -0
  59. metadata +34 -6
  60. data/bin/new_form.rb +0 -54
@@ -86,11 +86,16 @@ class Controller
86
86
 
87
87
  cattr_accessor :action_metadata, {}
88
88
 
89
+ def initialize(context, base = nil)
90
+ super
91
+ self.class.template_root ||= "#{@context.dispatcher.template_root}#{base}"
92
+ end
93
+
89
94
  # Use the method_missing hook to compile the actions
90
95
  # for this controller.
91
96
 
92
97
  def method_missing(action, *args)
93
- if Rendering.compile_action(self.class, action, @template_root)
98
+ if Rendering.compile_action(self.class, action, self.class.template_root)
94
99
  send(action, *args)
95
100
  else
96
101
  super
@@ -101,11 +106,26 @@ class Controller
101
106
 
102
107
  alias __old_inherited inherited
103
108
 
104
- def inherited(subclass)
105
- subclass.class_eval %{
106
- DEF_FILE = caller[2].split(':')[-2]
107
- }
108
- __old_inherited(subclass)
109
+ #--
110
+ # gmosx, FIXME: the template_root hack is temporary.
111
+ # this should be moved to the render.
112
+ #++
113
+
114
+ def inherited(child)
115
+ child.class_eval %{
116
+ DEF_FILE = caller[2].to_s.strip.gsub( /:[0-9]+$/ , '')
117
+
118
+ @template_root = 'public'
119
+
120
+ def self.template_root
121
+ @template_root
122
+ end
123
+
124
+ def self.template_root=(root)
125
+ @template_root = root
126
+ end
127
+ }
128
+ __old_inherited(child)
109
129
  end
110
130
 
111
131
  # Define metadata for an action. This is a helper
@@ -133,36 +133,44 @@ class Dispatcher
133
133
  end
134
134
 
135
135
  parts = path.split('/')
136
+ parts.shift
136
137
 
137
138
  case parts.size
138
139
  when 0
139
140
  # / -> root.index
140
- # base = @template_root
141
+ base = '/'
141
142
  klass = controller_class_for(:root, context)
142
143
  action = 'index'
143
144
 
144
- when 2
145
- if klass = controller_class_for(parts[1], context)
145
+ when 1
146
+ if klass = controller_class_for(parts[0], context)
146
147
  # controller/ -> controller.index
147
- # base = "#{@template_root}/#{parts[1]}"
148
+ base = "/#{parts[0]}"
148
149
  action = 'index'
149
150
  else
150
151
  # action/ -> root.action
151
- # base = @template_root
152
+ base = '/'
152
153
  klass = controller_class_for(:root, context)
153
- action = parts[1]
154
+ action = parts[0]
154
155
  end
155
156
 
156
- when 3
157
- # controller/action/ -> controller.action
158
- # base = "#{@template_root}/#{parts[1]}"
159
- klass = controller_class_for(parts[1], context)
160
- action = parts[2]
157
+ else
158
+ if klass = controller_class_for(parts[0], context)
159
+ # controller/action -> controller.action
160
+ base = "/#{parts[0]}"
161
+ parts.shift
162
+ action = parts.join('__')
163
+ else
164
+ # action/ -> root.action
165
+ base = '/'
166
+ klass = controller_class_for(:root, context)
167
+ action = parts.join('__')
168
+ end
161
169
  end
162
-
170
+
163
171
  content_type = @apis[:api] || 'text/html'
164
172
 
165
- return klass, "__#{api}__#{action}", content_type
173
+ return klass, "__#{api}__#{action}", content_type, base
166
174
  end
167
175
  alias_method :split_path, :dispatch
168
176
 
@@ -0,0 +1,23 @@
1
+ # * George Moschovitis <gm@navel.gr>
2
+ # (c) 2004-2005 Navel, all rights reserved.
3
+ # $Id: environment.rb 340 2005-04-04 08:26:58Z gmosx $
4
+
5
+ # Setup up the proposed environment. You are free
6
+ # to skip this if you dont like it. Just set
7
+ #
8
+ # $NITRO_NO_ENVIRONMENT = true
9
+ #
10
+ # before requiring nitro.
11
+ #--
12
+ # gmosx: this is temporary code.
13
+ #++
14
+
15
+ Dir.chdir(File.dirname($0))
16
+
17
+ # Application code come here.
18
+
19
+ $LOAD_PATH.unshift 'src'
20
+
21
+ # Library code come here.
22
+
23
+ $LOAD_PATH.unshift 'lib'
data/lib/nitro/filters.rb CHANGED
@@ -1,13 +1,14 @@
1
1
  # * George Moschovitis <gm@navel.gr>
2
2
  # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id: filters.rb 326 2005-03-28 11:07:17Z gmosx $
3
+ # $Id: filters.rb 335 2005-03-31 14:02:02Z gmosx $
4
4
 
5
5
  module N
6
6
 
7
7
  # Filtering functionality for renders.
8
- # The design and implementation is HEAVILY influenced by Rails.
8
+ # The design and implementation is HEAVILY influenced
9
+ # by Rails.
9
10
  #
10
- # == Examples
11
+ # === Examples
11
12
  #
12
13
  # Filter as class:
13
14
  #
@@ -18,8 +19,9 @@ module N
18
19
  # before
19
20
  # filter
20
21
  # after
22
+ #
21
23
  #--
22
- # TODO: implement inheritable filters.
24
+ # TODO: rethink what happens with module filters.
23
25
  #++
24
26
 
25
27
  module Filtering
@@ -127,9 +129,9 @@ module Filtering
127
129
 
128
130
  alias :after_filter :append_after_filter
129
131
 
130
- # Install an arround Filter. A filter is a class that responds
131
- # to the before and after methods. Both methods are prepended to
132
- # the respective lists.
132
+ # Install an arround Filter. A filter is a class that
133
+ # responds to the before and after methods. Both methods
134
+ # are prepended to the respective lists.
133
135
 
134
136
  def prepend_arround_filter(*args)
135
137
  options = args.pop if args.last.is_a?(Hash)
@@ -200,7 +202,7 @@ module Filtering
200
202
  elsif filter.respond_to?('filter')
201
203
  code << "if #{filter}.filter(self) == false then return false end"
202
204
  else
203
- raise 'Valid filters are either a symbol, a string or a proc/method.'
205
+ raise 'Valid filters are either a Symbol, a String or a Proc/Method.'
204
206
  end
205
207
  end
206
208
 
@@ -2,41 +2,155 @@
2
2
  # (c) 2004-2005 Navel, all rights reserved.
3
3
  # $Id: l10n.rb 185 2004-12-10 13:29:09Z gmosx $
4
4
 
5
+ require 'yaml'
6
+
5
7
  require 'nitro/filters'
8
+ require 'nitro/shaders'
6
9
 
7
10
  module N
8
11
 
9
- # Localization support.
12
+ # Represents a locale.
10
13
  #--
11
- # TODO: use inflector to convert symbols to strings.
14
+ # TODO: initialize translation map from a yaml file.
12
15
  #++
13
16
 
14
- class Localization
17
+ class Locale
15
18
 
16
- # This map gives the correct localization hash
17
- # for the given locale.
19
+ # The localization map.
18
20
 
19
21
  attr_accessor :map
22
+
23
+ def initialize(map)
24
+ parse_hash(map)
25
+ end
26
+
27
+ # Transalte the given key.
28
+ #
29
+ # [+args+]
30
+ # An array of arguments. The first argument
31
+ # is the translation key. If additional arguments
32
+ # are provided they are used for sprintf
33
+ # interpolation.
34
+ #--
35
+ # THINK: Possibly avoid the creation of the
36
+ # array by making the api less elegant.
37
+ #++
38
+
39
+ def translate(*args)
40
+ if xlated = @map[args.shift]
41
+ if xlated.is_a?(String)
42
+ args.empty? ? xlated : sprintf(xlated, *args)
43
+ else
44
+ xlated.call(*args)
45
+ end
46
+ end
47
+ end
48
+ alias_method :[], :translate
20
49
 
21
- def initialize(map = {})
50
+ private
51
+
52
+ def parse_hash(map)
22
53
  @map = map
23
54
  end
24
55
 
25
- # Return the localization hash for the given
26
- # locale.
56
+ def parse_yaml(yaml)
57
+ raise 'Not implemented'
58
+ end
59
+
60
+ end
61
+
62
+ # Localization support.
63
+ #
64
+ # === Example
65
+ #
66
+ # locale_en = {
67
+ # 'See you' => 'See you',
68
+ # :long_paragraph => 'The best new books, up to 30% reduced price',
69
+ # :price => 'Price: %d %s',
70
+ # :proc_price => proc { |value, cur| "Price: #{value} #{cur}" }
71
+ # }
72
+ #
73
+ # locale_de = {
74
+ # 'See you' => 'Auf wieder sehen',
75
+ # :long_paragraph => 'Die besten neuer buecher, bis zu 30% reduziert',
76
+ # ...
77
+ # }
78
+ #
79
+ # Localization.add(:en => locale_en, :de => locale_de)
80
+ #
81
+ # lc = Localization.get
82
+ # lc['See you'] -> See you
83
+ # lc[:price, 100, 'euro'] -> Price: 100 euro
84
+ # lc = Localization.get[:de]
85
+ # lc['See you'] -> Auf wiedersehen
86
+ #
87
+ # To make localization even more easier, a LocalizationFilter
88
+ # and a LocalizationShader are provided.
89
+
90
+ class Localization
91
+
92
+ class << self
93
+
94
+ # A hash of the available locales.
95
+
96
+ attr_accessor :locales
97
+
98
+ def add(map = {})
99
+ for key, locale in map
100
+ if locale.is_a?(String)
101
+ # this is the name of the localization file.
102
+ locale = YAML.load(File.read(locale))
103
+ end
104
+ @locales[key.to_s] = Locale.new(locale)
105
+ end
106
+ end
107
+
108
+ # Return the localization hash for the given
109
+ # locale.
110
+
111
+ def get(locale = :en)
112
+ locale ||= 'en'
113
+ @locales[locale.to_s]
114
+ end
115
+ alias_method :locale, :get
116
+ alias_method :[], :get
27
117
 
28
- def get(locale = 'en')
29
- locale || = 'en'
30
- @map[locale]
31
118
  end
119
+
120
+ @locales = {}
121
+
32
122
  end
33
123
 
34
- # Localization filter
124
+ # Localization filter.
35
125
 
36
126
  module LocalizationFilter
37
127
  def localize
38
- @lc = @context.conf.lc.get(@session[:LC])
128
+ # @lc = @context.conf.localization[@session[:LOCALE]]
129
+ @lc = Localization[@context.session[:LOCALE]]
39
130
  end
40
131
  end
132
+
133
+ # Localization shader.
134
+ #
135
+ # === Examples
136
+ #
137
+ # <h1>[[Welcome]]</h1>
138
+ # <h1>[[:welcome]]</h1>
139
+
140
+ class LocalizationShader < Shader
41
141
 
142
+ def process(hash, text)
143
+ # handle symbols
144
+ text.gsub!(/\[\[\:(.*?)\]\]/, '#{@lc[\1]}')
145
+
146
+ # handle strings
147
+ text.gsub!(/\[\[(.*?)\]\]/, '#{@lc["\1"]}')
148
+
149
+ process_next(hash, text)
150
+ end
151
+
42
152
  end
153
+
154
+ end
155
+
156
+
data/lib/nitro/part.rb ADDED
@@ -0,0 +1,24 @@
1
+ # * George Moschovitis <gm@navel.gr>
2
+ # (c) 2004-2005 Navel, all rights reserved.
3
+ # $Id: part.rb 339 2005-04-01 14:02:14Z gmosx $
4
+
5
+ # UNDER CONSTRUCTION, dont use yet!
6
+
7
+ require 'glue/attribute'
8
+
9
+ module N
10
+
11
+ class Part
12
+ cattr_accessor :parts_root, "/home/gmosx/navel/gen/parts"
13
+ end
14
+
15
+ end
16
+
17
+ module Kernel
18
+
19
+ def require_part(name)
20
+ require "#{N::Part.parts_root}/#{name}/part"
21
+ end
22
+
23
+ end
24
+
data/lib/nitro/render.rb CHANGED
@@ -56,17 +56,17 @@ module Rendering
56
56
  # attempt to find a template of the form
57
57
  # template_root/action.xhtml
58
58
 
59
- path = "#{template_root}/#{action}.#{ext}".squeeze('/')
60
-
59
+ path = "#{template_root}/#{action.gsub(/__/, '/')}.#{ext}".squeeze('/')
60
+
61
61
  unless File.exist?(path)
62
62
 
63
63
  # attempt to find a template of the form
64
64
  # template_root/action/index.xhtml
65
65
 
66
- path = "#{template_root}/#{action}/#{Rendering.default_template}.#{ext}".squeeze('/')
67
-
66
+ path = "#{template_root}/#{action.gsub(/__/, '/')}/#{Rendering.default_template}.#{ext}".squeeze('/')
67
+
68
68
  unless File.exist?(path)
69
- # No template founD!
69
+ # No template found!
70
70
  path = nil
71
71
  end
72
72
  end
@@ -89,7 +89,12 @@ module Rendering
89
89
 
90
90
  def self.compile_action(klass, action, template_root)
91
91
  @@sync.synchronize do
92
- dummy, api, action = action.to_s.split('__')
92
+ action = action.to_s.split('__')
93
+ action.shift
94
+ api = action.shift
95
+ action = action.join('__')
96
+
97
+ # dummy, api, action = action.to_s.split('__')
93
98
 
94
99
  # This is not a controller action.
95
100
 
@@ -173,7 +178,7 @@ module Rendering
173
178
  }
174
179
  end
175
180
 
176
- # puts '---', code, '---' if action.to_s == 'index'
181
+ # puts '---', code, '---'
177
182
 
178
183
  klass.class_eval(code)
179
184
  end
@@ -184,6 +189,10 @@ module Rendering
184
189
  end
185
190
 
186
191
  # The rendering mixin.
192
+ #--
193
+ # TODO: handle template_root here instead of the
194
+ # controller.
195
+ #++
187
196
 
188
197
  module Render
189
198
 
@@ -210,20 +219,15 @@ module Render
210
219
  # The name of the currently executing action.
211
220
 
212
221
  attr_accessor :action_name
213
-
214
- # The template root for this render.
215
-
216
- cattr_accessor :template_root
217
222
 
218
223
  # Initialize the render.
219
224
  #
220
225
  # [+context+]
221
226
  # A parent render/controller acts as the context.
222
227
 
223
- def initialize(context)
228
+ def initialize(context, base = nil)
224
229
  @request = @context = context
225
230
  @out = context.out
226
- @template_root = @context.dispatcher.template_root
227
231
  end
228
232
 
229
233
  # Renders the action denoted by path. The path
@@ -233,7 +237,7 @@ module Render
233
237
  def render(path)
234
238
  Logger.debug "Rendering '#{path}'." if $DBG
235
239
 
236
- klass, action, content_type = @context.dispatcher.dispatch(path, @context)
240
+ klass, action, content_type, base = @context.dispatcher.dispatch(path, @context)
237
241
 
238
242
  @context.content_type = content_type
239
243
 
@@ -242,7 +246,7 @@ module Render
242
246
  if self.class == klass
243
247
  self.send(action)
244
248
  else
245
- klass.new(self).send(action)
249
+ klass.new(self, base).send(action)
246
250
  end
247
251
 
248
252
  rescue RenderExit => e