ramaze 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (174) hide show
  1. data/Rakefile +360 -0
  2. data/bin/ramaze +152 -0
  3. data/doc/CHANGELOG +2021 -0
  4. data/doc/COPYING +56 -0
  5. data/doc/COPYING.ja +51 -0
  6. data/doc/README +275 -0
  7. data/doc/TODO +33 -0
  8. data/doc/allison/LICENSE +184 -0
  9. data/doc/allison/README +37 -0
  10. data/doc/allison/allison.css +300 -0
  11. data/doc/allison/allison.gif +0 -0
  12. data/doc/allison/allison.js +307 -0
  13. data/doc/allison/allison.rb +287 -0
  14. data/doc/allison/cache/BODY +588 -0
  15. data/doc/allison/cache/CLASS_INDEX +4 -0
  16. data/doc/allison/cache/CLASS_PAGE +1 -0
  17. data/doc/allison/cache/FILE_INDEX +4 -0
  18. data/doc/allison/cache/FILE_PAGE +1 -0
  19. data/doc/allison/cache/FONTS +1 -0
  20. data/doc/allison/cache/FR_INDEX_BODY +1 -0
  21. data/doc/allison/cache/IMGPATH +1 -0
  22. data/doc/allison/cache/INDEX +1 -0
  23. data/doc/allison/cache/JAVASCRIPT +307 -0
  24. data/doc/allison/cache/METHOD_INDEX +4 -0
  25. data/doc/allison/cache/METHOD_LIST +1 -0
  26. data/doc/allison/cache/SRC_PAGE +1 -0
  27. data/doc/allison/cache/STYLE +322 -0
  28. data/doc/allison/cache/URL +1 -0
  29. data/examples/blog/main.rb +16 -0
  30. data/examples/blog/public/screen.css +106 -0
  31. data/examples/blog/src/controller.rb +50 -0
  32. data/examples/blog/src/element.rb +53 -0
  33. data/examples/blog/src/model.rb +29 -0
  34. data/examples/blog/template/edit.xhtml +6 -0
  35. data/examples/blog/template/index.xhtml +24 -0
  36. data/examples/blog/template/new.xhtml +5 -0
  37. data/examples/blog/template/view.xhtml +15 -0
  38. data/examples/blog/test/tc_entry.rb +18 -0
  39. data/examples/caching.rb +23 -0
  40. data/examples/element.rb +40 -0
  41. data/examples/hello.rb +23 -0
  42. data/examples/simple.rb +60 -0
  43. data/examples/templates/template/external.haml +21 -0
  44. data/examples/templates/template/external.liquid +28 -0
  45. data/examples/templates/template/external.mab +27 -0
  46. data/examples/templates/template/external.rhtml +29 -0
  47. data/examples/templates/template/external.rmze +24 -0
  48. data/examples/templates/template_erubis.rb +50 -0
  49. data/examples/templates/template_haml.rb +48 -0
  50. data/examples/templates/template_liquid.rb +64 -0
  51. data/examples/templates/template_markaby.rb +52 -0
  52. data/examples/templates/template_ramaze.rb +49 -0
  53. data/examples/whywiki/main.rb +56 -0
  54. data/examples/whywiki/template/edit.xhtml +14 -0
  55. data/examples/whywiki/template/show.xhtml +17 -0
  56. data/lib/proto/conf/benchmark.yaml +35 -0
  57. data/lib/proto/conf/debug.yaml +34 -0
  58. data/lib/proto/conf/live.yaml +33 -0
  59. data/lib/proto/conf/silent.yaml +31 -0
  60. data/lib/proto/conf/stage.yaml +33 -0
  61. data/lib/proto/main.rb +18 -0
  62. data/lib/proto/public/404.jpg +0 -0
  63. data/lib/proto/public/css/coderay.css +105 -0
  64. data/lib/proto/public/css/ramaze_error.css +42 -0
  65. data/lib/proto/public/error.xhtml +74 -0
  66. data/lib/proto/public/favicon.ico +0 -0
  67. data/lib/proto/public/js/jquery.js +1923 -0
  68. data/lib/proto/public/ramaze.png +0 -0
  69. data/lib/proto/src/controller/main.rb +7 -0
  70. data/lib/proto/src/element/page.rb +16 -0
  71. data/lib/proto/src/model.rb +5 -0
  72. data/lib/proto/template/index.xhtml +6 -0
  73. data/lib/ramaze.rb +317 -0
  74. data/lib/ramaze/adapter/mongrel.rb +111 -0
  75. data/lib/ramaze/adapter/webrick.rb +161 -0
  76. data/lib/ramaze/cache.rb +11 -0
  77. data/lib/ramaze/cache/memcached.rb +52 -0
  78. data/lib/ramaze/cache/memory.rb +6 -0
  79. data/lib/ramaze/cache/yaml_store.rb +37 -0
  80. data/lib/ramaze/controller.rb +10 -0
  81. data/lib/ramaze/dispatcher.rb +315 -0
  82. data/lib/ramaze/error.rb +11 -0
  83. data/lib/ramaze/gestalt.rb +108 -0
  84. data/lib/ramaze/global.rb +120 -0
  85. data/lib/ramaze/helper.rb +32 -0
  86. data/lib/ramaze/helper/aspect.rb +189 -0
  87. data/lib/ramaze/helper/auth.rb +120 -0
  88. data/lib/ramaze/helper/cache.rb +52 -0
  89. data/lib/ramaze/helper/feed.rb +135 -0
  90. data/lib/ramaze/helper/form.rb +204 -0
  91. data/lib/ramaze/helper/link.rb +80 -0
  92. data/lib/ramaze/helper/redirect.rb +48 -0
  93. data/lib/ramaze/helper/stack.rb +67 -0
  94. data/lib/ramaze/http_status.rb +66 -0
  95. data/lib/ramaze/inform.rb +166 -0
  96. data/lib/ramaze/snippets.rb +5 -0
  97. data/lib/ramaze/snippets/hash/keys_to_sym.rb +19 -0
  98. data/lib/ramaze/snippets/kernel/aquire.rb +22 -0
  99. data/lib/ramaze/snippets/kernel/autoreload.rb +79 -0
  100. data/lib/ramaze/snippets/kernel/caller_lines.rb +58 -0
  101. data/lib/ramaze/snippets/kernel/constant.rb +24 -0
  102. data/lib/ramaze/snippets/kernel/rescue_require.rb +12 -0
  103. data/lib/ramaze/snippets/kernel/self_method.rb +41 -0
  104. data/lib/ramaze/snippets/kernel/silently.rb +13 -0
  105. data/lib/ramaze/snippets/object/traits.rb +60 -0
  106. data/lib/ramaze/snippets/openstruct/temp.rb +10 -0
  107. data/lib/ramaze/snippets/string/DIVIDE.rb +16 -0
  108. data/lib/ramaze/snippets/string/camel_case.rb +14 -0
  109. data/lib/ramaze/snippets/string/snake_case.rb +12 -0
  110. data/lib/ramaze/snippets/symbol/to_proc.rb +14 -0
  111. data/lib/ramaze/snippets/thread/deadQUESTIONMARK.rb +11 -0
  112. data/lib/ramaze/store/default.rb +48 -0
  113. data/lib/ramaze/template.rb +102 -0
  114. data/lib/ramaze/template/amrita2.rb +40 -0
  115. data/lib/ramaze/template/erubis.rb +58 -0
  116. data/lib/ramaze/template/haml.rb +65 -0
  117. data/lib/ramaze/template/haml/actionview_stub.rb +20 -0
  118. data/lib/ramaze/template/liquid.rb +74 -0
  119. data/lib/ramaze/template/markaby.rb +68 -0
  120. data/lib/ramaze/template/ramaze.rb +177 -0
  121. data/lib/ramaze/template/ramaze/element.rb +166 -0
  122. data/lib/ramaze/template/ramaze/morpher.rb +156 -0
  123. data/lib/ramaze/tool/create.rb +70 -0
  124. data/lib/ramaze/tool/tidy.rb +71 -0
  125. data/lib/ramaze/trinity.rb +38 -0
  126. data/lib/ramaze/trinity/request.rb +244 -0
  127. data/lib/ramaze/trinity/response.rb +41 -0
  128. data/lib/ramaze/trinity/session.rb +129 -0
  129. data/lib/ramaze/version.rb +14 -0
  130. data/spec/spec_all.rb +73 -0
  131. data/spec/spec_helper.rb +215 -0
  132. data/spec/tc_adapter_mongrel.rb +24 -0
  133. data/spec/tc_adapter_webrick.rb +22 -0
  134. data/spec/tc_cache.rb +79 -0
  135. data/spec/tc_controller.rb +39 -0
  136. data/spec/tc_element.rb +100 -0
  137. data/spec/tc_error.rb +23 -0
  138. data/spec/tc_gestalt.rb +90 -0
  139. data/spec/tc_global.rb +46 -0
  140. data/spec/tc_helper_aspect.rb +65 -0
  141. data/spec/tc_helper_auth.rb +61 -0
  142. data/spec/tc_helper_cache.rb +81 -0
  143. data/spec/tc_helper_feed.rb +129 -0
  144. data/spec/tc_helper_form.rb +146 -0
  145. data/spec/tc_helper_link.rb +58 -0
  146. data/spec/tc_helper_redirect.rb +51 -0
  147. data/spec/tc_helper_stack.rb +55 -0
  148. data/spec/tc_morpher.rb +90 -0
  149. data/spec/tc_params.rb +84 -0
  150. data/spec/tc_request.rb +111 -0
  151. data/spec/tc_session.rb +56 -0
  152. data/spec/tc_store.rb +25 -0
  153. data/spec/tc_template_amrita2.rb +34 -0
  154. data/spec/tc_template_erubis.rb +41 -0
  155. data/spec/tc_template_haml.rb +44 -0
  156. data/spec/tc_template_liquid.rb +98 -0
  157. data/spec/tc_template_markaby.rb +74 -0
  158. data/spec/tc_template_ramaze.rb +54 -0
  159. data/spec/tc_tidy.rb +14 -0
  160. data/spec/template/amrita2/data.html +6 -0
  161. data/spec/template/amrita2/index.html +1 -0
  162. data/spec/template/amrita2/sum.html +1 -0
  163. data/spec/template/erubis/sum.rhtml +1 -0
  164. data/spec/template/haml/index.haml +5 -0
  165. data/spec/template/haml/with_vars.haml +4 -0
  166. data/spec/template/liquid/index.liquid +1 -0
  167. data/spec/template/liquid/products.liquid +45 -0
  168. data/spec/template/markaby/external.mab +8 -0
  169. data/spec/template/markaby/sum.mab +1 -0
  170. data/spec/template/ramaze/file_only.rmze +1 -0
  171. data/spec/template/ramaze/index.rmze +1 -0
  172. data/spec/template/ramaze/nested.rmze +1 -0
  173. data/spec/template/ramaze/sum.rmze +1 -0
  174. metadata +317 -0
@@ -0,0 +1,100 @@
1
+ # Copyright (c) 2006 Michael Fellinger m.fellinger@gmail.com
2
+ # All files in this distribution are subject to the terms of the Ruby license.
3
+
4
+ require 'spec/spec_helper'
5
+
6
+ include Ramaze
7
+
8
+ class TCElementController < Template::Ramaze
9
+ def index
10
+ "The index"
11
+ end
12
+
13
+ def elementy
14
+ "<Page>#{index}</Page>"
15
+ end
16
+
17
+ def nested
18
+ "<Page> some stuff <Page>#{index}</Page> more stuff </Page>"
19
+ end
20
+
21
+ def with_params(*params)
22
+ hash = Hash[*params.flatten].map{|k,v| %{#{k}="#{v}"}}.join(' ')
23
+ %{<PageWithParams #{hash}></PageWithParams>}
24
+ end
25
+
26
+ def little
27
+ %{<PageLittle />}
28
+ end
29
+
30
+ def little_params(*params)
31
+ hash = Hash[*params.flatten].map{|k,v| %{#{k}="#{v}"}}.join(' ')
32
+ %{<PageLittleWithParams #{hash} />}
33
+ end
34
+
35
+ def templating(times)
36
+ %{<PageWithTemplating times="#{times}" />}
37
+ end
38
+ end
39
+
40
+ class Page < Element
41
+ def render
42
+ %{ <wrap> #{content} </wrap> }
43
+ end
44
+ end
45
+
46
+ class PageWithParams < Element
47
+ def render
48
+ @hash.inspect
49
+ end
50
+ end
51
+
52
+ class PageLittle < Element
53
+ def render
54
+ "little"
55
+ end
56
+ end
57
+
58
+ class PageLittleWithParams < Element
59
+ def render
60
+ @hash.inspect
61
+ end
62
+ end
63
+
64
+ class PageWithTemplating < Element
65
+ def render
66
+ (1..@hash['times']).to_a.join(', ')
67
+ end
68
+ end
69
+
70
+ context "Element" do
71
+ ramaze(:mapping => {'/' => TCElementController})
72
+
73
+ specify "simple request" do
74
+ get('/').should == "The index"
75
+ end
76
+
77
+ specify "with element" do
78
+ get('/elementy').should == "<wrap> The index </wrap>"
79
+ end
80
+
81
+ specify "nested element" do
82
+ get('/nested').should == "<wrap> some stuff <wrap> The index </wrap> more stuff </wrap>"
83
+ end
84
+
85
+ specify "with_params" do
86
+ get('/with_params/one/two').should == {'one' => 'two'}.inspect
87
+ end
88
+
89
+ specify "little" do
90
+ get('/little').should == 'little'
91
+ end
92
+
93
+ specify "little params" do
94
+ get('/little_params/one/eins').should == {'one' => 'eins'}.inspect
95
+ end
96
+
97
+ specify "templating" do
98
+ get('/templating/10').should == (1..10).to_a.join(', ')
99
+ end
100
+ end
@@ -0,0 +1,23 @@
1
+ # Copyright (c) 2006 Michael Fellinger m.fellinger@gmail.com
2
+ # All files in this distribution are subject to the terms of the Ruby license.
3
+
4
+ require 'spec/spec_helper'
5
+
6
+ include Ramaze
7
+
8
+ class TCErrorController < Template::Ramaze
9
+ def index
10
+ self.class.name
11
+ end
12
+ end
13
+
14
+ context "Error" do
15
+ context "in dispatcher" do
16
+ ramaze :mapping => {'/' => TCErrorController}, :error_page => true
17
+
18
+ specify "wrong parameter" do
19
+ get('/').should == 'TCErrorController'
20
+ get('/1').should =~ /NoAction/
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,90 @@
1
+ # Copyright (c) 2006 Michael Fellinger m.fellinger@gmail.com
2
+ # All files in this distribution are subject to the terms of the Ruby license.
3
+
4
+ require 'spec/spec_helper'
5
+
6
+ context "Gestalt" do
7
+ def gestalt &block
8
+ Ramaze::Gestalt.new(&block).to_s
9
+ end
10
+
11
+ specify "simple tag" do
12
+ gestalt{ br }.should == '<br />'
13
+ gestalt{ p }.should == '<p />'
14
+ end
15
+
16
+ specify "open close tags" do
17
+ gestalt{ p{} }.should == '<p></p>'
18
+ gestalt{ div{} }.should == '<div></div>'
19
+ end
20
+
21
+ specify "nested tags" do
22
+ gestalt{ p{ br } }.should == '<p><br /></p>'
23
+ end
24
+
25
+ specify "deep nested tags" do
26
+ gestalt{ p do
27
+ div do
28
+ ol do
29
+ li
30
+ end
31
+ end
32
+ end
33
+ }.should == '<p><div><ol><li /></ol></div></p>'
34
+ end
35
+
36
+ specify "deep nested tags with repetition" do
37
+ gestalt{ p do
38
+ div do
39
+ ol do
40
+ li
41
+ li
42
+ end
43
+ ol do
44
+ li
45
+ li
46
+ end
47
+ end
48
+ end
49
+ }.should == '<p><div><ol><li /><li /></ol><ol><li /><li /></ol></div></p>'
50
+ end
51
+
52
+ specify "deep nested tags with strings" do
53
+ gestalt{
54
+ p do
55
+ div do
56
+ 'Hello, World'
57
+ end
58
+ end
59
+ }.should == '<p><div>Hello, World</div></p>'
60
+ end
61
+
62
+ specify "some simple example" do
63
+ gestalt{
64
+ html do
65
+ head do
66
+ title do
67
+ "Hello World"
68
+ end
69
+ end
70
+ body do
71
+ h1 do
72
+ "Hello World"
73
+ end
74
+ end
75
+ end
76
+ }.should == '<html><head><title>Hello World</title></head><body><h1>Hello World</h1></body></html>'
77
+ end
78
+
79
+ specify "now some ruby inside" do
80
+ gestalt{
81
+ table do
82
+ tr do
83
+ %w[one two three].each do |s|
84
+ td{s}
85
+ end
86
+ end
87
+ end
88
+ }.should == '<table><tr><td>one</td><td>two</td><td>three</td></tr></table>'
89
+ end
90
+ end
@@ -0,0 +1,46 @@
1
+ # Copyright (c) 2006 Michael Fellinger m.fellinger@gmail.com
2
+ # All files in this distribution are subject to the terms of the Ruby license.
3
+
4
+ require 'spec/spec_helper'
5
+
6
+ include Ramaze
7
+
8
+ context "Global" do
9
+ specify "just simple assignment and retrive" do
10
+ Global.some = :xxx
11
+ Global.some.should == :xxx
12
+ end
13
+
14
+ specify "setup" do
15
+ Global.setup :a => :b
16
+ Global.a.should == :b
17
+ Global.some.should == :xxx
18
+ Global.setup :a => :c
19
+ Global.a.should == :c
20
+ end
21
+
22
+ specify "more neat stuff" do
23
+ Global.update :a => :d, :foo => :bar
24
+ Global.a.should == :c
25
+ Global.foo.should == :bar
26
+ end
27
+
28
+ specify "values_at" do
29
+ Global.values_at(:a, :foo).should == [:c, :bar]
30
+ end
31
+
32
+ specify "getting thready" do
33
+ Global[:i] = 0
34
+ Thread.main[:i] = 0
35
+
36
+ (1..10).each do |i|
37
+ Thread.new do
38
+ Global[:i] += i
39
+ Thread.main[:i] += i
40
+ end
41
+ end
42
+
43
+ Global[:i].should == Thread.main[:i]
44
+ Global[:i].should == 55
45
+ end
46
+ end
@@ -0,0 +1,65 @@
1
+ # Copyright (c) 2006 Michael Fellinger m.fellinger@gmail.com
2
+ # All files in this distribution are subject to the terms of the Ruby license.
3
+
4
+ require 'spec/spec_helper'
5
+
6
+ include Ramaze
7
+
8
+ class TCAspectController < Template::Ramaze
9
+ helper :aspect
10
+
11
+ def pre_aspect() '<aspect>' end
12
+ def post_aspect() '</aspect>' end
13
+ def wrap_aspect() '<br />' end
14
+
15
+ def test() 'test' end
16
+ pre :test, :pre_aspect
17
+ post :test, :post_aspect
18
+
19
+ def test_pre() 'test pre' end
20
+ pre :test_pre, :pre_aspect
21
+
22
+ def test_post() 'test post' end
23
+ post :test_post, :post_aspect
24
+
25
+ def test_wrap() 'test wrap' end
26
+ wrap :test_wrap, :wrap_aspect
27
+ end
28
+
29
+ class TCAspectAllController < Template::Ramaze
30
+ helper :aspect
31
+
32
+ def pre_aspect() '<pre>' end
33
+ def post_aspect() '</pre>' end
34
+
35
+ def test_all_first() 'first' end
36
+ def test_all_second() 'second' end
37
+
38
+ pre :all, :pre_aspect
39
+ post :all, :post_aspect
40
+ end
41
+
42
+ context "Aspect" do
43
+ ramaze(:mapping => {'/' => TCAspectController, '/all' => TCAspectAllController})
44
+
45
+ specify "pre" do
46
+ get('/test_pre').should == '<aspect>test pre'
47
+ end
48
+
49
+ specify "post" do
50
+ get('/test_post').should == 'test post</aspect>'
51
+ end
52
+
53
+ specify "pre and post" do
54
+ get('/test').should == '<aspect>test</aspect>'
55
+ end
56
+
57
+ specify "wrap" do
58
+ get('/test_wrap').should == '<br />test wrap<br />'
59
+ end
60
+
61
+ specify ":all" do
62
+ get('/all/test_all_first').should == '<pre>first</pre>'
63
+ get('/all/test_all_second').should == '<pre>second</pre>'
64
+ end
65
+ end
@@ -0,0 +1,61 @@
1
+ # Copyright (c) 2006 Michael Fellinger m.fellinger@gmail.com
2
+ # All files in this distribution are subject to the terms of the Ruby license.
3
+
4
+ require 'spec/spec_helper'
5
+
6
+ include Ramaze
7
+
8
+ class TCAuthHelperController < Template::Ramaze
9
+ helper :auth
10
+
11
+ def session_inspect
12
+ session.inspect
13
+ end
14
+
15
+ def secured
16
+ "Secret content"
17
+ end
18
+ pre :secured, :login_required
19
+ end
20
+
21
+ class TCAuthHashHelperController < TCAuthHelperController
22
+ trait :auth_table => {
23
+ 'manveru' => '5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8'
24
+ }
25
+ end
26
+
27
+ class TCAuthMethodHelperController < TCAuthHelperController
28
+ trait :auth_table => :auth_table
29
+
30
+ def auth_table
31
+ { 'manveru' => '5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8' }
32
+ end
33
+ end
34
+
35
+ class TCAuthLambdaHelperController < TCAuthHelperController
36
+ trait :auth_table => lambda{
37
+ { 'manveru' => '5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8' }
38
+ }
39
+ end
40
+
41
+ context "StackHelper" do
42
+ ramaze
43
+ [
44
+ TCAuthHashHelperController,
45
+ TCAuthMethodHelperController,
46
+ TCAuthLambdaHelperController
47
+ ].each do |controller|
48
+ p controller
49
+ ctx = Context.new('/session_inspect', Global.mapping.invert[controller])
50
+
51
+ specify "checking security" do
52
+ ctx.get('secured').should == ''
53
+ ctx.get('secured').should == ''
54
+ ctx.post('login', :username => 'manveru', :password => 'password').should == 'Secret content'
55
+ ctx.get('secured').should == 'Secret content'
56
+ ctx.get('secured').should == 'Secret content'
57
+ ctx.get('logout').should == ''
58
+ ctx.get('secured').should == ''
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,81 @@
1
+ # Copyright (c) 2006 Michael Fellinger m.fellinger@gmail.com
2
+ # All files in this distribution are subject to the terms of the Ruby license.
3
+
4
+ require 'spec/spec_helper'
5
+
6
+ include Ramaze
7
+
8
+ class TCCacheHelperController < Template::Ramaze
9
+ helper :cache
10
+
11
+ def index
12
+ self.class.name
13
+ end
14
+
15
+ def cached_value
16
+ value_cache[:time] ||= random
17
+ end
18
+
19
+ def uncache_value
20
+ value_cache.delete(:time)
21
+ end
22
+
23
+ def cached_action
24
+ random
25
+ end
26
+
27
+ def uncache_actions
28
+ uncache_all
29
+ end
30
+
31
+ cache_actions :cached_action
32
+
33
+ private
34
+
35
+ def random
36
+ [Time.now.usec, rand].inspect
37
+ end
38
+ end
39
+
40
+ context "CacheHelper" do
41
+ ramaze(:adapter => :mongrel, :mapping => {'/' => TCCacheHelperController})
42
+
43
+ specify "testrun" do
44
+ get('/').should == 'TCCacheHelperController'
45
+ end
46
+
47
+ def cached_value() get('/cached_value') end
48
+ def uncache_value() get('/uncache_value') end
49
+ def cached_action() get('/cached_action') end
50
+ def uncache_actions() get('/uncache_actions') end
51
+
52
+ specify "cached value" do
53
+ uncached = cached_value
54
+
55
+ 3.times do
56
+ uncached.should == cached_value
57
+ end
58
+
59
+ old = cached_value
60
+
61
+ 3.times do
62
+ uncache_value
63
+ cached_value.should_not == old
64
+ end
65
+ end
66
+
67
+ specify "cached action" do
68
+ uncached = cached_action
69
+
70
+ 3.times do
71
+ cached_action.should == uncached
72
+ end
73
+
74
+ old = cached_action
75
+
76
+ 3.times do
77
+ uncache_actions
78
+ cached_action.should_not == old
79
+ end
80
+ end
81
+ end