bike 0.2.2 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +11 -20
- data/lib/_widget/submit.rb +1 -1
- data/lib/set/_set.rb +14 -6
- data/lib/set/static_folder.rb +41 -35
- data/t/skin/foo/boo/form.html +1 -0
- data/t/skin/foo/boo/rss.xml +1 -0
- data/t/skin/t_tmpl_form/form.html +1 -0
- data/t/skin/t_tmpl_form/index.html +1 -0
- data/t/skin/t_tmpl_read/index.html +1 -0
- data/t/skin/t_tmpl_read/read.html +1 -0
- data/t/test_set_folder.rb +59 -16
- data/t/test_set_static.rb +68 -2
- metadata +9 -3
data/README.rdoc
CHANGED
@@ -3,9 +3,11 @@
|
|
3
3
|
Bike is the easiest web application framework ever.
|
4
4
|
You can make various apps such like blog, forum, contact form by putting single (or several) HTML file with a bit of special markups. The view rules. There is no model definition, no server restart, and no coding at all.
|
5
5
|
|
6
|
-
==
|
6
|
+
== Sites
|
7
7
|
|
8
|
-
http://github.com/afunai/bike
|
8
|
+
* Home: http://github.com/afunai/bike
|
9
|
+
* Docs: http://github.com/afunai/bike/wiki
|
10
|
+
* Demo: http://runo.heroku.com/examples/index.html
|
9
11
|
|
10
12
|
== Features
|
11
13
|
|
@@ -16,7 +18,7 @@ http://github.com/afunai/bike/wiki
|
|
16
18
|
* You can make nested apps inside an app (e.g. blog comments inside a blog entry).
|
17
19
|
* Authentication / Authorization / User admin are built in by default.
|
18
20
|
* Storage can be plain YAML files (default), or any RDB via Sequel.
|
19
|
-
* Bike
|
21
|
+
* Bike can be deployed anywhere as it is a simple Rack application.
|
20
22
|
|
21
23
|
== Quick Start
|
22
24
|
|
@@ -28,9 +30,6 @@ Open a command line terminal. Type:
|
|
28
30
|
|
29
31
|
gem install bike
|
30
32
|
|
31
|
-
If you want to make thumbnails for submitted images, you have to install QuickMagick as well.
|
32
|
-
http://rubyforge.org/projects/quickmagick/
|
33
|
-
|
34
33
|
=== Step 2 - Initialize a Bike Directory
|
35
34
|
|
36
35
|
In a command line terminal, go to an empty directory where you want to build Bike projects.
|
@@ -46,7 +45,6 @@ This will create a "bike" directory, which includes:
|
|
46
45
|
|
47
46
|
=== Step 3 - Start a Test Server
|
48
47
|
|
49
|
-
In the terminal, change to the newly created "bike" directory.
|
50
48
|
Type:
|
51
49
|
|
52
50
|
bike run
|
@@ -55,24 +53,20 @@ Type:
|
|
55
53
|
|
56
54
|
Now open this URL with your browser.
|
57
55
|
|
58
|
-
|
56
|
+
http://localhost:9292/
|
59
57
|
|
60
58
|
You will see the default homepage of Bike.
|
61
|
-
There is some links to examples such like Blog, Contact Form, Forum, etc.
|
59
|
+
There is some links to examples such like Blog, Contact Form, Forum, etc. See what can be done by plain HTML files.
|
62
60
|
|
63
61
|
=== Step 5 - Create Your Own App
|
64
62
|
|
65
|
-
Let's call our app "fab".
|
66
|
-
It is a web-based forum where logged in users can submit their own articles, and everybody can read them.
|
67
|
-
We put links to signup / login at bottom of the app.
|
68
|
-
|
69
63
|
Create a new directory under bike/skin/:
|
70
64
|
|
71
|
-
mkdir skin/
|
65
|
+
mkdir skin/myapp/
|
72
66
|
|
73
67
|
Then create a new HTML file with your favorite editor:
|
74
68
|
|
75
|
-
edit skin/
|
69
|
+
edit skin/myapp/index.html
|
76
70
|
|
77
71
|
The content is: (You can just copy & paste, of course)
|
78
72
|
|
@@ -102,12 +96,9 @@ The content is: (You can just copy & paste, of course)
|
|
102
96
|
|
103
97
|
=== Step 6 - That's it!
|
104
98
|
|
105
|
-
|
106
|
-
|
107
|
-
http://localhost:9292/fab/
|
99
|
+
http://localhost:9292/myapp/index.html
|
108
100
|
|
109
|
-
You have just created your first app.
|
110
|
-
When you need more complicated tricks, HTMLs under skin/examples/ will be your help. Also, you should check out the wiki: http://github.com/afunai/bike/wiki
|
101
|
+
You have just created your first app. Log in with root/root to try it out. Have a nice ride!
|
111
102
|
|
112
103
|
== Note on Patches/Pull Requests
|
113
104
|
|
data/lib/_widget/submit.rb
CHANGED
@@ -37,7 +37,7 @@ _html
|
|
37
37
|
def _g_submit_preview_delete(arg)
|
38
38
|
if (
|
39
39
|
permit_get?(arg.merge(:action => :delete)) &&
|
40
|
-
collect_item(arg[:conds]).
|
40
|
+
collect_item(arg[:conds]).any? {|item| item[:id] !~ Bike::REX::ID_NEW } &&
|
41
41
|
arg[:orig_action] != :preview
|
42
42
|
)
|
43
43
|
<<_html
|
data/lib/set/_set.rb
CHANGED
@@ -92,17 +92,13 @@ module Bike::Set
|
|
92
92
|
def _get(arg)
|
93
93
|
if respond_to?("_g_#{arg[:action]}", true)
|
94
94
|
_get_by_method arg
|
95
|
-
elsif summary?(arg) && action_tmpl = my[:tmpl][:summary]
|
96
|
-
_get_by_tmpl(arg, action_tmpl)
|
97
|
-
elsif action_tmpl = my[:tmpl][arg[:sub_action]] || my[:tmpl][arg[:action]]
|
98
|
-
_get_by_tmpl(arg, action_tmpl)
|
99
95
|
else
|
100
|
-
_get_by_tmpl(arg,
|
96
|
+
_get_by_tmpl(arg, action_tmpl(arg))
|
101
97
|
end
|
102
98
|
end
|
103
99
|
|
104
100
|
def _get_by_tmpl(arg, tmpl = '')
|
105
|
-
tmpl.gsub(/@\((.+?)\)/) {
|
101
|
+
tmpl.to_s.gsub(/@\((.+?)\)/) {
|
106
102
|
tag = $&
|
107
103
|
steps = $1.split '-'
|
108
104
|
id = steps.pop
|
@@ -169,6 +165,18 @@ module Bike::Set
|
|
169
165
|
}
|
170
166
|
end
|
171
167
|
|
168
|
+
def action_tmpl(arg)
|
169
|
+
if summary?(arg) && my[:tmpl][:summary]
|
170
|
+
my[:tmpl][:summary]
|
171
|
+
elsif action_tmpl = my[:tmpl][arg[:sub_action]] || my[:tmpl][arg[:action]]
|
172
|
+
action_tmpl
|
173
|
+
elsif [:create, :update, :delete, :login].include? arg[:action]
|
174
|
+
my[:tmpl][:form] || my[:tmpl][:index]
|
175
|
+
else
|
176
|
+
my[:tmpl][:read] || my[:tmpl][:index]
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
172
180
|
def summary?(arg)
|
173
181
|
[:read, nil].include?(arg[:action]) && !arg[:sub_action]
|
174
182
|
end
|
data/lib/set/static_folder.rb
CHANGED
@@ -10,44 +10,25 @@ class Bike::Set::Static::Folder < Bike::Set::Static
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def initialize(meta = {})
|
13
|
-
meta
|
14
|
-
meta
|
15
|
-
|
16
|
-
|
17
|
-
::Dir.glob(::File.join(Bike['skin_dir'], my[:html_dir].to_s, '*.html')).each {|f|
|
18
|
-
action = ::File.basename(f, '.*').intern
|
19
|
-
merge_tmpl(@meta, Bike::Parser.parse_html(::File.read(f), action)) if action != :index
|
20
|
-
}
|
21
|
-
::Dir.glob(::File.join(Bike['skin_dir'], my[:html_dir].to_s, '*.xml')).each {|f|
|
22
|
-
action = ::File.basename(f, '.*').intern
|
23
|
-
merge_tmpl(@meta, Bike::Parser.parse_xml(::File.read(f), action)) if action != :index
|
24
|
-
}
|
13
|
+
@meta = meta
|
14
|
+
@meta.merge! load_html
|
15
|
+
@meta.merge! load_yaml
|
25
16
|
|
26
17
|
@meta[:tmpl].values.each {|tmpl|
|
27
|
-
tmpl.sub!(/<head>([\s\n]*)/i) {
|
28
|
-
|
29
|
-
}
|
30
|
-
} if @meta[:tmpl]
|
18
|
+
tmpl.sub!(/<head>([\s\n]*)/i) { "#{$&}<base href=\"@(href)\" />#{$1}" }
|
19
|
+
}
|
31
20
|
|
32
|
-
@
|
21
|
+
@item_object = {}
|
33
22
|
end
|
34
23
|
|
35
24
|
def meta_dir
|
36
|
-
|
37
|
-
end
|
38
|
-
|
39
|
-
def meta_html_dir
|
40
|
-
if ::File.readable? ::File.join(Bike['skin_dir'], my[:dir], 'index.html')
|
41
|
-
my[:dir]
|
42
|
-
elsif my[:parent]
|
43
|
-
my[:parent][:html_dir]
|
44
|
-
end
|
25
|
+
my[:parent] ? ::File.join(my[:parent][:dir], my[:id]) : my[:id]
|
45
26
|
end
|
46
27
|
|
47
28
|
private
|
48
29
|
|
49
30
|
def _get(arg)
|
50
|
-
if arg['main'] && action_tmpl =
|
31
|
+
if arg['main'] && action_tmpl = action_tmpl(arg['main'])
|
51
32
|
_get_by_tmpl(arg, action_tmpl)
|
52
33
|
else
|
53
34
|
super
|
@@ -66,17 +47,42 @@ class Bike::Set::Static::Folder < Bike::Set::Static
|
|
66
47
|
super
|
67
48
|
end
|
68
49
|
|
69
|
-
def load_html
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
50
|
+
def load_html
|
51
|
+
files = ::Dir[::File.join Bike['skin_dir'], my[:dir], '*.{html,xml}'].sort
|
52
|
+
|
53
|
+
if model_file = files.find {|f| ['form', 'index'].include? ::File.basename(f, '.*') }
|
54
|
+
html = ::File.read model_file
|
55
|
+
action = ::File.basename(model_file, '.*').intern
|
56
|
+
meta = {:html => html}
|
57
|
+
meta.merge! Bike::Parser.parse_html(html, action, (::File.extname(model_file) == '.xml'))
|
58
|
+
|
59
|
+
files.delete model_file
|
60
|
+
files.each {|f|
|
61
|
+
html = ::File.read f
|
62
|
+
action = ::File.basename(f, '.*').intern
|
63
|
+
merge_tmpl(
|
64
|
+
meta,
|
65
|
+
Bike::Parser.parse_html(html, action, (::File.extname(f) == '.xml'))
|
66
|
+
)
|
67
|
+
}
|
68
|
+
|
69
|
+
meta
|
70
|
+
elsif my[:parent]
|
71
|
+
{
|
72
|
+
:label => my[:parent][:label],
|
73
|
+
:item => my[:parent][:item],
|
74
|
+
:tmpl => my[:parent][:tmpl],
|
75
|
+
}
|
76
|
+
else
|
77
|
+
{
|
78
|
+
:item => {},
|
79
|
+
:tmpl => {},
|
80
|
+
}
|
75
81
|
end
|
76
82
|
end
|
77
83
|
|
78
|
-
def load_yaml
|
79
|
-
yaml_file = ::File.join(Bike['skin_dir'], dir, 'index.yaml')
|
84
|
+
def load_yaml
|
85
|
+
yaml_file = ::File.join(Bike['skin_dir'], my[:dir], 'index.yaml')
|
80
86
|
meta = ::File.exists?(yaml_file) ? YAML.load_file(yaml_file) : {}
|
81
87
|
meta.keys.inject({}) {|m, k|
|
82
88
|
m[k.intern] = meta[k]
|
@@ -0,0 +1 @@
|
|
1
|
+
<html><ul class="app-boo"></ul></html>
|
@@ -0,0 +1 @@
|
|
1
|
+
<xml class="dummy">boo</xml>
|
@@ -0,0 +1 @@
|
|
1
|
+
<form>
|
@@ -0,0 +1 @@
|
|
1
|
+
<index>
|
@@ -0,0 +1 @@
|
|
1
|
+
<index>
|
@@ -0,0 +1 @@
|
|
1
|
+
<read>
|
data/t/test_set_folder.rb
CHANGED
@@ -39,22 +39,6 @@ class TC_Set_Folder < Test::Unit::TestCase
|
|
39
39
|
)
|
40
40
|
end
|
41
41
|
|
42
|
-
def test_meta_html_dir
|
43
|
-
folder = Bike::Set::Static::Folder.root.item('foo')
|
44
|
-
assert_equal(
|
45
|
-
'/foo',
|
46
|
-
folder[:html_dir],
|
47
|
-
"Folder#meta_html_dir should return meta_dir if there is 'index.html'"
|
48
|
-
)
|
49
|
-
|
50
|
-
folder = Bike::Set::Static::Folder.root.item('foo', 'bar')
|
51
|
-
assert_equal(
|
52
|
-
'/foo',
|
53
|
-
folder[:html_dir],
|
54
|
-
"Folder#meta_html_dir should return parent[:html_dir] if there is no 'index.html' in [:dir]"
|
55
|
-
)
|
56
|
-
end
|
57
|
-
|
58
42
|
def test_meta_href
|
59
43
|
folder = Bike::Set::Static::Folder.root.item('t_summary')
|
60
44
|
|
@@ -73,6 +57,29 @@ class TC_Set_Folder < Test::Unit::TestCase
|
|
73
57
|
)
|
74
58
|
end
|
75
59
|
|
60
|
+
def test_load_html
|
61
|
+
folder = Bike::Set::Static::Folder.root.item('foo', 'boo')
|
62
|
+
assert_equal(
|
63
|
+
'boo',
|
64
|
+
folder[:item]['main'][:workflow],
|
65
|
+
'Folder#load_html should load [:item] from form.html if available'
|
66
|
+
)
|
67
|
+
assert_equal(
|
68
|
+
"<html>$(main.message)$(main)</html>\n",
|
69
|
+
folder[:tmpl][:form],
|
70
|
+
'Folder#load_html should load [:tmpl][:form] from form.html'
|
71
|
+
)
|
72
|
+
assert_nil(
|
73
|
+
folder[:tmpl][:index],
|
74
|
+
'Folder#load_html should leave [:tmpl][:index] empty if there is no index.html'
|
75
|
+
)
|
76
|
+
assert_equal(
|
77
|
+
"<xml>boo</xml>\n",
|
78
|
+
folder[:tmpl][:rss],
|
79
|
+
'Folder#load_html should load [:tmpl] from *.xml if available'
|
80
|
+
)
|
81
|
+
end
|
82
|
+
|
76
83
|
def test_load_yaml
|
77
84
|
folder = Bike::Set::Static::Folder.new(:id => 'foo', :parent => nil)
|
78
85
|
assert_equal(
|
@@ -412,6 +419,42 @@ _html
|
|
412
419
|
)
|
413
420
|
end
|
414
421
|
|
422
|
+
def test_get_by_tmpl_with_form_action
|
423
|
+
folder = Bike::Set::Static::Folder.root.item('t_tmpl_form')
|
424
|
+
|
425
|
+
[:create, :update, :delete, :login].each {|action|
|
426
|
+
assert_equal(
|
427
|
+
"<form>\n",
|
428
|
+
folder.get('main' => {:action => action}),
|
429
|
+
"Folder#_get_by_tmpl should use tmpl[:form] if arg['main'][:action] is :#{action}"
|
430
|
+
)
|
431
|
+
}
|
432
|
+
|
433
|
+
assert_equal(
|
434
|
+
"<index>\n",
|
435
|
+
folder.get('main' => {:action => :read}),
|
436
|
+
'Folder#_get_by_tmpl should not use tmpl[:form] for read actions'
|
437
|
+
)
|
438
|
+
end
|
439
|
+
|
440
|
+
def test_get_by_tmpl_with_read_action
|
441
|
+
folder = Bike::Set::Static::Folder.root.item('t_tmpl_read')
|
442
|
+
|
443
|
+
[:read, :summary, :foo, nil].each {|action|
|
444
|
+
assert_equal(
|
445
|
+
"<read>\n",
|
446
|
+
folder.get('main' => {:action => action}),
|
447
|
+
"Folder#_get_by_tmpl should use tmpl[:read] if arg['main'][:action] is :#{action}"
|
448
|
+
)
|
449
|
+
}
|
450
|
+
|
451
|
+
assert_equal(
|
452
|
+
"<index>\n",
|
453
|
+
folder.get('main' => {:action => :create}),
|
454
|
+
'Folder#_get_by_tmpl should not use tmpl[:read] for form actions'
|
455
|
+
)
|
456
|
+
end
|
457
|
+
|
415
458
|
def test_g_login
|
416
459
|
folder = Bike::Set::Static::Folder.root.item('t_contact')
|
417
460
|
|
data/t/test_set_static.rb
CHANGED
@@ -242,7 +242,7 @@ _html
|
|
242
242
|
)
|
243
243
|
end
|
244
244
|
|
245
|
-
def
|
245
|
+
def test_get_by_tmpl_non_existing_meta
|
246
246
|
ss = Bike::Set::Static.new(:html => '')
|
247
247
|
assert_equal(
|
248
248
|
'foo @(foo-bar) foo',
|
@@ -256,7 +256,7 @@ _html
|
|
256
256
|
)
|
257
257
|
end
|
258
258
|
|
259
|
-
def
|
259
|
+
def test_get_by_tmpl_non_existing_item
|
260
260
|
ss = Bike::Set::Static.new(:html => '')
|
261
261
|
assert_equal(
|
262
262
|
'foo $(foo) foo',
|
@@ -265,6 +265,72 @@ _html
|
|
265
265
|
)
|
266
266
|
end
|
267
267
|
|
268
|
+
def test_get_by_tmpl_with_form_action
|
269
|
+
ss = Bike::Set::Static.new(:html => 'index')
|
270
|
+
ss[:tmpl][:form] = 'form'
|
271
|
+
class << ss
|
272
|
+
undef_method :_g_login # test purpose only
|
273
|
+
end
|
274
|
+
|
275
|
+
[:create, :update, :delete, :login].each {|action|
|
276
|
+
assert_equal(
|
277
|
+
'form',
|
278
|
+
ss.get(:action => action),
|
279
|
+
"Set#_get_by_tmpl should use tmpl[:form] for :#{action}"
|
280
|
+
)
|
281
|
+
}
|
282
|
+
|
283
|
+
ss[:tmpl][:read] = nil
|
284
|
+
assert_equal(
|
285
|
+
'index',
|
286
|
+
ss.get(:action => :read),
|
287
|
+
'Set#_get_by_tmpl should not use tmpl[:form] for read actions'
|
288
|
+
)
|
289
|
+
ss[:tmpl][:read] = 'read'
|
290
|
+
assert_equal(
|
291
|
+
'read',
|
292
|
+
ss.get(:action => :read),
|
293
|
+
'Set#_get_by_tmpl should not use tmpl[:form] for read actions'
|
294
|
+
)
|
295
|
+
end
|
296
|
+
|
297
|
+
def test_get_by_tmpl_without_index_action
|
298
|
+
ss = Bike::Set::Static.new(:html => '')
|
299
|
+
ss[:tmpl] = {:form => 'form'}
|
300
|
+
|
301
|
+
assert_equal(
|
302
|
+
'',
|
303
|
+
ss.get(:action => :read),
|
304
|
+
'Set#_get_by_tmpl should not use tmpl[:form] for :read'
|
305
|
+
)
|
306
|
+
end
|
307
|
+
|
308
|
+
def test_get_by_tmpl_with_read_action
|
309
|
+
ss = Bike::Set::Static.new(:html => 'index')
|
310
|
+
ss[:tmpl][:read] = 'read'
|
311
|
+
|
312
|
+
[:read, :summary, :foo, nil].each {|action|
|
313
|
+
assert_equal(
|
314
|
+
'read',
|
315
|
+
ss.get(:action => action),
|
316
|
+
"Set#_get_by_tmpl should use tmpl[:read] when available"
|
317
|
+
)
|
318
|
+
}
|
319
|
+
|
320
|
+
ss[:tmpl][:form] = nil
|
321
|
+
assert_equal(
|
322
|
+
'index',
|
323
|
+
ss.get(:action => :create),
|
324
|
+
'Set#_get_by_tmpl should not use tmpl[:read] for form actions'
|
325
|
+
)
|
326
|
+
ss[:tmpl][:form] = 'form'
|
327
|
+
assert_equal(
|
328
|
+
'form',
|
329
|
+
ss.get(:action => :create),
|
330
|
+
'Set#_get_by_tmpl should not use tmpl[:read] for form actions'
|
331
|
+
)
|
332
|
+
end
|
333
|
+
|
268
334
|
def test_recursive_tmpl
|
269
335
|
ss = Bike::Set::Static.new(:html => <<'_html')
|
270
336
|
<li>$()</li>
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 2
|
8
|
-
-
|
9
|
-
version: 0.2.
|
8
|
+
- 3
|
9
|
+
version: 0.2.3
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Akira FUNAI
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-11-02 00:00:00 +09:00
|
18
18
|
default_executable: bike
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -244,6 +244,8 @@ files:
|
|
244
244
|
- t/skin/foo/bar/20091120_0001.yaml
|
245
245
|
- t/skin/foo/bar/index.yaml
|
246
246
|
- t/skin/foo/baz/css/baz.css
|
247
|
+
- t/skin/foo/boo/form.html
|
248
|
+
- t/skin/foo/boo/rss.xml
|
247
249
|
- t/skin/foo/css/foo.css
|
248
250
|
- t/skin/foo/index.html
|
249
251
|
- t/skin/foo/index.yaml
|
@@ -264,6 +266,10 @@ files:
|
|
264
266
|
- t/skin/t_summary/create.html
|
265
267
|
- t/skin/t_summary/index.html
|
266
268
|
- t/skin/t_summary/summary.html
|
269
|
+
- t/skin/t_tmpl_form/form.html
|
270
|
+
- t/skin/t_tmpl_form/index.html
|
271
|
+
- t/skin/t_tmpl_read/index.html
|
272
|
+
- t/skin/t_tmpl_read/read.html
|
267
273
|
- t/t.rb
|
268
274
|
- t/test_bike.rb
|
269
275
|
- t/test_call.rb
|