devcenter 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (192) hide show
  1. data/.gitignore +18 -0
  2. data/Gemfile +8 -0
  3. data/LICENSE.txt +22 -0
  4. data/README.md +39 -0
  5. data/Rakefile +2 -0
  6. data/bin/devcenter +7 -0
  7. data/devcenter.gemspec +30 -0
  8. data/lib/devcenter.rb +6 -0
  9. data/lib/devcenter/cli.rb +45 -0
  10. data/lib/devcenter/coderay_extensions.rb +70 -0
  11. data/lib/devcenter/commands.rb +4 -0
  12. data/lib/devcenter/commands/base.rb +47 -0
  13. data/lib/devcenter/commands/open.rb +34 -0
  14. data/lib/devcenter/commands/preview.rb +28 -0
  15. data/lib/devcenter/commands/pull.rb +37 -0
  16. data/lib/devcenter/helpers.rb +41 -0
  17. data/lib/devcenter/layout.html +299 -0
  18. data/lib/devcenter/md_parser.rb +87 -0
  19. data/lib/devcenter/previewer.rb +36 -0
  20. data/lib/devcenter/previewer/assets/images/public/article-icon-large.png +0 -0
  21. data/lib/devcenter/previewer/assets/images/public/article-icon.png +0 -0
  22. data/lib/devcenter/previewer/assets/images/public/aside_accordion_indicator_default.png +0 -0
  23. data/lib/devcenter/previewer/assets/images/public/aside_accordion_indicator_open.png +0 -0
  24. data/lib/devcenter/previewer/assets/images/public/body_bg.png +0 -0
  25. data/lib/devcenter/previewer/assets/images/public/callout_bg.png +0 -0
  26. data/lib/devcenter/previewer/assets/images/public/feed-icon-sprite.png +0 -0
  27. data/lib/devcenter/previewer/assets/images/public/heroku-header-logo-mobile.png +0 -0
  28. data/lib/devcenter/previewer/assets/images/public/heroku-header-logo.png +0 -0
  29. data/lib/devcenter/previewer/assets/images/public/heroku-logo.png +0 -0
  30. data/lib/devcenter/previewer/assets/images/public/icon_sprite_16.png +0 -0
  31. data/lib/devcenter/previewer/assets/images/public/index_li_bullet.png +0 -0
  32. data/lib/devcenter/previewer/assets/images/public/intro_bg.png +0 -0
  33. data/lib/devcenter/previewer/assets/images/public/jive_discussion_arrow.png +0 -0
  34. data/lib/devcenter/previewer/assets/images/public/jive_discussion_glyph.png +0 -0
  35. data/lib/devcenter/previewer/assets/images/public/line.png +0 -0
  36. data/lib/devcenter/previewer/assets/images/public/pre_code_background.png +0 -0
  37. data/lib/devcenter/previewer/assets/images/public/search-icon.png +0 -0
  38. data/lib/devcenter/previewer/assets/images/public/search_glyph.png +0 -0
  39. data/lib/devcenter/previewer/assets/images/public/search_return.png +0 -0
  40. data/lib/devcenter/previewer/assets/images/public/tag-icon-large.png +0 -0
  41. data/lib/devcenter/previewer/assets/images/public/toc-icon.png +0 -0
  42. data/lib/devcenter/previewer/assets/public.css +2125 -0
  43. data/lib/devcenter/previewer/assets/public/article-icon-large.png +0 -0
  44. data/lib/devcenter/previewer/assets/public/article-icon.png +0 -0
  45. data/lib/devcenter/previewer/assets/public/aside_accordion_indicator_default.png +0 -0
  46. data/lib/devcenter/previewer/assets/public/aside_accordion_indicator_open.png +0 -0
  47. data/lib/devcenter/previewer/assets/public/body_bg.png +0 -0
  48. data/lib/devcenter/previewer/assets/public/callout_bg.png +0 -0
  49. data/lib/devcenter/previewer/assets/public/feed-icon-sprite.png +0 -0
  50. data/lib/devcenter/previewer/assets/public/heroku-header-logo-mobile.png +0 -0
  51. data/lib/devcenter/previewer/assets/public/heroku-header-logo.png +0 -0
  52. data/lib/devcenter/previewer/assets/public/heroku-logo.png +0 -0
  53. data/lib/devcenter/previewer/assets/public/icon_sprite_16.png +0 -0
  54. data/lib/devcenter/previewer/assets/public/index_li_bullet.png +0 -0
  55. data/lib/devcenter/previewer/assets/public/intro_bg.png +0 -0
  56. data/lib/devcenter/previewer/assets/public/jive_discussion_arrow.png +0 -0
  57. data/lib/devcenter/previewer/assets/public/jive_discussion_glyph.png +0 -0
  58. data/lib/devcenter/previewer/assets/public/line.png +0 -0
  59. data/lib/devcenter/previewer/assets/public/pre_code_background.png +0 -0
  60. data/lib/devcenter/previewer/assets/public/public.css +2125 -0
  61. data/lib/devcenter/previewer/assets/public/search-icon.png +0 -0
  62. data/lib/devcenter/previewer/assets/public/search_glyph.png +0 -0
  63. data/lib/devcenter/previewer/assets/public/search_return.png +0 -0
  64. data/lib/devcenter/previewer/assets/public/tag-icon-large.png +0 -0
  65. data/lib/devcenter/previewer/assets/public/toc-icon.png +0 -0
  66. data/lib/devcenter/previewer/file_listener.rb +23 -0
  67. data/lib/devcenter/previewer/views/article.erb +345 -0
  68. data/lib/devcenter/previewer/web_app.rb +53 -0
  69. data/lib/devcenter/previewer/web_server.rb +29 -0
  70. data/lib/devcenter/version.rb +3 -0
  71. data/vendor/sinatra/.gitignore +6 -0
  72. data/vendor/sinatra/.travis.yml +16 -0
  73. data/vendor/sinatra/.yardopts +4 -0
  74. data/vendor/sinatra/AUTHORS +61 -0
  75. data/vendor/sinatra/Gemfile +91 -0
  76. data/vendor/sinatra/LICENSE +22 -0
  77. data/vendor/sinatra/README.de.rdoc +2116 -0
  78. data/vendor/sinatra/README.es.rdoc +2106 -0
  79. data/vendor/sinatra/README.fr.rdoc +2133 -0
  80. data/vendor/sinatra/README.hu.rdoc +608 -0
  81. data/vendor/sinatra/README.jp.rdoc +1056 -0
  82. data/vendor/sinatra/README.ko.rdoc +1932 -0
  83. data/vendor/sinatra/README.pt-br.rdoc +778 -0
  84. data/vendor/sinatra/README.pt-pt.rdoc +647 -0
  85. data/vendor/sinatra/README.rdoc +2049 -0
  86. data/vendor/sinatra/README.ru.rdoc +2033 -0
  87. data/vendor/sinatra/README.zh.rdoc +1816 -0
  88. data/vendor/sinatra/Rakefile +182 -0
  89. data/vendor/sinatra/examples/chat.rb +61 -0
  90. data/vendor/sinatra/examples/simple.rb +3 -0
  91. data/vendor/sinatra/examples/stream.ru +26 -0
  92. data/vendor/sinatra/lib/sinatra.rb +5 -0
  93. data/vendor/sinatra/lib/sinatra/base.rb +1820 -0
  94. data/vendor/sinatra/lib/sinatra/images/404.png +0 -0
  95. data/vendor/sinatra/lib/sinatra/images/500.png +0 -0
  96. data/vendor/sinatra/lib/sinatra/main.rb +30 -0
  97. data/vendor/sinatra/lib/sinatra/showexceptions.rb +345 -0
  98. data/vendor/sinatra/lib/sinatra/version.rb +3 -0
  99. data/vendor/sinatra/sinatra.gemspec +18 -0
  100. data/vendor/sinatra/test/base_test.rb +172 -0
  101. data/vendor/sinatra/test/builder_test.rb +91 -0
  102. data/vendor/sinatra/test/coffee_test.rb +90 -0
  103. data/vendor/sinatra/test/compile_test.rb +139 -0
  104. data/vendor/sinatra/test/contest.rb +98 -0
  105. data/vendor/sinatra/test/creole_test.rb +65 -0
  106. data/vendor/sinatra/test/delegator_test.rb +160 -0
  107. data/vendor/sinatra/test/encoding_test.rb +20 -0
  108. data/vendor/sinatra/test/erb_test.rb +98 -0
  109. data/vendor/sinatra/test/extensions_test.rb +98 -0
  110. data/vendor/sinatra/test/filter_test.rb +437 -0
  111. data/vendor/sinatra/test/haml_test.rb +91 -0
  112. data/vendor/sinatra/test/helper.rb +123 -0
  113. data/vendor/sinatra/test/helpers_test.rb +1768 -0
  114. data/vendor/sinatra/test/integration/app.rb +62 -0
  115. data/vendor/sinatra/test/integration_helper.rb +222 -0
  116. data/vendor/sinatra/test/integration_test.rb +87 -0
  117. data/vendor/sinatra/test/less_test.rb +69 -0
  118. data/vendor/sinatra/test/liquid_test.rb +59 -0
  119. data/vendor/sinatra/test/mapped_error_test.rb +305 -0
  120. data/vendor/sinatra/test/markaby_test.rb +80 -0
  121. data/vendor/sinatra/test/markdown_test.rb +82 -0
  122. data/vendor/sinatra/test/middleware_test.rb +68 -0
  123. data/vendor/sinatra/test/nokogiri_test.rb +67 -0
  124. data/vendor/sinatra/test/public/favicon.ico +0 -0
  125. data/vendor/sinatra/test/rabl_test.rb +89 -0
  126. data/vendor/sinatra/test/rack_test.rb +45 -0
  127. data/vendor/sinatra/test/radius_test.rb +59 -0
  128. data/vendor/sinatra/test/rdoc_test.rb +66 -0
  129. data/vendor/sinatra/test/readme_test.rb +120 -0
  130. data/vendor/sinatra/test/request_test.rb +45 -0
  131. data/vendor/sinatra/test/response_test.rb +64 -0
  132. data/vendor/sinatra/test/result_test.rb +76 -0
  133. data/vendor/sinatra/test/route_added_hook_test.rb +59 -0
  134. data/vendor/sinatra/test/routing_test.rb +1175 -0
  135. data/vendor/sinatra/test/sass_test.rb +116 -0
  136. data/vendor/sinatra/test/scss_test.rb +89 -0
  137. data/vendor/sinatra/test/server_test.rb +48 -0
  138. data/vendor/sinatra/test/settings_test.rb +561 -0
  139. data/vendor/sinatra/test/sinatra_test.rb +12 -0
  140. data/vendor/sinatra/test/slim_test.rb +84 -0
  141. data/vendor/sinatra/test/static_test.rb +219 -0
  142. data/vendor/sinatra/test/streaming_test.rb +149 -0
  143. data/vendor/sinatra/test/templates_test.rb +333 -0
  144. data/vendor/sinatra/test/textile_test.rb +65 -0
  145. data/vendor/sinatra/test/views/a/in_a.str +1 -0
  146. data/vendor/sinatra/test/views/ascii.erb +2 -0
  147. data/vendor/sinatra/test/views/b/in_b.str +1 -0
  148. data/vendor/sinatra/test/views/calc.html.erb +1 -0
  149. data/vendor/sinatra/test/views/error.builder +3 -0
  150. data/vendor/sinatra/test/views/error.erb +3 -0
  151. data/vendor/sinatra/test/views/error.haml +3 -0
  152. data/vendor/sinatra/test/views/error.sass +2 -0
  153. data/vendor/sinatra/test/views/explicitly_nested.str +1 -0
  154. data/vendor/sinatra/test/views/foo/hello.test +1 -0
  155. data/vendor/sinatra/test/views/hello.builder +1 -0
  156. data/vendor/sinatra/test/views/hello.coffee +1 -0
  157. data/vendor/sinatra/test/views/hello.creole +1 -0
  158. data/vendor/sinatra/test/views/hello.erb +1 -0
  159. data/vendor/sinatra/test/views/hello.haml +1 -0
  160. data/vendor/sinatra/test/views/hello.less +5 -0
  161. data/vendor/sinatra/test/views/hello.liquid +1 -0
  162. data/vendor/sinatra/test/views/hello.mab +1 -0
  163. data/vendor/sinatra/test/views/hello.md +1 -0
  164. data/vendor/sinatra/test/views/hello.nokogiri +1 -0
  165. data/vendor/sinatra/test/views/hello.rabl +2 -0
  166. data/vendor/sinatra/test/views/hello.radius +1 -0
  167. data/vendor/sinatra/test/views/hello.rdoc +1 -0
  168. data/vendor/sinatra/test/views/hello.sass +2 -0
  169. data/vendor/sinatra/test/views/hello.scss +3 -0
  170. data/vendor/sinatra/test/views/hello.slim +1 -0
  171. data/vendor/sinatra/test/views/hello.str +1 -0
  172. data/vendor/sinatra/test/views/hello.test +1 -0
  173. data/vendor/sinatra/test/views/hello.textile +1 -0
  174. data/vendor/sinatra/test/views/hello.wlang +1 -0
  175. data/vendor/sinatra/test/views/hello.yajl +1 -0
  176. data/vendor/sinatra/test/views/layout2.builder +3 -0
  177. data/vendor/sinatra/test/views/layout2.erb +2 -0
  178. data/vendor/sinatra/test/views/layout2.haml +2 -0
  179. data/vendor/sinatra/test/views/layout2.liquid +2 -0
  180. data/vendor/sinatra/test/views/layout2.mab +2 -0
  181. data/vendor/sinatra/test/views/layout2.nokogiri +3 -0
  182. data/vendor/sinatra/test/views/layout2.rabl +3 -0
  183. data/vendor/sinatra/test/views/layout2.radius +2 -0
  184. data/vendor/sinatra/test/views/layout2.slim +3 -0
  185. data/vendor/sinatra/test/views/layout2.str +2 -0
  186. data/vendor/sinatra/test/views/layout2.test +1 -0
  187. data/vendor/sinatra/test/views/layout2.wlang +2 -0
  188. data/vendor/sinatra/test/views/nested.str +1 -0
  189. data/vendor/sinatra/test/views/utf8.erb +2 -0
  190. data/vendor/sinatra/test/wlang_test.rb +70 -0
  191. data/vendor/sinatra/test/yajl_test.rb +86 -0
  192. metadata +414 -0
@@ -0,0 +1,778 @@
1
+ = Sinatra
2
+ <i>Atenção: Este documento é apenas uma tradução da versão em inglês e pode estar desatualizado.</i>
3
+
4
+ Sinatra é uma
5
+ {DSL}[http://pt.wikipedia.org/wiki/Linguagem_de_domínio_específico]
6
+ para criar aplicações web em Ruby com o mínimo de esforço e rapidez:
7
+
8
+ # minhaapp.rb
9
+ require 'sinatra'
10
+
11
+ get '/' do
12
+ 'Olá Mundo!'
13
+ end
14
+
15
+ Instale a gem e execute como:
16
+
17
+ gem install sinatra
18
+ ruby -rubygems minhaapp.rb
19
+
20
+ Acesse em: http://localhost:4567
21
+
22
+ Recomendamos a execução de <tt>gem install thin</tt>. Caso esteja disponível, o Sinatra irá usar.
23
+
24
+ == Rotas
25
+
26
+ No Sinatra, uma rota é um método HTTP emparelhado com um padrão de URL. Cada rota possui um bloco de execução:
27
+
28
+ get '/' do
29
+ .. mostrando alguma coisa ..
30
+ end
31
+
32
+ post '/' do
33
+ .. criando alguma coisa ..
34
+ end
35
+
36
+ put '/' do
37
+ .. atualizando alguma coisa ..
38
+ end
39
+
40
+ patch '/' do
41
+ .. modificando alguma coisa ..
42
+ end
43
+
44
+ delete '/' do
45
+ .. removendo alguma coisa ..
46
+ end
47
+
48
+ options '/' do
49
+ .. estabelecendo alguma coisa ..
50
+ end
51
+
52
+ As rotas são interpretadas na ordem em que são definidos. A primeira rota encontrada responde ao pedido.
53
+
54
+ Padrões de rota podem conter parâmetros nomeados, acessível através do hash <tt>params</tt>:
55
+
56
+ get '/ola/:nome' do
57
+ # corresponde a "GET /ola/foo" e "GET /ola/bar"
58
+ # params[:nome] é 'foo' ou 'bar'
59
+ "Olá #{params[:nome]}!"
60
+ end
61
+
62
+ Você também pode acessar parâmetros nomeados através dos parâmetros de um bloco:
63
+
64
+ get '/ola/:nome' do |n|
65
+ "Olá #{n}!"
66
+ end
67
+
68
+ Padrões de rota também podem conter parâmetros splat (wildcard), acessível através do array <tt>params[: splat]</tt>:
69
+
70
+ get '/diga/*/para/*' do
71
+ # corresponde a /diga/ola/para/mundo
72
+ params[:splat] # => ["ola", "mundo"]
73
+ end
74
+
75
+ get '/download/*.*' do
76
+ # corresponde a /download/pasta/do/arquivo.xml
77
+ params[:splat] # => ["pasta/do/arquivo", "xml"]
78
+ end
79
+
80
+ Ou com parâmetros de um bloco:
81
+
82
+ get '/download/*.*' do |pasta, ext|
83
+ [pasta, ext] # => ["pasta/do/arquivo", "xml"]
84
+ end
85
+
86
+ Rotas podem corresponder com expressões regulares:
87
+
88
+ get %r{/ola/([\w]+)} do
89
+ "Olá, #{params[:captures].first}!"
90
+ end
91
+
92
+ Ou com parâmetros de um bloco:
93
+
94
+ get %r{/ola/([\w]+)} do |c|
95
+ "Olá, #{c}!"
96
+ end
97
+
98
+ Padrões de rota podem contar com parâmetros opcionais:
99
+
100
+ get '/posts.?:formato?' do
101
+ # corresponde a "GET /posts" e qualquer extensão "GET /posts.json", "GET /posts.xml", etc.
102
+ end
103
+
104
+ A propósito, a menos que você desative a proteção contra ataques (veja abaixo), o caminho solicitado pode ser alterado antes de concluir a comparação com as suas rotas.
105
+
106
+ === Condições
107
+
108
+ Rotas podem incluir uma variedade de condições, tal como o <tt>user agent</tt>:
109
+
110
+ get '/foo', :agent => /Songbird (\d\.\d)[\d\/]*?/ do
111
+ "Você está usando o Songbird versão #{params[:agent][0]}"
112
+ end
113
+
114
+ get '/foo' do
115
+ # Correspondente a navegadores que não sejam Songbird
116
+ end
117
+
118
+ Outras condições disponíveis são <tt>host_name</tt> e <tt>provides</tt>:
119
+
120
+ get '/', :host_name => /^admin\./ do
121
+ "Área administrativa. Acesso negado!"
122
+ end
123
+
124
+ get '/', :provides => 'html' do
125
+ haml :index
126
+ end
127
+
128
+ get '/', :provides => ['rss', 'atom', 'xml'] do
129
+ builder :feed
130
+ end
131
+
132
+ Você pode facilmente definir suas próprias condições:
133
+
134
+ set(:probabilidade) { |valor| condition { rand <= valor } }
135
+
136
+ get '/ganha_um_carro', :probabilidade => 0.1 do
137
+ "Você ganhou!"
138
+ end
139
+
140
+ get '/ganha_um_carro' do
141
+ "Sinto muito, você perdeu."
142
+ end
143
+
144
+ Use splat, para uma condição que levam vários valores:
145
+
146
+ set(:auth) do |*roles| # <- observe o splat aqui
147
+ condition do
148
+ unless logged_in? && roles.any? {|role| current_user.in_role? role }
149
+ redirect "/login/", 303
150
+ end
151
+ end
152
+ end
153
+
154
+ get "/minha/conta/", :auth => [:usuario, :administrador] do
155
+ "Detalhes da sua conta"
156
+ end
157
+
158
+ get "/apenas/administrador/", :auth => :administrador do
159
+ "Apenas administradores são permitidos aqui!"
160
+ end
161
+
162
+ === Retorno de valores
163
+
164
+ O valor de retorno do bloco de uma rota determina pelo menos o corpo da resposta passado para o cliente HTTP, ou pelo menos o próximo middleware na pilha Rack. Frequentemente, isto é uma <tt>string</tt>, tal como nos exemplos acima. Mas, outros valores também são aceitos.
165
+
166
+ Você pode retornar uma resposta válida ou um objeto para o Rack, sendo eles de qualquer tipo de objeto que queira. Além disto, é possível retornar um código de status HTTP.
167
+
168
+ * Um array com três elementros: [status (Fixnum), cabecalho (Hash), corpo da resposta (responde à #each)]
169
+
170
+ * Um array com dois elementros: [status (Fixnum), corpo da resposta (responde à #each)]
171
+
172
+ * Um objeto que responda à #each sem passar nada, mas, sim, <tt>strings</tt> para um dado bloco
173
+
174
+ * Um objeto <tt>Fixnum</tt> representando o código de status
175
+
176
+ Dessa forma, podemos implementar facilmente um exemplo de streaming:
177
+
178
+ class Stream
179
+ def each
180
+ 100.times { |i| yield "#{i}\n" }
181
+ end
182
+ end
183
+
184
+ get('/') { Stream.new }
185
+
186
+ Você também pode usar o método auxiliar <tt>stream</tt> (descrito abaixo) para incorporar a lógica de streaming na rota.
187
+
188
+ === Custom Route Matchers
189
+
190
+ Como apresentado acima, a estrutura do Sinatra conta com suporte embutido para uso de padrões de String e expressões regulares como validadores de rota. No entanto, ele não pára por aí. Você pode facilmente definir os seus próprios validadores:
191
+
192
+ class AllButPattern
193
+ Match = Struct.new(:captures)
194
+
195
+ def initialize(except)
196
+ @except = except
197
+ @captures = Match.new([])
198
+ end
199
+
200
+ def match(str)
201
+ @captures unless @except === str
202
+ end
203
+ end
204
+
205
+ def all_but(pattern)
206
+ AllButPattern.new(pattern)
207
+ end
208
+
209
+ get all_but("/index") do
210
+ # ...
211
+ end
212
+
213
+ Note que o exemplo acima pode ser robusto e complicado em excesso. Pode também ser implementado como:
214
+
215
+ get // do
216
+ pass if request.path_info == "/index"
217
+ # ...
218
+ end
219
+
220
+ Ou, usando algo mais denso à frente:
221
+
222
+ get %r{^(?!/index$)} do
223
+ # ...
224
+ end
225
+
226
+ == Arquivos estáticos
227
+
228
+ Arquivos estáticos são disponibilizados a partir do diretório <tt>./public</tt>. Você pode especificar
229
+ um local diferente pela opção <tt>:public_folder</tt>
230
+
231
+ set :public_folder, File.dirname(__FILE__) + '/estatico'
232
+
233
+ Note que o nome do diretório público não é incluido na URL. Um arquivo
234
+ <tt>./public/css/style.css</tt> é disponibilizado como
235
+ <tt>http://example.com/css/style.css</tt>.
236
+
237
+ == Views / Templates
238
+
239
+ Templates presumem-se estar localizados sob o diretório <tt>./views</tt>.
240
+ Para utilizar um diretório view diferente:
241
+
242
+ set :views, File.dirname(__FILE__) + '/modelo'
243
+
244
+ Uma coisa importante a ser lembrada é que você sempre tem as referências dos
245
+ templates como símbolos, mesmo se eles estiverem em um sub-diretório (nesse
246
+ caso utilize <tt>:'subdir/template'</tt>). Métodos de renderização irão processar
247
+ qualquer string passada diretamente para elas.
248
+
249
+ === Haml Templates
250
+
251
+ A gem/biblioteca haml é necessária para renderizar templates HAML:
252
+
253
+ # Você precisa do 'require haml' em sua aplicação.
254
+ require 'haml'
255
+
256
+ get '/' do
257
+ haml :index
258
+ end
259
+
260
+ Renderiza <tt>./views/index.haml</tt>.
261
+
262
+ {Opções Haml}[http://haml.info/docs/yardoc/file.HAML_REFERENCE.html#options]
263
+ podem ser setadas globalmente através das configurações do sinatra,
264
+ veja {Opções e Configurações}[http://www.sinatrarb.com/configuration.html],
265
+ e substitua em uma requisição individual.
266
+
267
+ set :haml, {:format => :html5 } # o formato padrão do Haml é :xhtml
268
+
269
+ get '/' do
270
+ haml :index, :haml_options => {:format => :html4 } # substituido
271
+ end
272
+
273
+
274
+ === Erb Templates
275
+
276
+ # Você precisa do 'require erb' em sua aplicação
277
+ require 'erb'
278
+
279
+ get '/' do
280
+ erb :index
281
+ end
282
+
283
+ Renderiza <tt>./views/index.erb</tt>
284
+
285
+ === Erubis
286
+
287
+ A gem/biblioteca erubis é necessária para renderizar templates erubis:
288
+
289
+ # Você precisa do 'require erubis' em sua aplicação.
290
+ require 'erubis'
291
+
292
+ get '/' do
293
+ erubis :index
294
+ end
295
+
296
+ Renderiza <tt>./views/index.erubis</tt>
297
+
298
+ === Builder Templates
299
+
300
+ A gem/biblioteca builder é necessária para renderizar templates builder:
301
+
302
+ # Você precisa do 'require builder' em sua aplicação.
303
+ require 'builder'
304
+
305
+ get '/' do
306
+ content_type 'application/xml', :charset => 'utf-8'
307
+ builder :index
308
+ end
309
+
310
+ Renderiza <tt>./views/index.builder</tt>.
311
+
312
+ === Sass Templates
313
+
314
+ A gem/biblioteca sass é necessária para renderizar templates sass:
315
+
316
+ # Você precisa do 'require haml' ou 'require sass' em sua aplicação.
317
+ require 'sass'
318
+
319
+ get '/stylesheet.css' do
320
+ content_type 'text/css', :charset => 'utf-8'
321
+ sass :stylesheet
322
+ end
323
+
324
+ Renderiza <tt>./views/stylesheet.sass</tt>.
325
+
326
+ {Opções Sass}[http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#options]
327
+ podem ser setadas globalmente através das configurações do sinatra,
328
+ veja {Opções e Configurações}[http://www.sinatrarb.com/configuration.html],
329
+ e substitua em uma requisição individual.
330
+
331
+ set :sass, {:style => :compact } # o estilo padrão do Sass é :nested
332
+
333
+ get '/stylesheet.css' do
334
+ content_type 'text/css', :charset => 'utf-8'
335
+ sass :stylesheet, :style => :expanded # substituido
336
+ end
337
+
338
+ === Less Templates
339
+
340
+ A gem/biblioteca less é necessária para renderizar templates Less:
341
+
342
+ # Você precisa do 'require less' em sua aplicação.
343
+ require 'less'
344
+
345
+ get '/stylesheet.css' do
346
+ content_type 'text/css', :charset => 'utf-8'
347
+ less :stylesheet
348
+ end
349
+
350
+ Renderiza <tt>./views/stylesheet.less</tt>.
351
+
352
+ === Inline Templates
353
+
354
+ get '/' do
355
+ haml '%div.title Olá Mundo'
356
+ end
357
+
358
+ Renderiza a string, em uma linha, no template.
359
+
360
+ === Acessando Variáveis nos Templates
361
+
362
+ Templates são avaliados dentro do mesmo contexto como manipuladores de rota. Variáveis
363
+ de instância setadas em rotas manipuladas são diretamente acessadas por templates:
364
+
365
+ get '/:id' do
366
+ @foo = Foo.find(params[:id])
367
+ haml '%h1= @foo.nome'
368
+ end
369
+
370
+ Ou, especifique um hash explícito para variáveis locais:
371
+
372
+ get '/:id' do
373
+ foo = Foo.find(params[:id])
374
+ haml '%h1= foo.nome', :locals => { :foo => foo }
375
+ end
376
+
377
+ Isso é tipicamente utilizando quando renderizamos templates como partials dentro
378
+ de outros templates.
379
+
380
+ === Templates Inline
381
+
382
+ Templates podem ser definidos no final do arquivo fonte(.rb):
383
+
384
+ require 'rubygems'
385
+ require 'sinatra'
386
+
387
+ get '/' do
388
+ haml :index
389
+ end
390
+
391
+ __END__
392
+
393
+ @@ layout
394
+ %html
395
+ = yield
396
+
397
+ @@ index
398
+ %div.title Olá Mundo!!!!!
399
+
400
+ NOTA: Templates inline definidos no arquivo fonte são automaticamente carregados
401
+ pelo sinatra. Digite `enable :inline_templates` se você tem templates
402
+ inline no outro arquivo fonte.
403
+
404
+ === Templates nomeados
405
+
406
+ Templates também podem ser definidos utilizando o método top-level <tt>template</tt>:
407
+
408
+ template :layout do
409
+ "%html\n =yield\n"
410
+ end
411
+
412
+ template :index do
413
+ '%div.title Olá Mundo!'
414
+ end
415
+
416
+ get '/' do
417
+ haml :index
418
+ end
419
+
420
+ Se existir um template com nome "layout", ele será utilizado toda vez que um
421
+ template for renderizado. Você pode desabilitar layouts passando <tt>:layout => false</tt>.
422
+
423
+ get '/' do
424
+ haml :index, :layout => !request.xhr?
425
+ end
426
+
427
+ == Helpers
428
+
429
+ Use o método de alto nível <tt>helpers</tt> para definir métodos auxiliares para utilizar em
430
+ manipuladores de rotas e modelos:
431
+
432
+ helpers do
433
+ def bar(nome)
434
+ "#{nome}bar"
435
+ end
436
+ end
437
+
438
+ get '/:nome' do
439
+ bar(params[:nome])
440
+ end
441
+
442
+ == Filtros
443
+
444
+ Filtros Before são avaliados antes de cada requisição dentro do contexto da requisição
445
+ e pode modificar a requisição e a reposta. Variáveis de instância setadas nos
446
+ filtros são acessadas através de rotas e templates:
447
+
448
+ before do
449
+ @nota = 'Oi!'
450
+ request.path_info = '/foo/bar/baz'
451
+ end
452
+
453
+ get '/foo/*' do
454
+ @nota #=> 'Oi!'
455
+ params[:splat] #=> 'bar/baz'
456
+ end
457
+
458
+ Filtros After são avaliados após cada requisição dentro do contexto da
459
+ requisição e também podem modificar o pedido e a resposta. Variáveis de instância
460
+ definidas nos filtros before e rotas são acessadas através dos filtros after:
461
+
462
+ after do
463
+ puts response.status
464
+ end
465
+
466
+ Filtros opcionalmente tem um padrão, fazendo com que sejam avaliados somente se o caminho
467
+ do pedido coincidir com esse padrão:
468
+
469
+ before '/protected/*' do
470
+ authenticate!
471
+ end
472
+
473
+ after '/create/:slug' do |slug|
474
+ session[:last_slug] = slug
475
+ end
476
+
477
+ == Halting
478
+
479
+ Para parar imediatamente uma requisição com um filtro ou rota utilize:
480
+
481
+ halt
482
+
483
+ Você também pode especificar o status quando parar...
484
+
485
+ halt 410
486
+
487
+ Ou com corpo de texto...
488
+
489
+ halt 'isso será o corpo do texto'
490
+
491
+ Ou também...
492
+
493
+ halt 401, 'vamos embora!'
494
+
495
+ Com cabeçalhos...
496
+
497
+ halt 402, {'Content-Type' => 'text/plain'}, 'revanche'
498
+
499
+ == Passing
500
+
501
+ Uma rota pode processar aposta para a próxima rota correspondente usando <tt>pass</tt>:
502
+
503
+ get '/adivinhar/:quem' do
504
+ pass unless params[:quem] == 'Frank'
505
+ 'Você me pegou!'
506
+ end
507
+
508
+ get '/adivinhar/*' do
509
+ 'Você falhou!'
510
+ end
511
+
512
+ O bloqueio da rota é imediatamente encerrado e o controle continua com a próxima
513
+ rota de parâmetro. Se o parâmetro da rota não for encontrado, um 404 é retornado.
514
+
515
+ == Configuração
516
+
517
+ Rodando uma vez, na inicialização, em qualquer ambiente:
518
+
519
+ configure do
520
+ ...
521
+ end
522
+
523
+ Rodando somente quando o ambiente (RACK_ENV environment variável) é setado para
524
+ <tt>:production</tt>:
525
+
526
+ configure :production do
527
+ ...
528
+ end
529
+
530
+ Rodando quando o ambiente é setado para <tt>:production</tt> ou
531
+ <tt>:test</tt>:
532
+
533
+ configure :production, :test do
534
+ ...
535
+ end
536
+
537
+ == Tratamento de Erros
538
+
539
+ Tratamento de erros rodam dentro do mesmo contexto como rotas e filtros before, o
540
+ que significa que você pega todos os presentes que tem para oferecer, como <tt>haml</tt>, <tt>erb</tt>,
541
+ <tt>halt</tt>, etc.
542
+
543
+ === Não Encontrado
544
+
545
+ Quando um <tt>Sinatra::NotFound</tt> exception é levantado, ou o código de status
546
+ da reposta é 404, o <tt>not_found</tt> manipulador é invocado:
547
+
548
+ not_found do
549
+ 'Isto está longe de ser encontrado'
550
+ end
551
+
552
+ === Erro
553
+
554
+ O manipulador +error+ é invocado toda a vez que uma exceção é lançada a partir de
555
+ um bloco de rota ou um filtro. O objeto da exceção pode ser obtido a partir da variável
556
+ Rack <tt>sinatra.error</tt>:
557
+
558
+ error do
559
+ 'Desculpe, houve um erro desagradável - ' + env['sinatra.error'].name
560
+ end
561
+
562
+ Erros customizados:
563
+
564
+ error MeuErroCustomizado do
565
+ 'Então que aconteceu foi...' + env['sinatra.error'].message
566
+ end
567
+
568
+ Então, se isso acontecer:
569
+
570
+ get '/' do
571
+ raise MeuErroCustomizado, 'alguma coisa ruim'
572
+ end
573
+
574
+ Você receberá isso:
575
+
576
+ Então que aconteceu foi... alguma coisa ruim
577
+
578
+ Alternativamente, você pode instalar manipulador de erro para um código de status:
579
+
580
+ error 403 do
581
+ 'Accesso negado'
582
+ end
583
+
584
+ get '/secreto' do
585
+ 403
586
+ end
587
+
588
+ Ou um range:
589
+
590
+ error 400..510 do
591
+ 'Boom'
592
+ end
593
+
594
+ O Sinatra instala os manipuladores especiais <tt>not_found</tt> e <tt>error</tt> quando
595
+ roda sobre o ambiente de desenvolvimento.
596
+
597
+ == Mime Types
598
+
599
+ Quando utilizamos <tt>send_file</tt> ou arquivos estáticos você pode ter mime types Sinatra
600
+ não entendidos. Use +mime_type+ para registrar eles por extensão de arquivos:
601
+
602
+ mime_type :foo, 'text/foo'
603
+
604
+ Você também pode utilizar isto com o helper +content_type+:
605
+
606
+ content_type :foo
607
+
608
+ == Middleware Rack
609
+
610
+ O Sinatra roda no Rack[http://rack.rubyforge.org/], uma interface padrão
611
+ mínima para frameworks web em Ruby. Um das capacidades mais interessantes do Rack
612
+ para desenvolver aplicativos é suporte a "middleware" -- componentes que ficam
613
+ entre o servidor e sua aplicação monitorando e/ou manipulando o request/response do
614
+ HTTP para prover vários tipos de funcionalidades comuns.
615
+
616
+ O Sinatra faz construtores pipelines do middleware Rack facilmente em um nível superior
617
+ utilizando o método +use+:
618
+
619
+ require 'sinatra'
620
+ require 'meu_middleware_customizado'
621
+
622
+ use Rack::Lint
623
+ use MeuMiddlewareCustomizado
624
+
625
+ get '/ola' do
626
+ 'Olá mundo'
627
+ end
628
+
629
+ A semântica de +use+ é idêntica aquela definida para a DSL
630
+ Rack::Builder[http://rack.rubyforge.org/doc/classes/Rack/Builder.html]
631
+ (mais frequentemente utilizada para arquivos rackup). Por exemplo, o método +use+
632
+ aceita múltiplos argumentos/variáveis bem como blocos:
633
+
634
+ use Rack::Auth::Basic do |usuario, senha|
635
+ usuario == 'admin' && senha == 'secreto'
636
+ end
637
+
638
+ O Rack é distribuido com uma variedade de middleware padrões para logs,
639
+ debugs, rotas de URL, autenticação, e manipuladores de sessão. Sinatra utilizada
640
+ muitos desses componentes automaticamente baseando sobre configuração, então, tipicamente
641
+ você não tem +use+ explicitamente.
642
+
643
+ == Testando
644
+
645
+ Testes no Sinatra podem ser escritos utilizando qualquer biblioteca ou framework
646
+ de teste baseados no Rack. {Rack::Test}[http://gitrdoc.com/brynary/rack-test] é
647
+ recomendado:
648
+
649
+ require 'minha_aplicacao_sinatra'
650
+ require 'rack/test'
651
+
652
+ class MinhaAplicacaoTeste < Test::Unit::TestCase
653
+ include Rack::Test::Methods
654
+
655
+ def app
656
+ Sinatra::Application
657
+ end
658
+
659
+ def meu_test_default
660
+ get '/'
661
+ assert_equal 'Ola Mundo!', last_response.body
662
+ end
663
+
664
+ def teste_com_parametros
665
+ get '/atender', :name => 'Frank'
666
+ assert_equal 'Olá Frank!', last_response.bodymeet
667
+ end
668
+
669
+ def test_com_ambiente_rack
670
+ get '/', {}, 'HTTP_USER_AGENT' => 'Songbird'
671
+ assert_equal "Você está utilizando o Songbird!", last_response.body
672
+ end
673
+ end
674
+
675
+ NOTA: Os módulos de classe embutidos Sinatra::Test e Sinatra::TestHarness
676
+ são depreciados na versão 0.9.2.
677
+
678
+ == Sinatra::Base - Middleware, Bibliotecas e aplicativos modulares
679
+
680
+ Definir sua aplicação em um nível superior de trabalho funciona bem para micro aplicativos, mas tem
681
+ consideráveis incovenientes na construção de componentes reutilizáveis como um middleware Rack,
682
+ metal Rails, bibliotecas simples como um componente de servidor, ou
683
+ mesmo extensões Sinatra. A DSL de nível superior polui o espaço do objeto
684
+ e assume um estilo de configuração de micro aplicativos (exemplo: uma simples arquivo de
685
+ aplicação, diretórios ./public e ./views, logs, página de detalhes de exceção,
686
+ etc.). É onde o Sinatra::Base entra em jogo:
687
+
688
+ require 'sinatra/base'
689
+
690
+ class MinhaApp < Sinatra::Base
691
+ set :sessions, true
692
+ set :foo, 'bar'
693
+
694
+ get '/' do
695
+ 'Ola mundo!'
696
+ end
697
+ end
698
+
699
+ A classe MinhaApp é um componente Rack independente que pode agir como um
700
+ middleware Rack, uma aplicação Rack, ou metal Rails. Você pode +utilizar+ ou
701
+ +executar+ esta classe com um arquivo rackup +config.ru+; ou, controlar um componente
702
+ de servidor fornecendo como biblioteca:
703
+
704
+ MinhaApp.run! :host => 'localhost', :port => 9090
705
+
706
+ Os métodos disponíveis para subclasses Sinatra::Base são exatamente como aqueles
707
+ disponíveis via a DSL de nível superior. Aplicações de nível mais alto podem ser convertidas para
708
+ componentes Sinatra::Base com duas modificações:
709
+
710
+ * Seu arquivo deve requerer +sinatra/base+ ao invés de +sinatra+;
711
+ outra coisa, todos os métodos DSL do Sinatra são importados para o espaço
712
+ principal.
713
+ * Coloque as rotas da sua aplicação, manipuladores de erro, filtros e opções na subclasse de
714
+ um Sinatra::Base.
715
+
716
+ +Sinatra::Base+ é um quadro branco. Muitas opções são desabilitadas por padrão,
717
+ incluindo o servidor embutido. Veja {Opções e Configurações}[http://sinatra.github.com/configuration.html]
718
+ para detalhes de opções disponíveis e seus comportamentos.
719
+
720
+ SIDEBAR: A DSL de alto nível do Sinatra é implementada utilizando um simples sistema de
721
+ delegação. A classe +Sinatra::Application+ -- uma subclasse especial da
722
+ Sinatra::Base -- recebe todos os :get, :put, :post, :delete, :before,
723
+ :error, :not_found, :configure, e :set messages enviados para o
724
+ alto nível. Dê uma olhada no código você mesmo: aqui está o
725
+ {Sinatra::Delegator mixin}[http://github.com/sinatra/sinatra/blob/ceac46f0bc129a6e994a06100aa854f606fe5992/lib/sinatra/base.rb#L1128]
726
+ sendo {incluido dentro de um espaço principal}[http://github.com/sinatra/sinatra/blob/ceac46f0bc129a6e994a06100aa854f606fe5992/lib/sinatra/main.rb#L28]
727
+
728
+ == Linha de Comando
729
+
730
+ Aplicações Sinatra podem ser executadas diretamente:
731
+
732
+ ruby minhaapp.rb [-h] [-x] [-e AMBIENTE] [-p PORTA] [-o HOST] [-s SERVIDOR]
733
+
734
+ As opções são:
735
+
736
+ -h # ajuda
737
+ -p # define a porta (padrão é 4567)
738
+ -o # define o host (padrão é 0.0.0.0)
739
+ -e # define o ambiente (padrão é development)
740
+ -s # especifica o servidor/manipulador rack (padrão é thin)
741
+ -x # ativa o bloqueio (padrão é desligado)
742
+
743
+ == A última versão
744
+
745
+ Se você gostaria de utilizar o código da última versão do Sinatra, crie um clone
746
+ local e execute sua aplicação com o diretório <tt>sinatra/lib</tt> no
747
+ <tt>LOAD_PATH</tt>:
748
+
749
+ cd minhaapp
750
+ git clone git://github.com/sinatra/sinatra.git
751
+ ruby -I sinatra/lib minhaapp.rb
752
+
753
+ Alternativamente, você pode adicionar o diretório do <tt>sinatra/lib</tt> no
754
+ <tt>LOAD_PATH</tt> do seu aplicativo:
755
+
756
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/sinatra/lib'
757
+ require 'rubygems'
758
+ require 'sinatra'
759
+
760
+ get '/sobre' do
761
+ "Estou rodando a versão" + Sinatra::VERSION
762
+ end
763
+
764
+ Para atualizar o código do Sinatra no futuro:
765
+
766
+ cd meuprojeto/sinatra
767
+ git pull
768
+
769
+ == Mais
770
+
771
+ * {Website do Projeto}[http://www.sinatrarb.com/] - Documentação adicional,
772
+ novidades e links para outros recursos.
773
+ * {Contribuir}[http://www.sinatrarb.com/contributing] - Encontrar um bug? Precisa
774
+ de ajuda? Tem um patch?
775
+ * {Acompanhar Questões}[http://github.com/sinatra/sinatra/issues]
776
+ * {Twitter}[http://twitter.com/sinatra]
777
+ * {Lista de Email}[http://groups.google.com/group/sinatrarb/topics]
778
+ * {IRC: #sinatra}[irc://chat.freenode.net/#sinatra] em http://freenode.net