nitro 0.14.0 → 0.15.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.
- data/CHANGELOG +117 -0
- data/INSTALL +4 -0
- data/README +30 -31
- data/Rakefile +2 -2
- data/bin/nitro +10 -1
- data/bin/{new_app.rb → nitrogen} +12 -22
- data/doc/AUTHORS +4 -13
- data/doc/RELEASES +98 -0
- data/examples/ajax/run.rb +1 -3
- data/examples/blog/cache/entriesadmin +1 -1
- data/examples/blog/conf/locales/de.yml +4 -0
- data/examples/blog/conf/locales/en.yml +4 -0
- data/examples/blog/public/fcgi.rb +2 -3
- data/examples/blog/run.rb +10 -5
- data/examples/blog/src/controller.rb +21 -10
- data/examples/blog/src/mailer.rb +1 -1
- data/examples/blog/src/views/index.xhtml +2 -2
- data/examples/blog/src/xsl/style.xsl +6 -1
- data/examples/flash/run.rb +1 -3
- data/examples/no_xsl_blog/conf/locales/de.yml +4 -0
- data/examples/no_xsl_blog/conf/locales/en.yml +4 -0
- data/examples/no_xsl_blog/lib/blog/controller.rb +10 -0
- data/examples/no_xsl_blog/lib/blog/template.rb +4 -0
- data/examples/no_xsl_blog/public/fcgi.rb +2 -1
- data/examples/no_xsl_blog/public/index.xhtml +1 -1
- data/examples/no_xsl_blog/run.rb +8 -4
- data/examples/tiny/public/deep/dir/hello.xhtml +1 -0
- data/examples/tiny/public/fcgi.rb +2 -1
- data/examples/tiny/public/index.xhtml +5 -2
- data/examples/tiny/run.rb +1 -3
- data/examples/wee_style/run.rb +1 -3
- data/examples/why_wiki/run.rb +1 -3
- data/lib/nitro.rb +5 -2
- data/lib/nitro/builders/form.rb +8 -3
- data/lib/nitro/caching/stores.rb +3 -3
- data/lib/nitro/controller.rb +26 -6
- data/lib/nitro/dispatcher.rb +21 -13
- data/lib/nitro/environment.rb +23 -0
- data/lib/nitro/filters.rb +10 -8
- data/lib/nitro/localization.rb +127 -13
- data/lib/nitro/part.rb +24 -0
- data/lib/nitro/render.rb +19 -15
- data/lib/nitro/runner.rb +2 -1
- data/lib/nitro/scaffold.rb +69 -17
- data/lib/nitro/shaders.rb +54 -83
- data/lib/nitro/template.rb +7 -1
- data/proto/README +11 -0
- data/proto/conf/apache.conf +51 -0
- data/proto/conf/lhttpd.conf +107 -0
- data/proto/public/error.xhtml +56 -0
- data/proto/public/fcgi.rb +5 -0
- data/proto/public/index.xhtml +83 -0
- data/proto/public/js/ajax.js +63 -0
- data/proto/public/media/nitro.png +0 -0
- data/proto/run.rb +11 -0
- data/test/nitro/tc_controller.rb +1 -4
- data/test/nitro/tc_dispatcher.rb +8 -0
- data/test/nitro/tc_localization.rb +49 -0
- metadata +34 -6
- data/bin/new_form.rb +0 -54
data/lib/nitro/controller.rb
CHANGED
@@ -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,
|
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
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
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
|
data/lib/nitro/dispatcher.rb
CHANGED
@@ -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
|
-
|
141
|
+
base = '/'
|
141
142
|
klass = controller_class_for(:root, context)
|
142
143
|
action = 'index'
|
143
144
|
|
144
|
-
when
|
145
|
-
if klass = controller_class_for(parts[
|
145
|
+
when 1
|
146
|
+
if klass = controller_class_for(parts[0], context)
|
146
147
|
# controller/ -> controller.index
|
147
|
-
|
148
|
+
base = "/#{parts[0]}"
|
148
149
|
action = 'index'
|
149
150
|
else
|
150
151
|
# action/ -> root.action
|
151
|
-
|
152
|
+
base = '/'
|
152
153
|
klass = controller_class_for(:root, context)
|
153
|
-
action = parts[
|
154
|
+
action = parts[0]
|
154
155
|
end
|
155
156
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
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
|
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
|
8
|
+
# The design and implementation is HEAVILY influenced
|
9
|
+
# by Rails.
|
9
10
|
#
|
10
|
-
#
|
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:
|
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
|
131
|
-
# to the before and after methods. Both methods
|
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
|
205
|
+
raise 'Valid filters are either a Symbol, a String or a Proc/Method.'
|
204
206
|
end
|
205
207
|
end
|
206
208
|
|
data/lib/nitro/localization.rb
CHANGED
@@ -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
|
-
#
|
12
|
+
# Represents a locale.
|
10
13
|
#--
|
11
|
-
# TODO:
|
14
|
+
# TODO: initialize translation map from a yaml file.
|
12
15
|
#++
|
13
16
|
|
14
|
-
class
|
17
|
+
class Locale
|
15
18
|
|
16
|
-
#
|
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
|
-
|
50
|
+
private
|
51
|
+
|
52
|
+
def parse_hash(map)
|
22
53
|
@map = map
|
23
54
|
end
|
24
55
|
|
25
|
-
|
26
|
-
|
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.
|
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
|
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
|
-
|
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, '---'
|
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
|