Roteamento

O que é roteamento

No Sinatra, roteamento é como seu aplicativo responde às solicitações, pelo caminho da solicitação (por exemplo, /welcome) e pelo verbo HTTP usado (por exemplo, GET ou POST). A maneira como uma solicitação é escrita é a seguinte:

<http-verb> <path> do
    <code block to execute when this route is requested>
end

Aqui está um exemplo que responde a solicitações GET para o caminho /hello retornando uma página que diz “Hi, whats up”:

get "/hello" do
    return "Hi, whats up"
end

O Sinatra só responde às rotas que você definir. Se você não definir uma rota, o Sinatra retornará uma página de erro 404 Page Not Found.

O Sinatra responde às rotas na ordem em que são definidas. Se você tiver várias rotas que podem corresponder a uma determinada solicitação (consulte “Correspondência de caminho baseada em Regexp”), a primeira rota que se encaixa na solicitação é retornada.

OBSERVAÇÃO: Sinatra trata rotas com e sem barra (/) como 2 rotas diferentes e distintas. Ou seja, get '/hello' e get '/hello/' por padrão correspondem a diferentes blocos de código. Se você quiser ignorar a barra à direita e tratar ambas as rotas como a mesma, você pode adicionar ? após a barra para torná-la opcional, assim: get '/hello/?'. Isso usa a capacidade do Sinatra de usar expressões regulares para correspondência de rotas (mais sobre isso abaixo).

Verbos de roteamento Sinatra disponíveis

Existem vários verbos de roteamento disponíveis no Sinatra, eles correspondem diretamente aos verbos http

get '/' do
  .. get some data, a view, json, etc ..
end

post '/' do
  .. create a resource ..
end

put '/' do
  .. replace a resource ..
end

patch '/' do
  .. change a resource ..
end

delete '/' do
  .. delete something ..
end

options '/' do
  .. appease something ..
end

link '/' do
  .. affiliate something ..
end

unlink '/' do
  .. separate something ..
end

Correspondência de caminho baseada em Regexp

Ao combinar o caminho de uma rota, você pode fazer isso explicitamente, correspondendo apenas a um caminho, assim:

get "/hello" do
    return "Hello!"
end

Você também pode usar uma expressão regular para corresponder a rotas complexas. Qualquer rota que corresponda à expressão regular executará esse bloco de código. Se várias rotas puderem corresponder à solicitação, a primeira rota correspondente será executada.

Aqui está um exemplo típico de uma rota que corresponde a caminhos que incluem /user/ seguido por um ou mais dígitos (presumivelmente, IDs de usuário), ou seja, GET /user/1:

get /\/user\/\d+/ do
  "Hello, user!"
end

O exemplo acima corresponde a /user/1, mas também corresponde a /delete/user/1 e /user/1/delete/now, já que nossa expressão regular não é muito restritiva e permite uma correspondência parcial com qualquer parte do caminho.

Podemos ser mais explícitos com o regexp e dizer a ele para corresponder exatamente à rota, usando as diretivas \A e \z para ancorar a correspondência no início e no final do caminho:

get /\A\/user\/\d+\z/ do
  "Hello, user!"
end

Esta rota não corresponderá a /delete/user/1 ou /user/1/delete/now devido à ancoragem de correspondência.

Ignorando à direita /

Nossa rota de exemplo acima também não corresponderá a /user/1/ (com barra à direita). Se você quiser ignorar a barra final no final da rota, ajuste o regexp para tornar a barra opcional (observe o \/? no final):

get /\A\/user\/\d+\/?\z/ do
  "Hello, user! You may have navigated to /user/<ID> or /user/<ID>/ to get here."
end

Capturando correspondências de rota

Até agora, combinamos com rotas regexp, mas e se quisermos usar os valores correspondentes em nosso bloco de código? Dando continuidade ao nosso exemplo, como sabemos qual é o ID do usuário quando a rota é executada?

Podemos capturar a parte desejada do caminho e usar a variável param[:captures] do Sinatra para trabalhar com os dados dentro da rota:

get /\A\/user\/(\d+)\/?\z/ do
  "Hello, user! Your ID is #{params['captures'].first}!"
end

Parâmetros da Rota Sinatra

Claro que você pode passar dados para rotas Sinatra, para aceitar dados em suas rotas você pode adicionar parâmetros de rota. Você pode então acessar um hash de parâmetros:

get '/hello/:name' do
  # matches "GET /hello/foo" and "GET /hello/bar"
  # params['name'] is 'foo' or 'bar'
  "Hello #{params['name']}!"
end

Você também pode atribuir parâmetros diretamente a variáveis ​​como costumamos fazer em hashes Ruby:

get '/hello/:name' do |n|
  # matches "GET /hello/foo" and "GET /hello/bar"
  # params['name'] is 'foo' or 'bar'
  # n stores params['name']
  "Hello #{n}!"
end

Você também pode adicionar parâmetros curinga sem nomes específicos usando asteriscos. Eles podem ser acessados ​​usando params[‘splat’]:

get '/say/*/to/*' do
  # matches /say/hello/to/world
  params['splat'] # => ["hello", "world"]
end