Permalink
Newer
Older
100644 648 lines (448 sloc) 17.2 KB
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 DSL para criar rapidamente aplicações web em Ruby com o mínimo de
5
esforço:
6
7
# minhaapp.rb
8
require 'rubygems'
9
require 'sinatra'
10
get '/' do
11
'Olá Mundo!'
12
end
13
14
Instale a gem e execute como:
15
16
sudo gem install sinatra
17
ruby minhaapp.rb
18
19
Acesse em: http://localhost:4567
20
21
== Rotas
22
23
No Sinatra, uma rota é um metodo HTTP associado a uma URL correspondente padrão.
24
Cada rota é associada a um bloco:
25
26
get '/' do
27
.. mostrando alguma coisa ..
28
end
29
30
post '/' do
31
.. criando alguma coisa ..
32
end
33
34
put '/' do
35
.. atualizando alguma coisa ..
36
end
37
38
delete '/' do
39
.. apagando alguma coisa ..
40
end
41
42
Rotas são encontradas na ordem em que são definidas. A primeira rota que
43
é encontrada invoca o pedido.
44
45
Padrões de rota podem incluir parâmetros nomeados, acessáveis via a
46
hash <tt>params</tt>:
47
48
get '/ola/:nome' do
49
# corresponde a "GET /ola/foo" e "GET /ola/bar"
50
# params[:nome] é 'foo' ou 'bar'
51
"Olá #{params[:nome]}!"
52
end
53
54
Você também pode acessar parâmetros nomeados via bloco de parâmetros:
55
56
get '/ola/:nome' do |n|
57
"Olá #{n}!"
58
end
59
60
Padrões de rota também podem incluir parâmetros splat (ou curingas), acessáveis
61
via o array <tt>params[:splat]</tt>.
62
63
get '/diga/*/para/*' do
64
# corresponde a /diga/ola/para/mundo
65
params[:splat] # => ["ola", "mundo"]
66
end
67
68
get '/download/*.*' do
69
# corresponde a /download/pasta/do/arquivo.xml
70
params[:splat] # => ["pasta/do/arquivo", "xml"]
71
end
72
73
Rotas se correspondem com expressões regulares:
74
75
get %r{/ola/([\w]+)} do
76
"Olá, #{params[:captures].first}!"
77
end
78
79
Ou com um bloco de parâmetro:
80
81
get %r{/ola/([\w]+)} do |c|
82
"Hello, #{c}!"
83
end
84
85
Rotas podem incluir uma variedade de condições correspondes, tal como o agente usuário:
86
87
get '/foo', :agent => /Songbird (\d\.\d)[\d\/]*?/ do
88
"Você está utilizando a versão #{params[:agent][0]} do Songbird."
89
end
90
91
get '/foo' do
92
# Corresponde a um navegador não Songbird
93
end
94
95
== Arquivos estáticos
96
97
Arquivos estáticos são disponibilizados a partir do diretório <tt>./public</tt>. Você pode especificar
98
um local diferente pela opção <tt>:public_folder</tt>
100
set :public_folder, File.dirname(__FILE__) + '/estatico'
101
102
Note que o nome do diretório público não é incluido na URL. Um arquivo
103
<tt>./public/css/style.css</tt> é disponibilizado como
104
<tt>http://example.com/css/style.css</tt>.
105
106
== Views / Templates
107
108
Templates presumem-se estar localizados sob o diretório <tt>./views</tt>.
109
Para utilizar um diretório view diferente:
110
111
set :views, File.dirname(__FILE__) + '/modelo'
112
113
Uma coisa importante a ser lembrada é que você sempre tem as referências dos
114
templates como símbolos, mesmo se eles estiverem em um sub-diretório (nesse
115
caso utilize <tt>:'subdir/template'</tt>). Métodos de renderização irão processar
116
qualquer string passada diretamente para elas.
117
118
=== Haml Templates
119
120
A gem/biblioteca haml é necessária para renderizar templates HAML:
121
122
# Você precisa do 'require haml' em sua aplicação.
123
require 'haml'
124
125
get '/' do
126
haml :index
127
end
128
129
Renderiza <tt>./views/index.haml</tt>.
130
131
{Opções Haml}[http://haml-lang.com/docs/yardoc/file.HAML_REFERENCE.html#options]
132
podem ser setadas globalmente através das configurações do sinatra,
133
veja {Opções e Configurações}[http://www.sinatrarb.com/configuration.html],
134
e substitua em uma requisição individual.
135
136
set :haml, {:format => :html5 } # o formato padrão do Haml é :xhtml
137
138
get '/' do
139
haml :index, :haml_options => {:format => :html4 } # substituido
140
end
141
142
143
=== Erb Templates
144
145
# Você precisa do 'require erb' em sua aplicação
146
require 'erb'
147
148
get '/' do
149
erb :index
150
end
151
152
Renderiza <tt>./views/index.erb</tt>
153
154
=== Erubis
155
156
A gem/biblioteca erubis é necessária para renderizar templates erubis:
157
158
# Você precisa do 'require erubis' em sua aplicação.
159
require 'erubis'
160
161
get '/' do
162
erubis :index
163
end
164
165
Renderiza <tt>./views/index.erubis</tt>
166
167
=== Builder Templates
168
169
A gem/biblioteca builder é necessária para renderizar templates builder:
170
171
# Você precisa do 'require builder' em sua aplicação.
172
require 'builder'
173
174
get '/' do
175
content_type 'application/xml', :charset => 'utf-8'
176
builder :index
177
end
178
179
Renderiza <tt>./views/index.builder</tt>.
180
181
=== Sass Templates
182
183
A gem/biblioteca sass é necessária para renderizar templates sass:
184
185
# Você precisa do 'require haml' ou 'require sass' em sua aplicação.
186
require 'sass'
187
188
get '/stylesheet.css' do
189
content_type 'text/css', :charset => 'utf-8'
190
sass :stylesheet
191
end
192
193
Renderiza <tt>./views/stylesheet.sass</tt>.
194
195
{Opções Sass}[http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#options]
196
podem ser setadas globalmente através das configurações do sinatra,
197
veja {Opções e Configurações}[http://www.sinatrarb.com/configuration.html],
198
e substitua em uma requisição individual.
199
200
set :sass, {:style => :compact } # o estilo padrão do Sass é :nested
201
202
get '/stylesheet.css' do
203
content_type 'text/css', :charset => 'utf-8'
204
sass :stylesheet, :style => :expanded # substituido
205
end
206
207
=== Less Templates
208
209
A gem/biblioteca less é necessária para renderizar templates Less:
210
211
# Você precisa do 'require less' em sua aplicação.
212
require 'less'
213
214
get '/stylesheet.css' do
215
content_type 'text/css', :charset => 'utf-8'
216
less :stylesheet
217
end
218
219
Renderiza <tt>./views/stylesheet.less</tt>.
220
221
=== Inline Templates
222
223
get '/' do
224
haml '%div.title Olá Mundo'
225
end
226
227
Renderiza a string, em uma linha, no template.
228
229
=== Acessando Variáveis nos Templates
230
231
Templates são avaliados dentro do mesmo contexto como manipuladores de rota. Variáveis
232
de instância setadas em rotas manipuladas são diretamente acessadas por templates:
233
234
get '/:id' do
235
@foo = Foo.find(params[:id])
236
haml '%h1= @foo.nome'
237
end
238
239
Ou, especifique um hash explícito para variáveis locais:
240
241
get '/:id' do
242
foo = Foo.find(params[:id])
243
haml '%h1= foo.nome', :locals => { :foo => foo }
244
end
245
246
Isso é tipicamente utilizando quando renderizamos templates como partials dentro
247
de outros templates.
248
249
=== Templates Inline
250
251
Templates podem ser definidos no final do arquivo fonte(.rb):
252
253
require 'rubygems'
254
require 'sinatra'
255
256
get '/' do
257
haml :index
258
end
259
260
__END__
261
262
@@ layout
263
%html
264
= yield
265
266
@@ index
267
%div.title Olá Mundo!!!!!
268
269
NOTA: Templates inline definidos no arquivo fonte são automaticamente carregados
270
pelo sinatra. Digite `enable :inline_templates` se você tem templates
271
inline no outro arquivo fonte.
272
273
=== Templates nomeados
274
275
Templates também podem ser definidos utilizando o método top-level <tt>template</tt>:
276
277
template :layout do
278
"%html\n =yield\n"
279
end
280
281
template :index do
282
'%div.title Olá Mundo!'
283
end
284
285
get '/' do
286
haml :index
287
end
288
289
Se existir um template com nome "layout", ele será utilizado toda vez que um
290
template for renderizado. Você pode desabilitar layouts passando <tt>:layout => false</tt>.
291
292
get '/' do
293
haml :index, :layout => !request.xhr?
294
end
295
296
== Helpers
297
298
Use o método de alto nível <tt>helpers</tt> para definir métodos auxiliares para utilizar em
299
manipuladores de rotas e modelos:
300
301
helpers do
302
def bar(nome)
303
"#{nome}bar"
304
end
305
end
306
307
get '/:nome' do
308
bar(params[:nome])
309
end
310
311
== Filtros
312
313
Filtros Before são avaliados antes de cada requisição dentro do contexto da requisição
314
e pode modificar a requisição e a reposta. Variáveis de instância setadas nos
315
filtros são acessadas através de rotas e templates:
316
317
before do
318
@nota = 'Oi!'
319
request.path_info = '/foo/bar/baz'
320
end
321
322
get '/foo/*' do
323
@nota #=> 'Oi!'
324
params[:splat] #=> 'bar/baz'
325
end
326
327
Filtros After são avaliados após cada requisição dentro do contexto da
328
requisição e também podem modificar o pedido e a resposta. Variáveis de instância
329
definidas nos filtros before e rotas são acessadas através dos filtros after:
330
331
after do
332
puts response.status
333
end
334
335
Filtros opcionalmente tem um padrão, fazendo com que sejam avaliados somente se o caminho
336
do pedido coincidir com esse padrão:
337
338
before '/protected/*' do
339
authenticate!
340
end
341
342
after '/create/:slug' do |slug|
343
session[:last_slug] = slug
344
end
345
346
== Halting
347
348
Para parar imediatamente uma requisição com um filtro ou rota utilize:
349
350
halt
351
352
Você também pode especificar o status quando parar...
353
354
halt 410
355
356
Ou com corpo de texto...
357
358
halt 'isso será o corpo do texto'
359
360
Ou também...
361
362
halt 401, 'vamos embora!'
363
364
Com cabeçalhos...
365
366
halt 402, {'Content-Type' => 'text/plain'}, 'revanche'
367
368
== Passing
369
370
Uma rota pode processar aposta para a próxima rota correspondente usando <tt>pass</tt>:
371
372
get '/adivinhar/:quem' do
373
pass unless params[:quem] == 'Frank'
374
'Você me pegou!'
375
end
376
377
get '/adivinhar/*' do
378
'Você falhou!'
379
end
380
381
O bloqueio da rota é imediatamente encerrado e o controle continua com a próxima
382
rota de parâmetro. Se o parâmetro da rota não for encontrado, um 404 é retornado.
383
384
== Configuração
385
386
Rodando uma vez, na inicialização, em qualquer ambiente:
387
388
configure do
389
...
390
end
391
392
Rodando somente quando o ambiente (RACK_ENV environment variável) é setado para
393
<tt>:production</tt>:
394
395
configure :production do
396
...
397
end
398
399
Rodando quando o ambiente é setado para <tt>:production</tt> ou
400
<tt>:test</tt>:
401
402
configure :production, :test do
403
...
404
end
405
406
== Tratamento de Erros
407
408
Tratamento de erros rodam dentro do mesmo contexto como rotas e filtros before, o
409
que significa que você pega todos os presentes que tem para oferecer, como <tt>haml</tt>, <tt>erb</tt>,
410
<tt>halt</tt>, etc.
411
412
=== Não Encontrado
413
414
Quando um <tt>Sinatra::NotFound</tt> exception é levantado, ou o código de status
415
da reposta é 404, o <tt>not_found</tt> manipulador é invocado:
416
417
not_found do
418
'Isto está longe de ser encontrado'
419
end
420
421
=== Erro
422
423
O manipulador +error+ é invocado toda a vez que uma exceção é lançada a partir de
424
um bloco de rota ou um filtro. O objeto da exceção pode ser obtido a partir da variável
425
Rack <tt>sinatra.error</tt>:
426
427
error do
428
'Desculpe, houve um erro desagradável - ' + env['sinatra.error'].name
429
end
430
431
Erros customizados:
432
433
error MeuErroCustomizado do
434
'Então que aconteceu foi...' + env['sinatra.error'].message
435
end
436
437
Então, se isso acontecer:
438
439
get '/' do
440
raise MeuErroCustomizado, 'alguma coisa ruim'
441
end
442
443
Você receberá isso:
444
445
Então que aconteceu foi... alguma coisa ruim
446
447
Alternativamente, você pode instalar manipulador de erro para um código de status:
448
449
error 403 do
450
'Accesso negado'
451
end
452
453
get '/secreto' do
454
403
455
end
456
457
Ou um range:
458
459
error 400..510 do
460
'Boom'
461
end
462
463
O Sinatra instala os manipuladores especiais <tt>not_found</tt> e <tt>error</tt> quando
464
roda sobre o ambiente de desenvolvimento.
465
466
== Mime Types
467
468
Quando utilizamos <tt>send_file</tt> ou arquivos estáticos você pode ter mime types Sinatra
469
não entendidos. Use +mime_type+ para registrar eles por extensão de arquivos:
470
471
mime_type :foo, 'text/foo'
472
473
Você também pode utilizar isto com o helper +content_type+:
474
475
content_type :foo
476
477
== Middleware Rack
478
479
O Sinatra roda no Rack[http://rack.rubyforge.org/], uma interface padrão
480
mínima para frameworks web em Ruby. Um das capacidades mais interessantes do Rack
481
para desenvolver aplicativos é suporte a "middleware" -- componentes que ficam
482
entre o servidor e sua aplicação monitorando e/ou manipulando o request/response do
483
HTTP para prover vários tipos de funcionalidades comuns.
484
485
O Sinatra faz construtores pipelines do middleware Rack facilmente em um nível superior
486
utilizando o método +use+:
487
488
require 'sinatra'
489
require 'meu_middleware_customizado'
490
491
use Rack::Lint
492
use MeuMiddlewareCustomizado
493
494
get '/ola' do
495
'Olá mundo'
496
end
497
498
A semântica de +use+ é idêntica aquela definida para a DSL
499
Rack::Builder[http://rack.rubyforge.org/doc/classes/Rack/Builder.html]
500
(mais frequentemente utilizada para arquivos rackup). Por exemplo, o método +use+
501
aceita múltiplos argumentos/variáveis bem como blocos:
502
503
use Rack::Auth::Basic do |usuario, senha|
504
usuario == 'admin' && senha == 'secreto'
505
end
506
507
O Rack é distribuido com uma variedade de middleware padrões para logs,
508
debugs, rotas de URL, autenticação, e manipuladores de sessão. Sinatra utilizada
509
muitos desses componentes automaticamente baseando sobre configuração, então, tipicamente
510
você não tem +use+ explicitamente.
511
512
== Testando
513
514
Testes no Sinatra podem ser escritos utilizando qualquer biblioteca ou framework
515
de teste baseados no Rack. {Rack::Test}[http://gitrdoc.com/brynary/rack-test] é
516
recomendado:
517
518
require 'minha_aplicacao_sinatra'
519
require 'rack/test'
520
521
class MinhaAplicacaoTeste < Test::Unit::TestCase
522
include Rack::Test::Methods
523
524
def app
525
Sinatra::Application
526
end
527
528
def meu_test_default
529
get '/'
530
assert_equal 'Ola Mundo!', last_response.body
531
end
532
533
def teste_com_parametros
534
get '/atender', :name => 'Frank'
535
assert_equal 'Olá Frank!', last_response.bodymeet
536
end
537
538
def test_com_ambiente_rack
539
get '/', {}, 'HTTP_USER_AGENT' => 'Songbird'
540
assert_equal "Você está utilizando o Songbird!", last_response.body
541
end
542
end
543
544
NOTA: Os módulos de classe embutidos Sinatra::Test e Sinatra::TestHarness
545
são depreciados na versão 0.9.2.
546
547
== Sinatra::Base - Middleware, Bibliotecas e aplicativos modulares
548
549
Definir sua aplicação em um nível superior de trabalho funciona bem para micro aplicativos, mas tem
550
consideráveis incovenientes na construção de componentes reutilizáveis como um middleware Rack,
551
metal Rails, bibliotecas simples como um componente de servidor, ou
552
mesmo extensões Sinatra. A DSL de nível superior polui o espaço do objeto
553
e assume um estilo de configuração de micro aplicativos (exemplo: uma simples arquivo de
554
aplicação, diretórios ./public e ./views, logs, página de detalhes de exceção,
555
etc.). É onde o Sinatra::Base entra em jogo:
556
557
require 'sinatra/base'
558
559
class MinhaApp < Sinatra::Base
560
set :sessions, true
561
set :foo, 'bar'
562
563
get '/' do
564
'Ola mundo!'
565
end
566
end
567
568
A classe MinhaApp é um componente Rack independente que pode agir como um
569
middleware Rack, uma aplicação Rack, ou metal Rails. Você pode +utilizar+ ou
570
+executar+ esta classe com um arquivo rackup +config.ru+; ou, controlar um componente
571
de servidor fornecendo como biblioteca:
572
573
MinhaApp.run! :host => 'localhost', :port => 9090
574
575
Os métodos disponíveis para subclasses Sinatra::Base são exatamente como aqueles
576
disponíveis via a DSL de nível superior. Aplicações de nível mais alto podem ser convertidas para
577
componentes Sinatra::Base com duas modificações:
578
579
* Seu arquivo deve requerer +sinatra/base+ ao invés de +sinatra+;
580
outra coisa, todos os métodos DSL do Sinatra são importados para o espaço
581
principal.
582
* Coloque as rotas da sua aplicação, manipuladores de erro, filtros e opções na subclasse de
583
um Sinatra::Base.
584
585
+Sinatra::Base+ é um quadro branco. Muitas opções são desabilitadas por padrão,
586
incluindo o servidor embutido. Veja {Opções e Configurações}[http://sinatra.github.com/configuration.html]
587
para detalhes de opções disponíveis e seus comportamentos.
588
589
SIDEBAR: A DSL de alto nível do Sinatra é implementada utilizando um simples sistema de
590
delegação. A classe +Sinatra::Application+ -- uma subclasse especial da
591
Sinatra::Base -- recebe todos os :get, :put, :post, :delete, :before,
592
:error, :not_found, :configure, e :set messages enviados para o
593
alto nível. Dê uma olhada no código você mesmo: aqui está o
594
{Sinatra::Delegator mixin}[http://github.com/sinatra/sinatra/blob/ceac46f0bc129a6e994a06100aa854f606fe5992/lib/sinatra/base.rb#L1128]
595
sendo {incluido dentro de um espaço principal}[http://github.com/sinatra/sinatra/blob/ceac46f0bc129a6e994a06100aa854f606fe5992/lib/sinatra/main.rb#L28]
596
597
== Linha de Comando
598
599
Aplicações Sinatra podem ser executadas diretamente:
600
601
ruby minhaapp.rb [-h] [-x] [-e AMBIENTE] [-p PORTA] [-o HOST] [-s SERVIDOR]
602
603
As opções são:
604
605
-h # ajuda
606
-p # define a porta (padrão é 4567)
607
-o # define o host (padrão é 0.0.0.0)
608
-e # define o ambiente (padrão é development)
609
-s # especifica o servidor/manipulador rack (padrão é thin)
610
-x # ativa o bloqueio (padrão é desligado)
611
612
== A última versão
613
614
Se você gostaria de utilizar o código da última versão do Sinatra, crie um clone
615
local e execute sua aplicação com o diretório <tt>sinatra/lib</tt> no
616
<tt>LOAD_PATH</tt>:
617
618
cd minhaapp
619
git clone git://github.com/sinatra/sinatra.git
620
ruby -I sinatra/lib minhaapp.rb
621
622
Alternativamente, você pode adicionar o diretório do <tt>sinatra/lib</tt> no
623
<tt>LOAD_PATH</tt> do seu aplicativo:
624
625
$LOAD_PATH.unshift File.dirname(__FILE__) + '/sinatra/lib'
626
require 'rubygems'
627
require 'sinatra'
628
629
get '/sobre' do
630
"Estou rodando a versão" + Sinatra::VERSION
631
end
632
633
Para atualizar o código do Sinatra no futuro:
634
635
cd meuprojeto/sinatra
636
git pull
637
638
== Mais
639
640
* {Website do Projeto}[http://www.sinatrarb.com/] - Documentação adicional,
641
novidades e links para outros recursos.
642
* {Contribuir}[http://www.sinatrarb.com/contributing] - Encontrar um bug? Precisa
643
de ajuda? Tem um patch?
644
* {Acompanhar Questões}[http://github.com/sinatra/sinatra/issues]
645
* {Twitter}[http://twitter.com/sinatra]
646
* {Lista de Email}[http://groups.google.com/group/sinatrarb/topics]
647
* {IRC: #sinatra}[irc://chat.freenode.net/#sinatra] em http://freenode.net