nitro 0.6.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +175 -0
- data/README +41 -7
- data/RELEASES +24 -0
- data/Rakefile +5 -7
- data/bin/new_app.rb +26 -4
- data/bin/new_form.rb +54 -0
- data/bin/proto/config.rb +3 -3
- data/bin/proto/root/index.xhtml +2 -34
- data/bin/proto/root/style.css +4 -70
- data/bin/proto/root/style.xsl +8 -39
- data/doc/tutorial.txt +5 -0
- data/examples/blog/app.rb +2 -1
- data/examples/blog/config.rb +7 -2
- data/examples/blog/root/style.xsl +1 -2
- data/examples/flash/README +34 -0
- data/examples/flash/app.rb +20 -0
- data/examples/flash/config.rb +38 -0
- data/examples/flash/lib/flash.rb +40 -0
- data/examples/flash/root/index.xhtml +25 -0
- data/examples/flash/root/show_inline_text.xhtml +12 -0
- data/examples/flash/tmp.swf +0 -0
- data/examples/og/README +7 -0
- data/examples/og/mock_example.rb +58 -0
- data/examples/og/run.rb +9 -5
- data/examples/tiny/root/include.xhtml +3 -0
- data/examples/tiny/root/index.xhtml +2 -1
- data/lib/glue/property.rb +166 -107
- data/lib/glue/property.rb.old +307 -0
- data/lib/nitro/builders/form.rb +26 -17
- data/lib/nitro/events.rb +1 -1
- data/lib/nitro/markup.rb +120 -0
- data/lib/nitro/server/cookie.rb +1 -1
- data/lib/nitro/server/dispatcher.rb +5 -6
- data/lib/nitro/server/filters.rb +1 -1
- data/lib/nitro/server/render.rb +33 -29
- data/lib/nitro/server/shaders.rb +32 -3
- data/lib/nitro/server/user.rb +1 -1
- data/lib/nitro/server/webrick.rb +9 -4
- data/lib/nitro/ui/popup.rb +1 -1
- data/lib/nitro/ui/select.rb +1 -1
- data/lib/nitro/ui/tabs.rb +1 -1
- data/lib/nitro/version.rb +2 -2
- data/lib/og.rb +17 -6
- data/lib/og/backend.rb +34 -4
- data/lib/og/backends/mysql.rb +3 -17
- data/lib/og/backends/psql.rb +5 -17
- data/lib/og/meta.rb +41 -26
- data/lib/og/mock.rb +223 -0
- data/lib/og/version.rb +2 -2
- data/lib/parts/content.rb +61 -0
- data/test/glue/{tc_properties.rb → tc_property.rb} +0 -1
- data/test/glue/tc_property_mixins.rb +62 -0
- data/test/og/tc_lifecycle.rb +107 -0
- data/test/tc_og.rb +31 -4
- data/vendor/README +6 -0
- data/vendor/binding_of_caller.rb +81 -0
- data/vendor/breakpoint.rb +526 -0
- data/vendor/breakpoint_client.rb +157 -0
- metadata +135 -95
@@ -0,0 +1,40 @@
|
|
1
|
+
# code:
|
2
|
+
# * George Moschovitis <gm@navel.gr>
|
3
|
+
#
|
4
|
+
# (c) 2004 Navel, all rights reserved.
|
5
|
+
# $Id: flash.rb 189 2004-12-13 21:38:05Z gmosx $
|
6
|
+
|
7
|
+
require 'nitro/service'
|
8
|
+
require 'ming/ming'
|
9
|
+
|
10
|
+
module N
|
11
|
+
|
12
|
+
|
13
|
+
# = FlashService
|
14
|
+
#
|
15
|
+
class FlashService < N::Service
|
16
|
+
include Ming
|
17
|
+
|
18
|
+
SOURCE_FILE = __FILE__
|
19
|
+
|
20
|
+
def show_text
|
21
|
+
create_flash
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def create_flash
|
27
|
+
m = SWFMovie.new
|
28
|
+
f = SWFBrowserFont.new('_serif')
|
29
|
+
t = SWFTextField.new
|
30
|
+
t.set_font(f)
|
31
|
+
t.add_string(@params['text'])
|
32
|
+
m.add(t)
|
33
|
+
@response.header['Content-Type'] = 'application/x-shockwave-flash'
|
34
|
+
m.save('tmp.swf')
|
35
|
+
@out = File.read('tmp.swf')
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end # module
|
@@ -0,0 +1,25 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
|
3
|
+
<html>
|
4
|
+
|
5
|
+
<h1>Dynamic flash generation.</h1>
|
6
|
+
|
7
|
+
<p>
|
8
|
+
<h3>Implemented as an action</h3>
|
9
|
+
<form name="t1" action="show_text">
|
10
|
+
Enter some text here:<br />
|
11
|
+
<input type="text" name="text" /><br />
|
12
|
+
<input type="submit" />
|
13
|
+
</form>
|
14
|
+
</p>
|
15
|
+
|
16
|
+
<p>
|
17
|
+
<h3>Implemented inline in the template action</h3>
|
18
|
+
<form name="t1" action="show_inline_text">
|
19
|
+
Enter some text here:<br />
|
20
|
+
<input type="text" name="text" /><br />
|
21
|
+
<input type="submit" />
|
22
|
+
</form>
|
23
|
+
</p>
|
24
|
+
|
25
|
+
</html>
|
Binary file
|
data/examples/og/README
CHANGED
@@ -0,0 +1,58 @@
|
|
1
|
+
# = Og Mocking Example
|
2
|
+
#
|
3
|
+
# A simple example to demonstrate how to mock Og.
|
4
|
+
# Very useful in test units.
|
5
|
+
#
|
6
|
+
# code:
|
7
|
+
# * George Moschovitis <gm@navel.gr>
|
8
|
+
#
|
9
|
+
# (c) 2004 Navel, all rights reserved.
|
10
|
+
# $Id: run.rb 185 2004-12-10 13:29:09Z gmosx $
|
11
|
+
|
12
|
+
$LOAD_PATH.unshift '../../lib'
|
13
|
+
|
14
|
+
require 'rubygems'
|
15
|
+
require 'flexmock'
|
16
|
+
require 'og'
|
17
|
+
require 'og/mock'
|
18
|
+
require 'logger'
|
19
|
+
|
20
|
+
$log = Logger.new($stderr)
|
21
|
+
|
22
|
+
class Article
|
23
|
+
prop_accessor :body, String
|
24
|
+
|
25
|
+
def initialize(body = nil)
|
26
|
+
@body = body
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class SimpleTest < Test::Unit::TestCase
|
31
|
+
|
32
|
+
def setup
|
33
|
+
$og = Og::MockDatabase.new
|
34
|
+
end
|
35
|
+
|
36
|
+
def teardown
|
37
|
+
$og = nil
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_me
|
41
|
+
mocks = [
|
42
|
+
Article.new('body1'),
|
43
|
+
Article.new('body2'),
|
44
|
+
Article.new('body3')
|
45
|
+
]
|
46
|
+
$og.mock_handle(:load_all) { |klass, extrasql| mocks }
|
47
|
+
|
48
|
+
# differnt ways to call the mocked method...
|
49
|
+
puts 'Here are the articles:', Article.all
|
50
|
+
puts 'Here are the articles:', Article.load_all
|
51
|
+
puts 'Here are the articles:', $og.load_all(Article)
|
52
|
+
|
53
|
+
# 3 times called
|
54
|
+
assert_equal(3, $og.mock_count(:load_all))
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
data/examples/og/run.rb
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
# * George Moschovitis <gm@navel.gr>
|
7
7
|
#
|
8
8
|
# (c) 2004 Navel, all rights reserved.
|
9
|
-
# $Id: run.rb
|
9
|
+
# $Id: run.rb 198 2004-12-22 11:26:59Z gmosx $
|
10
10
|
|
11
11
|
$:.unshift "../../lib"
|
12
12
|
|
@@ -103,7 +103,7 @@ class Category
|
|
103
103
|
prop_accessor :body, String
|
104
104
|
|
105
105
|
# define a 'many to many' relation.
|
106
|
-
many_to_many Article
|
106
|
+
many_to_many :articles, Article
|
107
107
|
|
108
108
|
def initialize(title = nil)
|
109
109
|
@title = title
|
@@ -141,7 +141,6 @@ end
|
|
141
141
|
# Initialize a logger.
|
142
142
|
|
143
143
|
$log = Logger.new(STDERR);
|
144
|
-
|
145
144
|
# Og configuration.
|
146
145
|
config = {
|
147
146
|
:address => "localhost",
|
@@ -199,9 +198,11 @@ c2.article_oid = a1.oid
|
|
199
198
|
# managed objects).
|
200
199
|
$og << c2
|
201
200
|
|
201
|
+
# an alternative (easier and cooler) way to add children in a
|
202
|
+
# has_many relation:
|
202
203
|
c3 = ArticleComment.new("Comment 3")
|
203
|
-
|
204
|
-
c3
|
204
|
+
# add_comment is automatically added by Og.
|
205
|
+
a1.add_comment(c3)
|
205
206
|
|
206
207
|
puts "\n\n"
|
207
208
|
puts "* Print all all comments for article 1:"
|
@@ -287,4 +288,7 @@ puts '---'
|
|
287
288
|
|
288
289
|
article.categories.each { |c| puts c.title }
|
289
290
|
|
291
|
+
# create and save the article in one step.
|
292
|
+
article = Article.create("title", "body")
|
290
293
|
|
294
|
+
puts '--', article.oid
|
data/lib/glue/property.rb
CHANGED
@@ -2,10 +2,9 @@
|
|
2
2
|
# * George Moschovitis <gm@navel.gr>
|
3
3
|
# design:
|
4
4
|
# * Anastastios Koutoumanos <ak@navel.gr>
|
5
|
-
# * Elias Karakoulakis <ekarak@ktismata.com>
|
6
5
|
#
|
7
6
|
# (c) 2004 Navel, all rights reserved.
|
8
|
-
# $Id: property.rb
|
7
|
+
# $Id: property.rb 200 2004-12-27 11:24:41Z gmosx $
|
9
8
|
|
10
9
|
require "glue/array"
|
11
10
|
require "glue/hash"
|
@@ -25,10 +24,8 @@ module G
|
|
25
24
|
#
|
26
25
|
#--
|
27
26
|
# TODO:
|
28
|
-
# Inject only the really needd methods into Module.
|
29
27
|
# Perhaps a sync is needed in evals (!!!!)
|
30
28
|
#++
|
31
|
-
#
|
32
29
|
class Property
|
33
30
|
# the symbol of the property
|
34
31
|
attr_accessor :symbol
|
@@ -36,7 +33,7 @@ class Property
|
|
36
33
|
attr_accessor :name
|
37
34
|
# the class of the property
|
38
35
|
attr_accessor :klass
|
39
|
-
# additional metadata (like sql
|
36
|
+
# additional metadata (like sql declaration, sql index, etc)
|
40
37
|
attr_accessor :meta
|
41
38
|
|
42
39
|
def initialize(symbol, klass, meta = {})
|
@@ -52,6 +49,119 @@ class Property
|
|
52
49
|
def to_s
|
53
50
|
return name
|
54
51
|
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
# = PropertyUtils
|
56
|
+
#
|
57
|
+
# A collection of Property related utility methods.
|
58
|
+
#
|
59
|
+
module PropertyUtils
|
60
|
+
|
61
|
+
# Add accessors to the properties to the given target
|
62
|
+
# (Module or Class). For simplicity also create the
|
63
|
+
# meta accessors.
|
64
|
+
#--
|
65
|
+
# gmosx: Perhaps we 'll optimize this in the future.
|
66
|
+
#++
|
67
|
+
def self.enchant(target)
|
68
|
+
unless target.singleton_methods.include?('__props')
|
69
|
+
target.module_eval <<-"end_eval", __FILE__, __LINE__
|
70
|
+
@@__meta = G::SafeHash.new
|
71
|
+
@@__props = G::SafeArray.new
|
72
|
+
|
73
|
+
def self.__props
|
74
|
+
@@__props
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.__props=(props)
|
78
|
+
@@__props = props
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.__meta
|
82
|
+
@@__meta
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.__meta=(meta)
|
86
|
+
@@__meta = meta
|
87
|
+
end
|
88
|
+
end_eval
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# Copy properties from src (Module or Class) to dest.
|
93
|
+
#
|
94
|
+
def self.copy_props(src, dest)
|
95
|
+
src.__props.each do |p|
|
96
|
+
add_prop(dest, p)
|
97
|
+
end
|
98
|
+
|
99
|
+
# copy the metadata.
|
100
|
+
src.__meta.each do |k, val|
|
101
|
+
val.each { |v| dest.meta(k, v) } if val
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# Add the property to the target (Class or Module)
|
106
|
+
#
|
107
|
+
def self.add_prop(target, prop)
|
108
|
+
if idx = target.__props.index(prop)
|
109
|
+
# override in case of duplicates. Keep the order of the props.
|
110
|
+
target.__props[idx] = prop
|
111
|
+
else
|
112
|
+
target.__props << prop
|
113
|
+
end
|
114
|
+
|
115
|
+
# Precompile the property read/write methods
|
116
|
+
|
117
|
+
s, klass = prop.symbol, prop.klass
|
118
|
+
|
119
|
+
if prop.meta[:reader]
|
120
|
+
target.module_eval %{
|
121
|
+
def #{s}
|
122
|
+
return @#{s}
|
123
|
+
end
|
124
|
+
}
|
125
|
+
end
|
126
|
+
|
127
|
+
# gmosx: __force_xxx reuses xxx= to allow for easier
|
128
|
+
# overrides.
|
129
|
+
if prop.meta[:writer]
|
130
|
+
target.module_eval %{
|
131
|
+
#{prop_setter(prop)}
|
132
|
+
|
133
|
+
def __force_#{s}(val)
|
134
|
+
self.#{s}=(} + case klass.name
|
135
|
+
when Fixnum.name
|
136
|
+
"val.to_i()"
|
137
|
+
when String.name
|
138
|
+
"val.to_s()"
|
139
|
+
when Float.name
|
140
|
+
"val.to_f()"
|
141
|
+
when Time.name
|
142
|
+
"Time.parse(val.to_s())"
|
143
|
+
when TrueClass.name, FalseClass.name
|
144
|
+
"val.to_i() > 0"
|
145
|
+
else
|
146
|
+
"val"
|
147
|
+
end + %{)
|
148
|
+
end
|
149
|
+
}
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# Generates the property setter code. Can be overriden
|
154
|
+
# to support extra functionality (example: markup)
|
155
|
+
#
|
156
|
+
def self.prop_setter(prop)
|
157
|
+
s = prop.symbol
|
158
|
+
%{
|
159
|
+
def #{s}=(val)
|
160
|
+
@#{s} = val
|
161
|
+
end
|
162
|
+
}
|
163
|
+
end
|
164
|
+
|
55
165
|
end
|
56
166
|
|
57
167
|
end # module
|
@@ -90,36 +200,55 @@ class Module
|
|
90
200
|
end
|
91
201
|
end
|
92
202
|
|
93
|
-
|
94
|
-
eval %{
|
95
|
-
# Properties
|
96
|
-
# An array is used to enforce order.
|
97
|
-
def __props
|
98
|
-
@__props
|
99
|
-
end
|
203
|
+
G::PropertyUtils.enchant(self)
|
100
204
|
|
101
|
-
|
102
|
-
|
205
|
+
if self.is_a?(Class)
|
206
|
+
|
207
|
+
# Add some extra code to append features to
|
208
|
+
# subclasses.
|
209
|
+
self.module_eval <<-"end_eval", __FILE__, __LINE__
|
210
|
+
|
211
|
+
def self.inherited(sub)
|
212
|
+
G::PropertyUtils.enchant(sub)
|
213
|
+
G::PropertyUtils.copy_props(self, sub)
|
214
|
+
# gmosx: We have to define @@__props first to avoid reusing
|
215
|
+
# the hash from the module. super must stay at the end.
|
216
|
+
super
|
103
217
|
end
|
104
|
-
|
105
|
-
|
106
|
-
|
218
|
+
|
219
|
+
end_eval
|
220
|
+
|
221
|
+
else
|
222
|
+
|
223
|
+
# Add some extra code for modules to append
|
224
|
+
# their features to classes that include it.
|
225
|
+
self.module_eval <<-"end_eval", __FILE__, __LINE__
|
226
|
+
|
227
|
+
def self.append_features(base)
|
228
|
+
G::PropertyUtils.enchant(base)
|
229
|
+
G::PropertyUtils.copy_props(self, base)
|
230
|
+
# gmosx: We have to define @@__props first to avoid reusing
|
231
|
+
# the hash from the module. super must stay at the end.
|
232
|
+
super
|
107
233
|
end
|
108
234
|
|
109
|
-
|
110
|
-
|
111
|
-
end
|
112
|
-
}
|
235
|
+
end_eval
|
236
|
+
|
113
237
|
end
|
114
|
-
|
115
|
-
@__props = G::SafeArray.new() unless @__props
|
116
|
-
|
238
|
+
|
117
239
|
property = G::Property.new(symbol, klass, meta)
|
118
240
|
|
119
241
|
reader = meta[:reader] || true
|
120
242
|
writer = writer || meta[:writer] || false
|
121
|
-
|
122
|
-
|
243
|
+
|
244
|
+
meta[:reader] = true if meta[:reader].nil?
|
245
|
+
if defined?(writer)
|
246
|
+
meta[:writer] = writer
|
247
|
+
else
|
248
|
+
meta[:writer] = true if meta[:writer].nil?
|
249
|
+
end
|
250
|
+
|
251
|
+
G::PropertyUtils.add_prop(self, property)
|
123
252
|
end
|
124
253
|
|
125
254
|
# Helper method. Accepts a collection of symbols and generates
|
@@ -218,90 +347,20 @@ class Module
|
|
218
347
|
end
|
219
348
|
end
|
220
349
|
|
221
|
-
# Add the property
|
222
|
-
#
|
223
|
-
def __add_prop(prop, reader = true, writer = true)
|
224
|
-
if idx = @__props.index(prop)
|
225
|
-
# override in case of duplicates. Keep the order of the props.
|
226
|
-
@__props[idx] = prop
|
227
|
-
else
|
228
|
-
@__props << prop
|
229
|
-
end
|
230
|
-
|
231
|
-
# Precompile the property read/write methods
|
232
|
-
|
233
|
-
s, klass = prop.symbol, prop.klass
|
234
|
-
|
235
|
-
if reader
|
236
|
-
module_eval %{
|
237
|
-
def #{s}
|
238
|
-
return @#{s}
|
239
|
-
end
|
240
|
-
}
|
241
|
-
end
|
242
|
-
|
243
|
-
# gmosx: __force_xxx reuses xxx= to allow for easier
|
244
|
-
# overrides.
|
245
|
-
if writer
|
246
|
-
module_eval %{
|
247
|
-
def #{s}=(val)
|
248
|
-
@#{s} = val
|
249
|
-
end
|
250
|
-
|
251
|
-
def __force_#{s}(val)
|
252
|
-
self.#{s}=(} + case klass.name
|
253
|
-
when Fixnum.name
|
254
|
-
"val.to_i()"
|
255
|
-
when String.name
|
256
|
-
"val.to_s()"
|
257
|
-
when Float.name
|
258
|
-
"val.to_f()"
|
259
|
-
when Time.name
|
260
|
-
"Time.parse(val.to_s())"
|
261
|
-
when TrueClass.name, FalseClass.name
|
262
|
-
"val.to_i() > 0"
|
263
|
-
else
|
264
|
-
"val"
|
265
|
-
end + %{)
|
266
|
-
end
|
267
|
-
}
|
268
|
-
end
|
269
|
-
end
|
270
350
|
|
271
|
-
# Attach metadata
|
272
|
-
#
|
351
|
+
# Attach metadata.
|
352
|
+
# Guard against duplicates, no need to keep order.
|
353
|
+
# This method uses closures :)
|
354
|
+
#--
|
355
|
+
# gmosx: crappy implementation, recode.
|
356
|
+
#++
|
273
357
|
def meta(key, val)
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
@__meta[key].delete_if { |v| val == v }
|
280
|
-
@__meta[key] << val
|
358
|
+
self.module_eval <<-"end_eval", __FILE__, __LINE__
|
359
|
+
@@__meta[key] ||= []
|
360
|
+
@@__meta[key].delete_if { |v| val == v }
|
361
|
+
@@__meta[key] << val
|
362
|
+
end_eval
|
281
363
|
end
|
282
|
-
|
283
|
-
# This method is typically called before including other
|
284
|
-
# modules to preserve properties order.
|
285
|
-
#
|
286
|
-
def inherit_meta(mod = superclass)
|
287
|
-
# concat props.
|
288
|
-
if mod.__props
|
289
|
-
@__props = G::SafeArray.new unless @__props
|
290
|
-
|
291
|
-
mod.__props.each { |p|
|
292
|
-
__add_prop(p)
|
293
|
-
}
|
294
|
-
end
|
295
364
|
|
296
|
-
# concat metadata
|
297
|
-
if mod.__meta
|
298
|
-
mod.__meta.each { |k, val|
|
299
|
-
val.each { |v|
|
300
|
-
meta(k, v)
|
301
|
-
} if val
|
302
|
-
}
|
303
|
-
end
|
304
|
-
end
|
305
|
-
|
306
365
|
end
|
307
366
|
|