runo 0.1.1 → 0.1.2

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.
@@ -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