infod 0.0.2 → 0.0.3.0

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.
Files changed (83) hide show
  1. data/infod.rb +51 -12
  2. data/infod/{Th/404.rb → 404.rb} +4 -16
  3. data/infod/500.rb +53 -0
  4. data/infod/GET.rb +104 -0
  5. data/infod/HEAD.rb +23 -0
  6. data/infod/HTTP.rb +105 -0
  7. data/infod/{Th/PATCH.rb → PATCH.rb} +0 -0
  8. data/infod/POST.rb +34 -0
  9. data/infod/audio.rb +30 -0
  10. data/infod/blog.rb +34 -0
  11. data/infod/cal.rb +72 -0
  12. data/infod/{Es/code.rb → code.rb} +7 -4
  13. data/infod/constants.rb +55 -0
  14. data/infod/{Es/css.rb → css.rb} +0 -0
  15. data/infod/{Es/csv.rb → csv.rb} +0 -0
  16. data/infod/{Es/du.rb → du.rb} +0 -0
  17. data/infod/edit.rb +73 -0
  18. data/infod/{H/facets.rb → facets.rb} +20 -11
  19. data/infod/{Es/feed.rb → feed.rb} +17 -16
  20. data/infod/{Es/find.rb → find.rb} +2 -3
  21. data/infod/forum.rb +13 -0
  22. data/infod/{Es/fs.rb → fs.rb} +5 -2
  23. data/infod/glob.rb +26 -0
  24. data/infod/graph.rb +131 -0
  25. data/infod/{Es/grep.rb → grep.rb} +3 -3
  26. data/infod/{Es/groonga.rb → groonga.rb} +35 -26
  27. data/infod/{H/histogram.rb → histogram.rb} +23 -16
  28. data/infod/html.rb +231 -0
  29. data/infod/{Es/image.rb → image.rb} +16 -26
  30. data/infod/{Es/index.rb → index.rb} +44 -49
  31. data/infod/infod.rb +51 -12
  32. data/infod/json.rb +38 -0
  33. data/infod/{Es/kv.rb → kv.rb} +3 -9
  34. data/infod/{Y.rb → lambda.rb} +18 -1
  35. data/infod/ls.rb +49 -0
  36. data/infod/mail.rb +108 -0
  37. data/infod/{Es/man.rb → man.rb} +3 -15
  38. data/infod/{H/microblog.rb → microblog.rb} +22 -31
  39. data/infod/{K.rb → mime.rb} +68 -52
  40. data/infod/{N.rb → names.rb} +77 -56
  41. data/infod/page.rb +13 -0
  42. data/infod/postscript.rb +26 -0
  43. data/infod/rdf.rb +51 -0
  44. data/infod/{Rb.rb → ruby.rb} +18 -33
  45. data/infod/{Es/schema.rb → schema.rb} +23 -8
  46. data/infod/{Es/search.rb → search.rb} +5 -11
  47. data/infod/{Es/sh.rb → sh.rb} +0 -0
  48. data/infod/{Es/text.rb → text.rb} +33 -29
  49. data/infod/{H/threads.rb → threads.rb} +20 -27
  50. data/infod/{H/time.rb → time.rb} +14 -34
  51. data/infod/{H/wiki.rb → wiki.rb} +0 -0
  52. metadata +53 -64
  53. data/config.ru +0 -3
  54. data/infod/Es.rb +0 -31
  55. data/infod/Es/filter.rb +0 -75
  56. data/infod/Es/glob.rb +0 -22
  57. data/infod/Es/html.rb +0 -271
  58. data/infod/Es/in.rb +0 -68
  59. data/infod/Es/json.rb +0 -68
  60. data/infod/Es/ls.rb +0 -58
  61. data/infod/Es/mail.rb +0 -87
  62. data/infod/Es/mime.rb +0 -59
  63. data/infod/Es/out.rb +0 -52
  64. data/infod/Es/pager.rb +0 -34
  65. data/infod/Es/pdf.rb +0 -19
  66. data/infod/Es/rdf.rb +0 -35
  67. data/infod/H.rb +0 -15
  68. data/infod/H/audio.rb +0 -19
  69. data/infod/H/blog.rb +0 -15
  70. data/infod/H/cal.rb +0 -81
  71. data/infod/H/edit.rb +0 -88
  72. data/infod/H/forum.rb +0 -4
  73. data/infod/H/hf.rb +0 -114
  74. data/infod/H/mail.rb +0 -92
  75. data/infod/H/who.rb +0 -30
  76. data/infod/Th.rb +0 -36
  77. data/infod/Th/500.rb +0 -41
  78. data/infod/Th/GET.rb +0 -62
  79. data/infod/Th/HEAD.rb +0 -5
  80. data/infod/Th/POST.rb +0 -39
  81. data/infod/Th/perf.rb +0 -37
  82. data/infod/Th/uid.rb +0 -24
  83. data/infod/Th/util.rb +0 -89
data/infod/Es/rdf.rb DELETED
@@ -1,35 +0,0 @@
1
- #watch __FILE__
2
- class E
3
-
4
- def self.renderRDF d,f
5
- require 'linkeddata'
6
- (RDF::Writer.for f).buffer{|w|
7
- d.values.each{|r| r.triples{|s,p,o|
8
- s = RDF::URI s
9
- p = RDF::URI p
10
- o = ([E,Hash].member?(o.class) ? (RDF::URI o.uri) : (RDF::Literal o)) rescue nil
11
- (w << (RDF::Statement.new s,p,o) if o ) rescue nil
12
- }}}
13
- end
14
-
15
- def triplrRDF format=:rdfa, localFile=true ; require 'linkeddata'
16
- location = (localFile && f) ? d : uri
17
- puts [:RDF,location].join ' '
18
- RDF::Reader.open(location, :format => format){|r|
19
- r.each_triple{|s,p,o|
20
- yield s.to_s, p.to_s, [RDF::Node, RDF::URI].member?(o.class) ? E(o) : o.value.do{|v|v.class == String ? v.to_utf8 : v}}}
21
- end
22
-
23
- [['application/ld+json',:jsonld],
24
- ['application/json+ld',:jsonld],
25
- ['application/jsonld',:jsonld],
26
- ['application/rdf+xml',:rdfxml],
27
- ['application/rdfxml',:rdfxml],
28
- ['text/ntriples',:ntriples],
29
- ['text/turtle',:turtle],
30
- ['text/rdf+n3',:n3],
31
- ['text/n3',:n3]
32
- ].map{|mime|
33
- F[Render+mime[0]] = ->d,a=nil{E.renderRDF d, mime[1]}}
34
-
35
- end
data/infod/H.rb DELETED
@@ -1,15 +0,0 @@
1
- %w{
2
- audio
3
- cal
4
- edit
5
- facets
6
- forum
7
- hf
8
- histogram
9
- mail
10
- microblog
11
- threads
12
- time
13
- who
14
- wiki
15
- }.each{|r|require_relative 'H/'+r}
data/infod/H/audio.rb DELETED
@@ -1,19 +0,0 @@
1
- class E
2
-
3
- fn 'set/audio',->d,e,m{d.take.select{|e|e.ext.match AudioFile}}
4
- fn 'set/video',->d,e,m{d.take.select{|e|e.ext.match VideoFile}}
5
-
6
- AudioK = {}
7
- %w{Album-Movie-Show_title Lead_performers-Soloists Title-songname-content_description}.map{|a|Audio + a}.concat(['uri',Stat+'mtime', Stat+'size']).map{|p|AudioK[p] = true}
8
-
9
- fn 'view/audio',->d,e{
10
- d = d.dup
11
- d.delete_if{|p,o| !p.match AudioFile }
12
- d.values.map{|r| r.delete_if{|p,o| !AudioK[p] }}
13
-
14
- [(H.once e, :mu, (H.js '/js/mu')),
15
- (H.once e, :audio, (H.js '/js/audio'), (H.css '/css/audio'), {id: :rand, c: :r}, {id: :jump, c: '&rarr;'}, {id: :info, target: :_blank, _: :a},
16
- {_: e.q.has_key?('video') ? :video : :audio, id: :media, controls: true}), '<br>',
17
- F['view/table'][d,e]]}
18
-
19
- end
data/infod/H/blog.rb DELETED
@@ -1,15 +0,0 @@
1
- class E
2
-
3
- # TODO this already exists so throw some porcelain in here for typical "blog" use-case
4
-
5
- F['/blog/GET'] =-> e,r {
6
-
7
- }
8
-
9
-
10
- F['/blog/post/GET'] =-> e,r {
11
-
12
- }
13
-
14
-
15
- end
data/infod/H/cal.rb DELETED
@@ -1,81 +0,0 @@
1
- #watch __FILE__
2
- class E
3
-
4
- # TODO test rww.io/data.fm linked-data calendar apps for compatibility with our backend (and fix our backend if it doesn't work, obiously..)
5
-
6
- fn 'cal/day',->{Time.now.strftime '%Y/%m/%d/'}
7
- fn 'cal/month',->{Time.now.strftime '%Y/%m/'}
8
-
9
- # y=day forwards to current day's directory
10
- %w{day month}.map{|i|
11
- fn 'req/'+i,->e,r{
12
- [303,{'Location'=>e.send(i).uri+r.q.except('y').qs},[]]}}
13
-
14
- def day; as Fn 'cal/day' end
15
- def month; as Fn 'cal/month' end
16
-
17
- fn 'table/year',->d{ m={}
18
- d.map{|u,r|
19
- r[Date][0].do{|t|
20
- t = Time.parse t unless t.time?
21
- o=12*t.year + t.month - 1
22
- x=o/3
23
- y=o%3
24
- m[x] ||= {}
25
- m[x][y] ||= {}
26
- m[x][y][u] = r
27
- m[x][y][:t] = t
28
- }}
29
- m }
30
-
31
- fn 'table/day',->d{ m={}
32
- d.map{|u,r|
33
- r[Date][0].do{|t|
34
- t = Time.parse t unless t.time?
35
- h=t.hour
36
- s=h/12
37
- h12=h%12
38
- m[h12] ||= {}
39
- m[h12][s] ||= {}
40
- m[h12][s][u] = r
41
- m[h12][s][:t] = t
42
- }}
43
- m }
44
-
45
- fn 'table/month',->d{ m={}
46
- d.map{|u,r|
47
- r[Date][0].do{|t|
48
- t = DateTime.parse t unless t.time?
49
- w=t.strftime('%Y%W').to_i
50
- d=t.cwday
51
- m[w] ||= {}
52
- m[w][d] ||= {}
53
- m[w][d][u] = r
54
- m[w][d][:t] = t
55
- }}
56
- m }
57
-
58
- fn 'view/year',->d,e{[(H.css '/css/cal'),(Fn 'view/t',d,e,'year','month.label')]}
59
- fn 'view/month',->d,e{Fn 'view/t',d,e,'month','day.label'}
60
- fn 'view/day',->d,e{Fn 'view/t',d,e,'day','hour'}
61
-
62
- fn 'view/hour',->d,e{
63
- t = d.delete :t
64
- {style: 'background-color:#'+(t.hour % 2 == 1 ? 'ccc' : 'fff'),c:[{_: :b,style:'float:left;font-size:1.3em', c: [t.hour==0 && {_: :span, style: 'font-size:.8em;color:white;background-color:#ff%02xff' % rand(256),c: t.strftime('%e %B')},t.hour]},
65
- (Fn 'view/'+(e.q['hourv']||'title'),d,e)
66
- ]}}
67
-
68
- fn 'view/month.label',->d,e{
69
- t = d.delete :t
70
- {class: :month, style: 'background-color:#bb%02xff'%(rand(64)+192), c:
71
- ['<b>',(t.month==1 && ['<span class=year>',t.year,'</span> ']),t.strftime('%B'),'</b>',(Fn 'view/'+(e.q['monthv']||'month'),d,e)]}}
72
-
73
- fn 'view/day.label',->d,e{
74
- t = d.delete :t
75
- e[:m]||={}
76
- c=(e[:m][t.month]||='00%02xff' % (64+rand(192)))
77
- {style: 'padding:.4em;background-color:#'+c,c:[{_: :b,property: Date, c: [t.day, t.day==1 && {_: :span, style: 'font-size:.5em',c: t.strftime('%b')}]},
78
- (Fn 'view/'+(e.q['dayv']||'title'),d,e)
79
- ]}}
80
-
81
- end
data/infod/H/edit.rb DELETED
@@ -1,88 +0,0 @@
1
- watch __FILE__
2
- class E
3
-
4
- fn 'protograph/editable',->resource,env,graph{
5
- Fn 'protograph/_',resource,env,graph}
6
-
7
- fn 'graph/editable',->resource,env,graph{
8
- resource.fromStream graph, :triplrFsStore
9
- [Title,Creator,Content].map{|u|graph[u]||={}}}
10
-
11
- # show resource w/ links into editor
12
- fn 'view/edit',->g,e{
13
- [(H.once e, 'edit', (H.css '/css/edit')),
14
- g.map{|uri,s| uri && s &&
15
- (url = uri.E.localURL e
16
- {class: :resource,
17
- c: [{_: :a, class: :uri, id: uri, c: uri, href: url, title: 'view '+uri},
18
- {_: :a, class: :addField, c: '+add field', href: url+'?graph=_&view=editP'},
19
- s.map{|p,o|
20
- {class: :property,
21
- c: [{_: :a, class: :edit, c: :edit,
22
- href: e['REQUEST_PATH']+'?graph=editable&filter=p&view=editPO&p=uri,'+CGI.escape(p)},
23
- (case p
24
- when 'uri'
25
- {_: :a, class: :uri, c: p, href: p}
26
- when Content
27
- {_: :pre, c: o}
28
- else
29
- o.html
30
- end)]}}]})}]}
31
-
32
- # select or mint a property to edit
33
- fn 'view/editP',->g,e{
34
- [(H.once e, 'edit', (H.css '/css/edit')),
35
-
36
- # core properties
37
- [Date,Title,Creator,Content,Label].map{|p|
38
- {_: :a, href: p, c: p.label+' '}},
39
-
40
- # URI-typed input
41
- {_: :form, action: e['REQUEST_PATH'], method: :GET,
42
- c: [{_: :input, type: :url, name: :p, pattern: '^http.*$', size: 53},
43
-
44
- # editor arguments
45
- { filter: :p,
46
- graph: :editable,
47
- view: :editPO}.map{|n,v|
48
- {_: :input, type: :hidden, name: n, value: v}},
49
-
50
- # submit
51
- {_: :input, type: :submit, value: 'property'},
52
- ]},
53
- # schema search-engine
54
- #{_: :iframe, style: 'width: 100%;height:42ex', src: 'http://data.whats-your.name'}
55
- ]}
56
-
57
- # edit triples
58
- fn 'view/editPO',->g,e{
59
-
60
- p = e.q['p'].expand
61
-
62
- # triple -> input
63
- triple = ->s,p,o{
64
-
65
- # triple identifier
66
- i = (s.E.concatURI p).concatURI E(p).literal o
67
-
68
- [(case p
69
- when Content
70
- {_: :textarea, name: i, c: o, rows: 24, cols: 80}
71
- else
72
- {_: :input, name: i, value: o}
73
- end
74
- )]}
75
-
76
- {_: :form, name: :editor, method: :POST, action: e['REQUEST_PATH'],
77
- c: [(H.once e, 'edit', (H.css '/css/edit')),
78
- {_: :h2, c: p},
79
- # existing entries
80
- g.map{|s,r| r[p].do{|p| p.map{|o|
81
- triple[s,p,o]}.cr}},
82
- # new entry
83
- triple[e['uri'],p,''],' ',
84
- {_: :input, type: :submit, value: 'save'},
85
- {_: :a, c: ' cancel', href: e['REQUEST_PATH']+'?view=edit&graph=editable'}
86
- ]}}
87
-
88
- end
data/infod/H/forum.rb DELETED
@@ -1,4 +0,0 @@
1
- class E
2
-
3
-
4
- end
data/infod/H/hf.rb DELETED
@@ -1,114 +0,0 @@
1
- #watch __FILE__
2
-
3
- # databases of HF frequencies
4
- # curl http://eibispace.de/dx/sked-b11.csv > s.ssv
5
- # wget http://www1.m2.mediacat.ne.jp/binews/bib11.zip http://hfcc.org/data/b11/b11allx2.zip
6
- # unzip *zip
7
-
8
- class E
9
-
10
- F["?"]||={}
11
- F["?"].update({
12
- 'sw' => {
13
- 'view' => 'examine',
14
- 'ev'=>'sw',
15
- 'a'=>'Lng:49',
16
- 'minP' => 'FREQ',
17
- 'maxP' => 'FREQ',
18
- 'filter' => 'map',
19
- 'kHz:75' => 'FREQ',
20
- 'Time(UTC):93' => 'UTC',
21
- 'Station:201' => 'STATION',
22
- }
23
- })
24
-
25
- fn 'view/sw/base',->d,e,c{
26
- bands = {
27
- 120 => [2200,2500],
28
- 90 => [3100,3450],
29
- 75 => [3890,4123],
30
- 60 => [4740,5125],
31
- 49 => [800,6300],
32
- 40 => [7200,7600],
33
- 31 => [9200,9999],
34
- 25 => [11500,12160],
35
- 22 => [13500,13900],
36
- 19 => [15001,15900],
37
- 16 => [17500,17900],
38
- 13 => [21450,21850],
39
- 11 => [25700,26500],
40
- }
41
- band=0
42
- e[:clr]={}
43
- e[:fmax]=d.map{|_,r|r['FREQ'][0].to_f}.flatten.max||30000.0
44
- e[:scale]=100/(e[:fmax] - (d.map{|_,r|r['FREQ'][0].to_f}.flatten.min||0))
45
- [(H.css '/css/sw'),(H.js '/js/mu'),(H.js '/js/sw'),
46
- {id: :bands,
47
- c: bands.map{|meters,bounds|
48
- band += 1
49
- {_: :a, class: :band,
50
- style: "background-color:##{band % 2 == 0 ? 'fff' : 'cecece'}",
51
- c: '<span style="font-size:1.4em">'+meters.to_s+'</span>m',
52
- href: meters.to_s+'m.html'}}},
53
- {id: :scales, c: %w{800 1200 1600}.map{|b|{_: :span,class: :scale, c: b}}},
54
- {id: :spectrum, style: 'height:800px;position:absolute', c:
55
- [{id: 't'},{class: 'loc'},{id: 'clock'},c.(),
56
- (0..23).map{|h|
57
- [0,15,30,45].map{|m|
58
- t = h*60+m
59
- left = t*4
60
- utc="%02d%02d"%[h,m]
61
- [(1..3).map{|l|
62
- {_: :span, class: :u, c: utc, style: "top:#{l*25}%;left:#{left-19}px;"}},
63
- {class: :s,style: "border-color:#{m==0 ? 'white' : '#666'};left:#{left}px;"}]}}]}]}
64
-
65
- fn 'view/sw/item',->r,x{
66
- min=->t{t='%04d' % (t.class==String && t.empty? ? 0 : t)
67
- t[0..1].to_i*60+t[2..3].to_i}
68
- u = r['UTC'][0].to_s.match(/(\d+)-?(\d+)?/)
69
- b = u[1].to_i.max 2359
70
- e = (u[2] ? u[2].to_i : b + 30).max 2359
71
- f = r['FREQ'][0].to_f
72
- fi = f.to_i
73
- n = fi / 100
74
- x[:clr][n] ||= '#%06x' % rand(16777216)
75
- f && b && e &&
76
- (bmin=min.(b); emin=min.(e)
77
- top=(x[:fmax]-f)*x[:scale]
78
- v=->b,e{
79
- {t: r.except('uri','UTC','FREQ').values.join(' '),:class => :bar, b: b, e: e, f: fi,style:"
80
- background-color:#{x[:clr][n]};
81
- top: #{top}%;
82
- left: #{b*4.0}px;
83
- width:#{(e-b) * 4.0}px;
84
- ",c: (e-b > 60 ?
85
- ((0..(e-b)/60).map{|h|
86
- {_: :span, style: "position:absolute;left:#{h*120}px;top:0",c: f}}) : f)}}
87
- (bmin > emin) ? [v.(0,emin),
88
- v.(bmin,1440)] : v.(bmin,emin))}
89
-
90
- fn 'view/sw',->d,e{
91
- i=F['view/sw/item']
92
- Fn 'view/sw/base',d,e,->{d.map{|u,r|i.(r,e)}}}
93
-
94
- fn 'filter/gh',->o,m,_{
95
- m.values.map{|r|
96
- r[Content].do{|c|
97
- c.join.lines.each_with_index{|l,i|
98
- l.match(/^[^<]+$/) &&
99
- (u=r.uri+'#'+i.to_s
100
- m[u]={'uri' => u,
101
- 'big'=>[l.scan(/\b[A-Z][A-Z][A-Z]+\b/)],
102
- Content=>[l]}
103
- l.scan(/\d{4,}/){|d| d=d.to_i
104
- if d < 2400
105
- m[u]['UTC']=[d]
106
- elsif d < 30000
107
- m[u]['FREQ']=[d]
108
- end}
109
- m.delete u unless m[u].has_keys ['UTC','FREQ']
110
- )}
111
- m.delete r.uri
112
- }}}
113
-
114
- end
data/infod/H/mail.rb DELETED
@@ -1,92 +0,0 @@
1
- class E
2
-
3
- fn 'view/mail',->d,e{
4
- title = nil
5
-
6
- # JS/CSS
7
- [(H.once e,'mail.js',
8
- (H.css '/css/mail'), {_: :style, c: "a {background-color: #{E.cs}}"},
9
- (H.js '/js/mail'),
10
- (H.once e,:mu,(H.js '/js/mu')),
11
-
12
- # up to set-overview
13
- ({_: :a, id: :up, href: e['REQUEST_PATH'] + e.q.merge({'view' => 'page', 'v' => 'threads'}).qs, c: '&uarr;'} if d.keys.size > 2),
14
-
15
- # collapse/expand quoted content
16
- {id: :showQuote, c: :quotes, show: :true},{_: :style, id: :quote}),'<br>',
17
-
18
- # each message
19
- d.values.map{|m|
20
-
21
- # content available?
22
- [m.class == Hash && (m.has_key? E::SIOC+'content') &&
23
-
24
- {:class => :mail,
25
-
26
- c: [# message link
27
- {_: :a, name: m.uri, href: m.url+'?view=base', rel: :raw, title: :raw, c: '&nbsp;'},
28
-
29
- # To:, From: index search links
30
- [['sioc:has_creator',Creator],['sioc:addressed_to',To]].map{|a|
31
- m[a[1]].do{|m|
32
- m.map{|f| f.respond_to?(:uri) &&
33
- {_: :a, property: a[0], href: f.url+'?set=indexPO&p='+a[0]+'&view=threads&c=12', c: f.uri}}}},
34
-
35
- # mailto URI with embedded reply metadata
36
- (m['/mail/reply_to']||m[Creator]).do{|r| r[0] && r[0].respond_to?(:uri) &&
37
- {_: :a, title: :reply, c: 'r',
38
- href: "mailto:#{r[0].uri}?References=<#{m.uri}>&In-Reply-To=<#{m.uri}>&Subject=#{m[Title].join}"}},
39
-
40
- {class: :timestamp, c: m[Date].do{|d|d.map{|d|d.to_s[0..18]}}}, '<br clear=all>',
41
-
42
- # content
43
- {_: :pre,
44
- c: m[Content].map{|b|
45
-
46
- # line count
47
- i = 0
48
-
49
- # HTML message content
50
- b.class==String && b.
51
-
52
- # erase empty quoted lines
53
- gsub(/^\s*(&gt;)(&gt;|\s)*\n/,"").
54
-
55
- # each line
56
- lines.to_a.map{|l|
57
-
58
- # line identifier
59
- f = m.uri + ':' + (i+=1).to_s
60
-
61
- # wrapper
62
- {_: :span,
63
-
64
- # is line quoted?
65
- class: ((l.match /(^\s*(&gt;|On[^\n]+(said|wrote))[^\n]*)\n/) ? 'q' : 'u'), c:
66
-
67
- # id
68
- [{_: :a, id: f},
69
-
70
- # line
71
- l.chomp,
72
-
73
- # link
74
- (l.size > 64 &&
75
- {_: :a, class: :line, href: '#'+f,c: '&#160;'}),
76
-
77
- "\n" ]}}}}, # collate lines
78
-
79
- # title
80
- m[Title].do{|t|
81
- # only show if changed from previous
82
- title != t[0] && (
83
- title = t[0] # update title
84
- [{:class => :title, c: t.html, _: :a, href: m.url+'??=thread#'+m.uri},
85
- '<br clear=all>'])}]}]}]}
86
-
87
- # set a default view for RFC822 and SIOC types
88
- [MIMEtype+'message/rfc822',
89
- SIOCt+'MailMessage'].
90
- map{|m| F['view/'+m] = F['view/mail'] }
91
-
92
- end