runo 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -86,7 +86,7 @@ module Runo::Parser
86
86
  s = StringScanner.new html
87
87
  until s.eos?
88
88
  if s.scan /\$\((\w+)(?:\s+|\s*=\s*)([\w\-]+)\s*/m
89
- out << block.call(s[1], {:klass => s[2]}.merge(scan_tokens s))
89
+ out << block.call(s[1], {:klass => s[2]}.merge(scan_tokens(s)))
90
90
  else
91
91
  out << s.scan(/.+?(?=\$|\w|<|\z)/m)
92
92
  end
@@ -180,7 +180,7 @@ module Runo::Parser
180
180
  'default' => item_meta,
181
181
  },
182
182
  }
183
- (inner_html =~ /\A\s*<!--(.+?)-->/m) ? sd.merge(scan_tokens StringScanner.new($1)) : sd
183
+ (inner_html =~ /\A\s*<!--(.+?)-->/m) ? sd.merge(scan_tokens(StringScanner.new($1))) : sd
184
184
  end
185
185
 
186
186
  def parse_token(prefix, token, meta = {})
@@ -19,9 +19,9 @@ module Runo::Path
19
19
  end
20
20
 
21
21
  def base_of(path)
22
- base = Runo::Set::Static::Folder.root.item(steps_of path)
22
+ base = Runo::Set::Static::Folder.root.item steps_of(path)
23
23
  if base.is_a? Runo::Set::Static::Folder
24
- base.item 'main'
24
+ base.item('main') || base.find {|item| item.is_a? Runo::Set::Dynamic } || base
25
25
  else
26
26
  base
27
27
  end
@@ -11,7 +11,7 @@ require 'fileutils'
11
11
  class Runo::Storage::File < Runo::Storage
12
12
 
13
13
  def self.traverse(dir = '/', root = Runo['storage']['File']['data_dir'], &block)
14
- ::Dir.glob(::File.join root, dir, '*').sort.collect {|file|
14
+ ::Dir.glob(::File.join(root, dir, '*')).sort.collect {|file|
15
15
  ftype = ::File.ftype file
16
16
  base_name = ::File.basename file
17
17
  id, ext = base_name.split('.', 2)
@@ -76,7 +76,7 @@ class Runo::Storage::Sequel < Runo::Storage
76
76
  end
77
77
 
78
78
  def delete(id)
79
- @dataset.filter(_conds id).delete &&
79
+ @dataset.filter(_conds(id)).delete &&
80
80
  @dataset.grep(:full_name, _full_name("#{id}-%")).and(~:ext => 'yaml').delete &&
81
81
  id
82
82
  end
@@ -88,7 +88,7 @@ class Runo::Storage::Sequel < Runo::Storage
88
88
  private
89
89
 
90
90
  def _select_by_id(conds)
91
- @dataset.filter(_conds conds[:id]).collect {|v| _id v[:full_name] }
91
+ @dataset.filter(_conds(conds[:id])).collect {|v| _id v[:full_name] }
92
92
  end
93
93
 
94
94
  def _select_by_d(conds)
@@ -36,7 +36,7 @@ _html
36
36
 
37
37
  def _g_submit_preview_delete(arg)
38
38
  if (
39
- permit_get?(arg.merge :action => :delete) &&
39
+ permit_get?(arg.merge(:action => :delete)) &&
40
40
  collect_item(arg[:conds]).find {|item| item[:id] !~ Runo::REX::ID_NEW } &&
41
41
  arg[:orig_action] != :preview
42
42
  )
@@ -16,7 +16,7 @@ class Runo::Meta::Id < Runo::Field
16
16
  if (my[:max].to_i > 0) && (val.size > my[:max])
17
17
  [_('too long: %{max} characters maximum') % {:max => my[:max]}]
18
18
  elsif (my[:min].to_i == 1) && val.empty?
19
- [_ 'mandatory']
19
+ [_('mandatory')]
20
20
  elsif (my[:min].to_i > 0) && (val.size < my[:min])
21
21
  [_('too short: %{min} characters minimum') % {:min => my[:min]}]
22
22
  elsif val !~ /\A#{Runo::REX::ID_SHORT}\z/
@@ -48,7 +48,7 @@ class Runo::Meta::Timestamp < Runo::Field
48
48
  end
49
49
 
50
50
  def _date(time)
51
- time.is_a?(::Time) ? time.strftime(_ '%Y-%m-%dT%H:%M:%S') : 'n/a'
51
+ time.is_a?(::Time) ? time.strftime(_('%Y-%m-%dT%H:%M:%S')) : 'n/a'
52
52
  end
53
53
 
54
54
  def _g_create(arg)
@@ -110,7 +110,7 @@ class Runo
110
110
  Runo.current[:session] = env['rack.session']
111
111
 
112
112
  if Runo.transaction[tid].is_a? Runo::Field
113
- base = Runo.transaction[tid].item(Runo::Path.steps_of path.sub(/\A.*#{Runo::REX::TID}/, ''))
113
+ base = Runo.transaction[tid].item Runo::Path.steps_of(path.sub(/\A.*#{Runo::REX::TID}/, ''))
114
114
  else
115
115
  base = Runo::Path.base_of path
116
116
  end
@@ -271,10 +271,10 @@ class Runo
271
271
  :action => Runo::Path.action_of(req.path_info),
272
272
  :sub_action => Runo::Path.sub_action_of(req.path_info),
273
273
  }
274
- params.merge!(rebuild_params req.params)
274
+ params.merge! rebuild_params(req.params)
275
275
 
276
276
  params[:conds] ||= {}
277
- params[:conds].merge!(Runo::Path.conds_of req.path_info)
277
+ params[:conds].merge! Runo::Path.conds_of(req.path_info)
278
278
 
279
279
  params
280
280
  end
@@ -19,9 +19,9 @@ class Runo::Checkbox < Runo::Field
19
19
 
20
20
  def errors
21
21
  if val.empty?
22
- my[:mandatory] ? [_ 'mandatory'] : []
22
+ my[:mandatory] ? [_('mandatory')] : []
23
23
  else
24
- (val - my[:options]).empty? ? [] : [_ 'no such option']
24
+ (val - my[:options]).empty? ? [] : [_('no such option')]
25
25
  end
26
26
  end
27
27
 
@@ -54,7 +54,7 @@ class Runo::File < Runo::Field
54
54
  elsif (my[:max].to_i > 0) && (val['size'].to_i > my[:max])
55
55
  [_('too large: %{max} bytes maximum') % {:max => my[:max]}]
56
56
  elsif (my[:min].to_i == 1) && val['size'].to_i < 1
57
- [_ 'mandatory']
57
+ [_('mandatory')]
58
58
  elsif (my[:min].to_i > 0) && (val['size'].to_i < my[:min])
59
59
  [_('too small: %{min} bytes minimum') % {:min => my[:min]}]
60
60
  else
@@ -82,7 +82,7 @@ _html
82
82
  end
83
83
 
84
84
  def _g_thumbnail(arg = {})
85
- _g_default(arg.merge :sub_action => :without_link)
85
+ _g_default arg.merge(:sub_action => :without_link)
86
86
  end
87
87
 
88
88
  def _thumbnail(tempfile)
@@ -16,7 +16,7 @@ class Runo::Password < Runo::Field
16
16
  elsif (my[:max].to_i > 0) && (@size > my[:max])
17
17
  [_('too long: %{max} characters maximum') % {:max => my[:max]}]
18
18
  elsif (my[:min].to_i == 1) && (@size == 0)
19
- [_ 'mandatory']
19
+ [_('mandatory')]
20
20
  elsif (my[:min].to_i > 0) && (@size < my[:min])
21
21
  [_('too short: %{min} characters minimum') % {:min => my[:min]}]
22
22
  else
@@ -44,7 +44,7 @@ _html
44
44
  @val = v
45
45
  when :create, :update
46
46
  if v.is_a?(::String) && !v.empty?
47
- salt = ('a'..'z').to_a[rand 26] + ('a'..'z').to_a[rand 26]
47
+ salt = ('a'..'z').to_a[rand(26)] + ('a'..'z').to_a[rand(26)]
48
48
  @size = v.size
49
49
  @val = v.crypt salt
50
50
  elsif @val.nil?
@@ -13,9 +13,9 @@ class Runo::Radio < Runo::Field
13
13
 
14
14
  def errors
15
15
  if val.empty?
16
- my[:mandatory] ? [_ 'mandatory'] : []
16
+ my[:mandatory] ? [_('mandatory')] : []
17
17
  else
18
- my[:options].include?(val) ? [] : [_ 'no such option']
18
+ my[:options].include?(val) ? [] : [_('no such option')]
19
19
  end
20
20
  end
21
21
 
@@ -13,11 +13,11 @@ class Runo::Select < Runo::Field
13
13
 
14
14
  def errors
15
15
  if my[:mandatory] && val.empty?
16
- [_ 'mandatory']
16
+ [_('mandatory')]
17
17
  elsif my[:options].include?(val) || val.empty?
18
18
  []
19
19
  else
20
- [_ 'no such option']
20
+ [_('no such option')]
21
21
  end
22
22
  end
23
23
 
@@ -14,7 +14,7 @@ class Runo::Text < Runo::Field
14
14
  if (my[:max].to_i > 0) && (val.size > my[:max])
15
15
  [_('too long: %{max} characters maximum') % {:max => my[:max]}]
16
16
  elsif (my[:min].to_i == 1) && val.empty?
17
- [_ 'mandatory']
17
+ [_('mandatory')]
18
18
  elsif (my[:min].to_i > 0) && (val.size < my[:min])
19
19
  [_('too short: %{min} characters minimum') % {:min => my[:min]}]
20
20
  else
@@ -9,7 +9,7 @@ class Runo::Textarea < Runo::Field
9
9
  if (my[:max].to_i > 0) && (val.size > my[:max])
10
10
  [_('too long: %{max} characters maximum') % {:max => my[:max]}]
11
11
  elsif (my[:min].to_i == 1) && val.empty?
12
- [_ 'mandatory']
12
+ [_('mandatory')]
13
13
  elsif (my[:min].to_i > 0) && (val.size < my[:min])
14
14
  [_('too short: %{min} characters minimum') % {:min => my[:min]}]
15
15
  else
@@ -168,7 +168,7 @@ _html
168
168
  if id[Runo::REX::ID_NEW]
169
169
  @item_object[id].load_default
170
170
  else
171
- @item_object[id].load(@storage.val id)
171
+ @item_object[id].load @storage.val(id)
172
172
  end
173
173
  end
174
174
  @item_object[id]
@@ -11,7 +11,7 @@ class Runo::Set::Static < Runo::Field
11
11
 
12
12
  def initialize(meta = {})
13
13
  @meta = meta
14
- @meta.merge!(Runo::Parser.parse_html meta[:html]) if meta[:html]
14
+ @meta.merge!(Runo::Parser.parse_html(meta[:html])) if meta[:html]
15
15
  @meta[:item] ||= {}
16
16
  @item_object = {}
17
17
  end
@@ -87,7 +87,7 @@ _html
87
87
  def collect_item(conds = {}, &block)
88
88
  items = my[:item].keys
89
89
  items &= conds[:id].to_a if conds[:id] # select item(s) by id
90
- items.collect {|id|
90
+ items.sort.collect {|id|
91
91
  item = @item_object[id] ||= Runo::Field.instance(
92
92
  my[:item][id].merge(:id => id, :parent => self)
93
93
  )
@@ -14,11 +14,11 @@ class Runo::Set::Static::Folder < Runo::Set::Static
14
14
  meta[:html] = load_html(meta[:dir], meta[:parent])
15
15
  super
16
16
 
17
- ::Dir.glob(::File.join Runo['skin_dir'], my[:html_dir].to_s, '*.html').each {|f|
17
+ ::Dir.glob(::File.join(Runo['skin_dir'], my[:html_dir].to_s, '*.html')).each {|f|
18
18
  action = ::File.basename(f, '.*').intern
19
19
  merge_tmpl(@meta, Runo::Parser.parse_html(::File.read(f), action)) if action != :index
20
20
  }
21
- ::Dir.glob(::File.join Runo['skin_dir'], my[:html_dir].to_s, '*.xml').each {|f|
21
+ ::Dir.glob(::File.join(Runo['skin_dir'], my[:html_dir].to_s, '*.xml')).each {|f|
22
22
  action = ::File.basename(f, '.*').intern
23
23
  merge_tmpl(@meta, Runo::Parser.parse_xml(::File.read(f), action)) if action != :index
24
24
  }
@@ -59,7 +59,7 @@ class Runo::Set::Static::Folder < Runo::Set::Static
59
59
  return sd.instance_eval { collect_item(conds, &block) }
60
60
  elsif (
61
61
  conds[:id] =~ /\A\w+\z/ &&
62
- ::File.directory?(::File.join Runo['skin_dir'], my[:dir], conds[:id])
62
+ ::File.directory?(::File.join(Runo['skin_dir'], my[:dir], conds[:id]))
63
63
  )
64
64
  my[:item][conds[:id]] = {:klass => 'set-static-folder'}
65
65
  end
@@ -61,8 +61,6 @@
61
61
  Everybody who logged in can create a new post, or reply to a existing post.
62
62
  </dd>
63
63
  </dl>
64
- <div id="main" class="app-blog"></div>
65
- <!-- $(main.action_create) -->
66
64
  </div>
67
65
 
68
66
  <div id="right" class="column">
@@ -27,8 +27,6 @@
27
27
  This is your homepage of the Runo app.<br />
28
28
  You can play with <a href="./examples/">the examples</a> before making your first Runo app.
29
29
  </p>
30
- <div id="main" class="app-blog"></div>
31
- <!-- $(main.action_create) -->
32
30
  </div>
33
31
 
34
32
  <div id="right" class="column">
@@ -0,0 +1,8 @@
1
+ <html>
2
+ <head><title>@(label)</title></head>
3
+ <body>
4
+ <h1>@(label)</h1>
5
+ <ul id="abc" class="app-blog"><li></li></ul>
6
+ <ul id="sub" class="app-blog"><li></li></ul>
7
+ </body>
8
+ </html>
@@ -0,0 +1,6 @@
1
+ <html>
2
+ <head><title>@(label)</title></head>
3
+ <body>
4
+ <p>moo!</p>
5
+ </body>
6
+ </html>
@@ -350,6 +350,18 @@ class TC_Runo < Test::Unit::TestCase
350
350
  "Runo::Path.base_of should return the item('main') if the given steps point at a folder"
351
351
  )
352
352
 
353
+ sd = Runo::Path.base_of '/foo/qux/index.html'
354
+ assert_instance_of(
355
+ Runo::Set::Dynamic,
356
+ sd,
357
+ "Runo::Path.base_of should return an available set_dynamic if there is no 'main' in the folder"
358
+ )
359
+ assert_equal(
360
+ '-foo-qux-abc',
361
+ sd[:full_name],
362
+ "Runo::Path.base_of should return the first set_dynamic if there is no 'main' in the folder"
363
+ )
364
+
353
365
  sd = Runo::Path.base_of '/foo/bar/20091120_0001/comment/index.html'
354
366
  assert_instance_of(
355
367
  Runo::Text,
@@ -376,6 +388,20 @@ class TC_Runo < Test::Unit::TestCase
376
388
  )
377
389
  end
378
390
 
391
+ def test_base_of_empty_folder
392
+ f = Runo::Path.base_of '/foo/qux/moo/index.html'
393
+ assert_instance_of(
394
+ Runo::Set::Static::Folder,
395
+ f,
396
+ 'Runo::Path.base_of should return an folder if there is no SD in it'
397
+ )
398
+ assert_equal(
399
+ '-foo-qux-moo',
400
+ f[:full_name],
401
+ 'Runo::Path.base_of should return an folder if there is no SD in it'
402
+ )
403
+ end
404
+
379
405
  def test_path_of
380
406
  assert_equal(
381
407
  '20091224/123/',
@@ -1136,29 +1136,24 @@ _html
1136
1136
  'Runo#call should return both the base path and tid at :done'
1137
1137
  )
1138
1138
 
1139
- tid = res.headers['Location'][Runo::REX::TID]
1140
- new_id = res.headers['Location'][Runo::REX::PATH_ID]
1139
+ location = res.headers['Location']
1140
+ location =~ Runo::REX::PATH_ID
1141
+ new_id = sprintf('%.8d_%.4d', $1, $2)
1141
1142
 
1142
- res = Rack::MockRequest.new(@runo).get(
1143
- res.headers['Location']
1144
- )
1143
+ res = Rack::MockRequest.new(@runo).get location
1145
1144
  assert_match(
1146
1145
  /created 1 entry\./,
1147
1146
  res.body,
1148
1147
  'Runo#call should include the current message'
1149
1148
  )
1150
1149
 
1151
- res = Rack::MockRequest.new(@runo).get(
1152
- "http://example.com/#{tid}/#{new_id}index.html"
1153
- )
1150
+ res = Rack::MockRequest.new(@runo).get location
1154
1151
  assert_no_match(
1155
1152
  /created 1 entry\./,
1156
1153
  res.body,
1157
1154
  'Runo#call should not include the message twice'
1158
1155
  )
1159
1156
 
1160
- res.headers['Location'] =~ Runo::REX::PATH_ID
1161
- new_id = sprintf('%.8d_%.4d', $1, $2)
1162
1157
  res = Rack::MockRequest.new(@runo).post(
1163
1158
  'http://example.com/t_store/main/update.html',
1164
1159
  {
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 1
9
- version: 0.1.1
8
+ - 2
9
+ version: 0.1.2
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-07-06 00:00:00 +09:00
17
+ date: 2010-07-10 00:00:00 +09:00
18
18
  default_executable: runo
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -247,6 +247,8 @@ files:
247
247
  - t/skin/foo/index.html
248
248
  - t/skin/foo/index.yaml
249
249
  - t/skin/foo/not_css/foo.css
250
+ - t/skin/foo/qux/index.html
251
+ - t/skin/foo/qux/moo/index.html
250
252
  - t/skin/foo/sub-20100306_0001.yaml
251
253
  - t/skin/index.yaml
252
254
  - t/skin/t_attachment/index.html