runo 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. data/README.rdoc +1 -118
  2. data/bin/runo +4 -29
  3. data/lib/dummy.rb +0 -0
  4. metadata +12 -278
  5. data/lib/_error.rb +0 -14
  6. data/lib/_field.rb +0 -260
  7. data/lib/_i18n.rb +0 -144
  8. data/lib/_parser.rb +0 -256
  9. data/lib/_path.rb +0 -86
  10. data/lib/_storage/_storage.rb +0 -215
  11. data/lib/_storage/file.rb +0 -201
  12. data/lib/_storage/sequel.rb +0 -174
  13. data/lib/_storage/temp.rb +0 -73
  14. data/lib/_widget/action_create.rb +0 -23
  15. data/lib/_widget/action_login.rb +0 -22
  16. data/lib/_widget/action_signup.rb +0 -16
  17. data/lib/_widget/action_update.rb +0 -16
  18. data/lib/_widget/crumb.rb +0 -24
  19. data/lib/_widget/done.rb +0 -16
  20. data/lib/_widget/login.rb +0 -25
  21. data/lib/_widget/me.rb +0 -31
  22. data/lib/_widget/message.rb +0 -51
  23. data/lib/_widget/navi.rb +0 -88
  24. data/lib/_widget/submit.rb +0 -49
  25. data/lib/_widget/view_ym.rb +0 -77
  26. data/lib/_workflow/_workflow.rb +0 -89
  27. data/lib/_workflow/attachment.rb +0 -50
  28. data/lib/_workflow/blog.rb +0 -28
  29. data/lib/_workflow/contact.rb +0 -23
  30. data/lib/_workflow/forum.rb +0 -26
  31. data/lib/_workflow/register.rb +0 -39
  32. data/lib/meta/_meta.rb +0 -20
  33. data/lib/meta/group.rb +0 -19
  34. data/lib/meta/id.rb +0 -59
  35. data/lib/meta/owner.rb +0 -21
  36. data/lib/meta/timestamp.rb +0 -118
  37. data/lib/runo.rb +0 -396
  38. data/lib/scalar/checkbox.rb +0 -68
  39. data/lib/scalar/file.rb +0 -144
  40. data/lib/scalar/img.rb +0 -112
  41. data/lib/scalar/password.rb +0 -58
  42. data/lib/scalar/radio.rb +0 -47
  43. data/lib/scalar/select.rb +0 -47
  44. data/lib/scalar/text.rb +0 -38
  45. data/lib/scalar/textarea.rb +0 -35
  46. data/lib/scalar/textarea_pre.rb +0 -14
  47. data/lib/scalar/textarea_wiki.rb +0 -173
  48. data/lib/set/_set.rb +0 -196
  49. data/lib/set/dynamic.rb +0 -177
  50. data/lib/set/static.rb +0 -102
  51. data/lib/set/static_folder.rb +0 -96
  52. data/locale/en/index.po +0 -242
  53. data/locale/index.pot +0 -243
  54. data/locale/ja/index.po +0 -242
  55. data/locale/lazy_parser.rb +0 -54
  56. data/skel/config.ru +0 -27
  57. data/skel/skin/_users/00000000_frank-avatar.jpg +0 -0
  58. data/skel/skin/_users/00000000_frank-avatar_small.jpg +0 -0
  59. data/skel/skin/_users/00000000_frank.yaml +0 -12
  60. data/skel/skin/_users/00000000_root-avatar.jpg +0 -0
  61. data/skel/skin/_users/00000000_root-avatar_small.jpg +0 -0
  62. data/skel/skin/_users/00000000_root.yaml +0 -11
  63. data/skel/skin/_users/css/users.css +0 -21
  64. data/skel/skin/_users/css/users.less +0 -25
  65. data/skel/skin/_users/done.html +0 -42
  66. data/skel/skin/_users/index.html +0 -46
  67. data/skel/skin/_users/index.yaml +0 -3
  68. data/skel/skin/_users/summary.html +0 -40
  69. data/skel/skin/css/base.css +0 -93
  70. data/skel/skin/css/base.less +0 -139
  71. data/skel/skin/css/coax.css +0 -199
  72. data/skel/skin/css/coax.less +0 -244
  73. data/skel/skin/examples/blog/20091214_0001.yaml +0 -8
  74. data/skel/skin/examples/blog/20100630_0001.yaml +0 -8
  75. data/skel/skin/examples/blog/20100630_0002.yaml +0 -14
  76. data/skel/skin/examples/blog/20100701_0001.yaml +0 -8
  77. data/skel/skin/examples/blog/20100701_0002-a-20100701_0001-f.jpg +0 -0
  78. data/skel/skin/examples/blog/20100701_0002-a-20100701_0001-f_small.jpg +0 -0
  79. data/skel/skin/examples/blog/20100701_0002.yaml +0 -19
  80. data/skel/skin/examples/blog/frank/20100701_0001.yaml +0 -10
  81. data/skel/skin/examples/blog/frank/index.yaml +0 -4
  82. data/skel/skin/examples/blog/index.html +0 -51
  83. data/skel/skin/examples/blog/rss.xml +0 -18
  84. data/skel/skin/examples/contact/20100701_0001-file.txt +0 -1
  85. data/skel/skin/examples/contact/20100701_0001.yaml +0 -15
  86. data/skel/skin/examples/contact/20100701_0002.yaml +0 -8
  87. data/skel/skin/examples/contact/20100701_0003.yaml +0 -9
  88. data/skel/skin/examples/contact/index.html +0 -47
  89. data/skel/skin/examples/contact/js/contact.js +0 -13
  90. data/skel/skin/examples/contact/summary.html +0 -54
  91. data/skel/skin/examples/forum/20100701_0001.yaml +0 -41
  92. data/skel/skin/examples/forum/20100701_0002.yaml +0 -25
  93. data/skel/skin/examples/forum/index.html +0 -68
  94. data/skel/skin/examples/forum/summary.html +0 -47
  95. data/skel/skin/examples/index.html +0 -73
  96. data/skel/skin/index.html +0 -39
  97. data/skel/skin/js/base.js +0 -50
  98. data/t/locale/de/index.po +0 -19
  99. data/t/locale/en-GB/index.po +0 -25
  100. data/t/locale/ja/index.po +0 -30
  101. data/t/skin/_users/00000000_test.yaml +0 -3
  102. data/t/skin/_users/index.html +0 -13
  103. data/t/skin/foo/20091120_0001.yaml +0 -7
  104. data/t/skin/foo/bar/20091120_0001.yaml +0 -5
  105. data/t/skin/foo/bar/index.yaml +0 -5
  106. data/t/skin/foo/baz/css/baz.css +0 -1
  107. data/t/skin/foo/css/foo.css +0 -1
  108. data/t/skin/foo/index.html +0 -14
  109. data/t/skin/foo/index.yaml +0 -7
  110. data/t/skin/foo/not_css/foo.css +0 -1
  111. data/t/skin/foo/qux/index.html +0 -8
  112. data/t/skin/foo/qux/moo/index.html +0 -6
  113. data/t/skin/foo/sub-20100306_0001.yaml +0 -3
  114. data/t/skin/index.yaml +0 -3
  115. data/t/skin/t_attachment/index.html +0 -13
  116. data/t/skin/t_contact/done.html +0 -6
  117. data/t/skin/t_contact/index.html +0 -9
  118. data/t/skin/t_file/index.html +0 -16
  119. data/t/skin/t_img/index.html +0 -14
  120. data/t/skin/t_img/test.jpg +0 -0
  121. data/t/skin/t_select/index.html +0 -9
  122. data/t/skin/t_store/index.html +0 -9
  123. data/t/skin/t_summary/20100326_0001.yaml +0 -3
  124. data/t/skin/t_summary/create.html +0 -9
  125. data/t/skin/t_summary/index.html +0 -9
  126. data/t/skin/t_summary/summary.html +0 -9
  127. data/t/t.rb +0 -27
  128. data/t/test_checkbox.rb +0 -273
  129. data/t/test_field.rb +0 -330
  130. data/t/test_file.rb +0 -900
  131. data/t/test_id.rb +0 -215
  132. data/t/test_img.rb +0 -328
  133. data/t/test_meta.rb +0 -57
  134. data/t/test_parser.rb +0 -1516
  135. data/t/test_password.rb +0 -188
  136. data/t/test_radio.rb +0 -226
  137. data/t/test_role.rb +0 -249
  138. data/t/test_runo.rb +0 -768
  139. data/t/test_runo_call.rb +0 -1281
  140. data/t/test_runo_i18n.rb +0 -325
  141. data/t/test_select.rb +0 -182
  142. data/t/test_set_complex.rb +0 -527
  143. data/t/test_set_dynamic.rb +0 -1504
  144. data/t/test_set_folder.rb +0 -515
  145. data/t/test_set_permit.rb +0 -246
  146. data/t/test_set_static.rb +0 -468
  147. data/t/test_storage.rb +0 -915
  148. data/t/test_text.rb +0 -125
  149. data/t/test_textarea.rb +0 -138
  150. data/t/test_timestamp.rb +0 -473
  151. data/t/test_workflow.rb +0 -367
@@ -1,86 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- # Author:: Akira FUNAI
4
- # Copyright:: Copyright (c) 2009 Akira FUNAI
5
-
6
- module Runo::Path
7
-
8
- module_function
9
-
10
- def tid_of(path)
11
- path[Runo::REX::TID]
12
- end
13
-
14
- def steps_of(path)
15
- _dirname(path).gsub(Runo::REX::PATH_ID, '').split('/').select {|step_or_cond|
16
- step_or_cond != '' &&
17
- step_or_cond !~ Regexp.union(Runo::REX::COND, Runo::REX::COND_D, Runo::REX::TID)
18
- }
19
- end
20
-
21
- def base_of(path)
22
- base = Runo::Set::Static::Folder.root.item steps_of(path)
23
- if base.is_a? Runo::Set::Static::Folder
24
- base.item('main') || base.find {|item| item.is_a? Runo::Set::Dynamic } || base
25
- else
26
- base
27
- end
28
- end
29
-
30
- def conds_of(path)
31
- dir = _dirname path.gsub(Runo::REX::PATH_ID, '')
32
- conds = $& ? {:id => sprintf('%.8d_%.4d', $1, $2)} : {}
33
-
34
- dir.split('/').inject(conds) {|conds, step_or_cond|
35
- if step_or_cond =~ Runo::REX::COND
36
- conds[$1.intern] = $2
37
- elsif step_or_cond =~ Runo::REX::COND_D
38
- conds[:d] = $&
39
- end
40
- conds
41
- }
42
- end
43
-
44
- def action_of(path)
45
- a = _basename(path).to_s[/^[a-z]+/]
46
- a.intern if a && a != 'index'
47
- end
48
-
49
- def sub_action_of(path)
50
- a = _basename(path).to_s[/_([a-z]+)/, 1]
51
- a.intern if a
52
- end
53
-
54
- def path_of(conds)
55
- conds = {} unless conds.is_a? ::Hash
56
- (
57
- (conds.keys - [:order, :p, :id]) |
58
- ([:order, :p, :id] & conds.keys)
59
- ).collect {|cid|
60
- if cid == :id
61
- ids = Array(conds[:id]).collect {|id|
62
- (id =~ /_(#{Runo::REX::ID_SHORT})$/) ? $1 : (id if Runo::REX::ID)
63
- }.compact
64
- if (ids.size == 1) && (ids.first =~ Runo::REX::ID)
65
- '%s/%d/' % [$1, $2.to_i]
66
- elsif ids.size > 0
67
- "id=#{ids.join ','}/"
68
- end
69
- elsif cid == :d
70
- conds[:id] ? '' : "#{conds[:d]}/"
71
- else
72
- "#{cid}=#{Array(conds[cid]).join ','}/"
73
- end
74
- }.join.sub(%r{/p=1/$}, '/')
75
- end
76
-
77
- def _dirname(path) # returns '/foo/bar/' for '/foo/bar/'
78
- path[%r{^.*/}] || ''
79
- end
80
-
81
- def _basename(path) # returns nil for '/foo/bar/'
82
- path[%r{[^/]+$}]
83
- end
84
-
85
- end
86
-
@@ -1,215 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- # Author:: Akira FUNAI
4
- # Copyright:: Copyright (c) 2009 Akira FUNAI
5
-
6
- class Runo::Storage
7
-
8
- def self.instance(sd)
9
- if folder = sd[:folder]
10
- if folder != sd[:parent]
11
- Temp.new sd
12
- else
13
- klass = Runo['storage']['default'].capitalize
14
- self.const_get(klass).new sd
15
- end
16
- else
17
- Temp.new sd
18
- end
19
- end
20
-
21
- def self.available?
22
- false
23
- end
24
-
25
- attr_reader :sd
26
-
27
- def initialize(sd)
28
- @sd = sd
29
- end
30
-
31
- def persistent?
32
- true
33
- end
34
-
35
- def order
36
- @sd[:order]
37
- end
38
-
39
- def select(conds = {})
40
- _cast conds
41
- item_ids = _select(conds)
42
- item_ids = _sort(item_ids, conds)
43
- item_ids = _page(item_ids, conds)
44
- ((conds[:order] || order) =~ /^-/) ? item_ids.reverse : item_ids
45
- end
46
-
47
- def build(v)
48
- self
49
- end
50
-
51
- def clear
52
- self
53
- end
54
-
55
- def store(id, v)
56
- id
57
- end
58
-
59
- def delete(id)
60
- id
61
- end
62
-
63
- def navi(conds)
64
- conds[:p] = '1' unless conds[:p] || conds[:id] || (@sd[:p_size].to_i < 1)
65
- navi = {}
66
- (([:id, :p, :d] & conds.keys) | conds.keys).each {|cid|
67
- next unless conds[cid] && respond_to?("_sibs_#{cid}", true)
68
- sibs = __send__("_sibs_#{cid}", conds)
69
-
70
- c = (c.is_a?(::Array) && c.size < 2) ? conds[cid].first : conds[cid]
71
- if i = sibs.index(c)
72
- if !navi[:prev] && i > 0
73
- navi[:prev] = conds.merge(cid => sibs[i - 1])
74
- if ![:id, :p].include? cid
75
- navi[:prev][:id] = _select_without(:id, navi[:prev]).last if conds[:id]
76
- navi[:prev][:p] = _p_count(navi[:prev]).to_s if conds[:p]
77
- end
78
- end
79
- if !navi[:next] && i < (sibs.size - 1)
80
- navi[:next] = conds.merge(cid => sibs[i + 1])
81
- if ![:id, :p].include? cid
82
- navi[:next][:id] = _select_without(:id, navi[:next]).first if conds[:id]
83
- navi[:next][:p] = '1' if conds[:p]
84
- end
85
- end
86
- end
87
- navi[:sibs] ||= {cid => sibs} if navi[:prev] || navi[:next]
88
-
89
- break if navi[:prev] && navi[:next]
90
- }
91
-
92
- navi
93
- end
94
-
95
- def last(cid, conds)
96
- __send__("_sibs_#{cid}", conds).last
97
- end
98
-
99
- private
100
-
101
- def _cast(conds)
102
- ([:d, :id, :p] & conds.keys).each {|cid|
103
- case cid
104
- when :d
105
- conds[:d] = conds[:d].first if conds[:d].is_a? ::Array
106
- conds[:d] = conds[:d].to_s
107
- conds[:d] = last(:d, conds) if conds[:d] =~ /9999(99)?(99)?/
108
- conds[:d] = nil unless conds[:d] =~ Runo::REX::COND_D
109
- when :id
110
- conds[:id] = Array(conds[:id]).collect {|id|
111
- case id
112
- when '99999999_9999', 'last'
113
- last(:id, conds)
114
- when /\A#{Runo::REX::ID_SHORT}\z/
115
- "00000000_#{id}"
116
- when Runo::REX::ID, Runo::REX::ID_NEW
117
- id
118
- end
119
- }.uniq.compact
120
- when :p
121
- conds[:p] = conds[:p].first if conds[:p].is_a? ::Array
122
- conds[:p] = conds[:p].to_s
123
- conds[:p] = last(:p, conds) if conds[:p] == 'last'
124
- conds[:p] = nil unless conds[:p] =~ /^\d+$/
125
- end
126
- }
127
- conds
128
- end
129
-
130
- def _select(conds)
131
- if conds[:id]
132
- _select_by_id(conds) | (@sd.instance_variable_get(:@item_object).keys & Array(conds[:id]))
133
- elsif cid = (conds.keys - [:order, :p]).first
134
- m = "_select_by_#{cid}"
135
- respond_to?(m, true) ? __send__(m, conds) : []
136
- else
137
- _select_all(conds) | @sd.instance_variable_get(:@item_object).keys
138
- end
139
- end
140
-
141
- def _sort(item_ids, conds)
142
- item_ids.sort
143
- end
144
-
145
- def _page(item_ids, conds)
146
- size = @sd[:p_size].to_i
147
- return item_ids if size < 1
148
-
149
- page = conds[:p].to_i
150
- page = 1 if page < 1
151
- Array item_ids[(page - 1) * size, size]
152
- end
153
-
154
- def _sibs_id(conds)
155
- _select_without(:id, conds)
156
- end
157
-
158
- def _sibs_p(conds)
159
- p_count = _p_count(conds)
160
- p_count ? (1..p_count).collect {|i| i.to_s } : []
161
- end
162
-
163
- def _sibs_d(conds)
164
- rex_d = /^\d{#{conds[:d].length}}/
165
- _select_without(:id, :p, :d, conds).collect {|id| id[rex_d] }.uniq.compact
166
- end
167
-
168
- def _select_without(*cids)
169
- conds = cids.pop.dup
170
- cids.each {|cid| conds.delete cid }
171
- _sort(_select(conds), conds)
172
- end
173
-
174
- def _p_count(conds)
175
- (_select_without(:id, :p, conds).size / @sd[:p_size].to_f).ceil unless @sd[:p_size].to_f == 0
176
- end
177
-
178
- def cast_ids(ids)
179
- Array(ids).collect {|i|
180
- id = (i =~ /^[a-z]/) ? "00000000_#{i}" : i
181
- id if id =~ Runo::REX::ID
182
- }.compact
183
- end
184
-
185
- def new_id(v = {})
186
- return "00000000_#{v['_id']}" if v.is_a?(::Hash) && v['_id'] =~ /\A#{Runo::REX::ID_SHORT}\z/
187
-
188
- if v.is_a?(::Hash) && v['_timestamp'] && v['_timestamp']['published'].is_a?(::Time)
189
- d = v['_timestamp']['published'].strftime '%Y%m%d'
190
- else
191
- d = Time.now.strftime '%Y%m%d'
192
- end
193
- if max_in_d = _select(:d => d).sort.last
194
- max_in_d.succ
195
- else
196
- d + '_0001'
197
- end
198
- end
199
-
200
- def new_id?(id, v)
201
- if id == :new_id
202
- true
203
- elsif !v.is_a?(::Hash)
204
- false
205
- elsif id =~ /_#{Runo::REX::ID_SHORT}\z/
206
- v['_id'] =~ /\A#{Runo::REX::ID_SHORT}\z/ &&
207
- id != new_id(v)
208
- else
209
- v['_timestamp'] &&
210
- v['_timestamp']['published'].is_a?(::Time) &&
211
- id !~ /\A#{v['_timestamp']['published'].strftime('%Y%m%d')}/
212
- end
213
- end
214
-
215
- end
@@ -1,201 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- # Author:: Akira FUNAI
4
- # Copyright:: Copyright (c) 2009 Akira FUNAI
5
-
6
- require 'rubygems'
7
- require 'yaml'
8
- require 'ya2yaml'
9
- require 'fileutils'
10
-
11
- class Runo::Storage::File < Runo::Storage
12
-
13
- def self.traverse(dir = '/', root = Runo['storage']['File']['data_dir'], &block)
14
- ::Dir.glob(::File.join(root, dir, '*')).sort.collect {|file|
15
- ftype = ::File.ftype file
16
- base_name = ::File.basename file
17
- id, ext = base_name.split('.', 2)
18
- id = "main-#{id}" if id =~ Runo::REX::ID
19
- full_name = ::File.join(dir, id).gsub(::File::SEPARATOR, '-')
20
-
21
- if ftype == 'file' && id.sub(/^([^\d\-]+-)+/, '') =~ Runo::REX::ID
22
- val = nil
23
- ::File.open(file, 'r') {|f|
24
- f.flock ::File::LOCK_SH
25
- f.binmode
26
- val = f.read
27
- f.flock ::File::LOCK_UN
28
- }
29
- block.call(
30
- :dir => dir,
31
- :base_name => base_name,
32
- :full_name => full_name,
33
- :ext => ext,
34
- :val => (ext == 'yaml' ? YAML.load(val) : val)
35
- )
36
- elsif ftype == 'directory' && base_name !~ /\A#{Runo::REX::DIR_STATIC}\z/
37
- self.traverse(::File.join(dir, base_name), root, &block)
38
- end
39
- }.compact.flatten
40
- end
41
-
42
- def self.load_skel
43
- self.traverse('/', Runo['skin_dir']) {|entry|
44
- dir = ::File.join(Runo['storage']['File']['data_dir'], entry[:dir])
45
- unless ::File.exists? ::File.join(dir, entry[:base_name])
46
- ::FileUtils.mkpath(dir) unless ::File.directory? dir
47
- ::FileUtils.cp(
48
- ::File.join(Runo['skin_dir'], entry[:dir], entry[:base_name]),
49
- ::File.join(dir, entry[:base_name]),
50
- {:preserve => true}
51
- )
52
- end
53
- }
54
- end
55
-
56
- def self.available?
57
- Runo['storage']['File'] && Runo['storage']['File']['data_dir']
58
- end
59
-
60
- def initialize(sd)
61
- super
62
- unless @@loaded ||= false
63
- entries = ::Dir.glob ::File.join(Runo['storage']['File']['data_dir'], '*')
64
- self.class.load_skel if entries.empty?
65
- @@loaded = true
66
- end
67
- @dir = ::File.join(Runo['storage']['File']['data_dir'], @sd[:folder][:dir])
68
- ::FileUtils.mkpath(@dir) unless ::File.directory? @dir
69
- end
70
-
71
- def val(id = nil)
72
- if id
73
- load id
74
- else
75
- # this could be HUGE.
76
- _select_all({}).inject({}) {|v, id|
77
- v[id] = load id
78
- v
79
- }
80
- end
81
- end
82
-
83
- def build(v)
84
- clear
85
- v.each {|id, v| store(id, v) }
86
- self
87
- end
88
-
89
- def clear
90
- glob.each {|file| ::File.unlink ::File.join(@dir, file) }
91
- self
92
- end
93
-
94
- def store(id, v, ext = nil)
95
- save(id, v, ext)
96
- end
97
-
98
- def delete(id)
99
- remove_file(id) && id
100
- end
101
-
102
- def move(old_id, new_id)
103
- rename_file(old_id, new_id) && new_id
104
- end
105
-
106
- private
107
-
108
- def _select_by_id(conds)
109
- glob(Array(conds[:id])).collect {|f| f[/\d.*/][Runo::REX::ID] }.compact
110
- end
111
-
112
- def _select_by_d(conds)
113
- glob(conds[:d].to_s).collect {|f| f[/\.yaml$/] && f[/\d.*/][Runo::REX::ID] }.compact
114
- end
115
-
116
- def _select_all(conds)
117
- glob.collect {|f| f[/\.yaml$/] && f[/\d.*/][Runo::REX::ID] }.compact
118
- end
119
-
120
- def glob(id = :all)
121
- glob_pattern = "#{file_prefix}#{pattern_for id}.[a-z]*"
122
- ::Dir.chdir(@dir) { ::Dir.glob glob_pattern }
123
- end
124
-
125
- def file_prefix
126
- (@sd[:name] == 'main') ? '' : @sd[:name].sub(/^main-/, '') + '-'
127
- end
128
-
129
- def pattern_for(id)
130
- if id.is_a? Array
131
- "{#{id.join ','}}"
132
- elsif id == :all
133
- '[0-9]*_*'
134
- elsif id =~ /\A\d{4,8}\z/
135
- "#{id}*"
136
- end
137
- end
138
-
139
- def load(id)
140
- v = nil
141
- file = glob(Array(id)).sort.first
142
- ::File.open(::File.join(@dir, file), 'r') {|f|
143
- f.flock ::File::LOCK_SH
144
- f.binmode
145
- v = f.read
146
- f.flock ::File::LOCK_UN
147
- } if file
148
- (file[/\.yaml$/] ? YAML.load(v) : v) if v
149
- end
150
-
151
- def save(id, v, ext)
152
- if new_id?(id, v)
153
- old_id = id
154
- id = new_id v
155
- end
156
-
157
- if ext
158
- val = v
159
- ext = 'y' if ext == 'yaml'
160
- remove_file id
161
- else
162
- val = v.ya2yaml(:syck_compatible => true)
163
- ext = 'yaml'
164
- end
165
-
166
- file = "#{file_prefix}#{id}.#{ext}"
167
- if old_id && f = ::File.open(::File.join(@dir, file), 'a')
168
- f.seek(0, IO::SEEK_END)
169
- return if f.pos != 0 # duplicate id
170
- move(old_id, id) unless old_id == :new_id
171
- end
172
- ::File.open(::File.join(@dir, file), 'a') {|f|
173
- f.flock ::File::LOCK_EX
174
- f.binmode
175
- f.seek 0
176
- f.truncate 0
177
- f << val
178
- f.flock ::File::LOCK_UN
179
- f.chmod 0664
180
- } && id
181
- end
182
-
183
- def remove_file(id)
184
- glob_pattern = "#{file_prefix}#{pattern_for Array(id)}[.-]*"
185
- files = ::Dir.chdir(@dir) { ::Dir.glob glob_pattern } # may include child files
186
- files.each {|file|
187
- ::File.unlink ::File.join(@dir, file)
188
- }
189
- end
190
-
191
- def rename_file(old_id, new_id)
192
- glob_pattern = "#{file_prefix}#{pattern_for Array(old_id)}*"
193
- files = ::Dir.chdir(@dir) { ::Dir.glob glob_pattern } # may include child files
194
- rex = /^\A#{file_prefix}#{old_id}/
195
- files.each {|file|
196
- to_file = file.sub(rex, "#{file_prefix}#{new_id}")
197
- ::File.rename(::File.join(@dir, file), ::File.join(@dir, to_file))
198
- }
199
- end
200
-
201
- end